Quick link: Oracle Java 19 Docs
Line wrapping for if statements should generally use the 8-space rule, since conventional (4 space) indentation makes seeing the body difficult. For example:
//USE THIS INDENTATION INSTEAD
if ((condition1 && condition2)
|| (condition3 && condition4)
||!(condition5 && condition6)) {
doSomethingAboutIt();
}
Source: Oracle Code Conventions
- File:
<Class>.java
- Class: capitalised
- Method: lowercase camelcase
Example:
int i = 10;
return i > 0 ? true : false; // positive and negative evaluation
int val1 = 10;
int val2 = 20;
int max = val1 >= val2 ? val1 : val2; // max calculation
Source: Jenkov.com
espresso@FVFG31YLQ05P POP2_Programming % cd probs02-dist
espresso@FVFG31YLQ05P probs02-dist % java CountWords.java test.txt output.txt
test.txt
output.txt
Source: Stack Exchange
Instructions like the below are easier on IntelliJ and require a couple manual settings on VS Code.
Write a program that reads all words in a file (specified as the first argument) and prints out, for each word, the line numbers on which the word occurred. This output should also be written to a second file (specified as the second argument). By the arguments, we refer to the strings in the array
String[] args
that is passed to the main method.
You can set args
in a launch.json
file.
To create a file, you can follow simple instruction in VS Code debugging.
The setting is:
args
- The command-line arguments passed to the program. Use"${command:SpecifyProgramArgs}"
to prompt for program arguments. It accepts a string or an array of string.
Source: Launch
Example:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Launch Current File",
"request": "launch",
"mainClass": "${file}",
"args": ["test.text", "output.txt"]
// "args": "${command:SpecifyProgramArgs}"
/*
To prompt for program arguments. It accepts a string or an array of string.
Source: https://code.visualstudio.com/docs/java/java-debugging#_configuration-options
*/
},
{
"type": "java",
"name": "Launch CountWords",
"request": "launch",
"mainClass": "CountWords",
"projectName": "POP2_Programming_b4a0f6be"
}
]
}
for (1. initialise; 2. if condition; 4. then iterate) {
// 3. do statement
}
- initialises variable (can be initialised elsewhere)
- checks condition
- executes statements
- iteration
Source: POP2 Session 1
The continue
statement breaks one iteration (in the loop), if a specified condition occurs, and continues with the next iteration in the loop.
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
if (i == 4) {
continue;
}
System.out.println(i);
}
}
}
// Output
0
1
2
3
5
6
7
8
9
Source: W3School
The break
statement completely jumps out of a loop.
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
if (i == 4) {
break;
}
System.out.println(i);
}
}
}
// Output
0
1
2
3
Source: W3School
// for each
for (<type> <name> : arr) {
// make use of <name> variable;
}
// equivalent to normal for loop
for (int i = 0; i < arr.length; i++) {
<type> <name> = arr[i];
// make use of <name> variable;;
}
// Example
public static int maximum(int[] numbers){
// defines variable
int max = numbers[0];
// for each iteration
for (int num : numbers){
if (num > max) {
max = num;
}
}
return max;
Limitation:
- Not appropriate when you want to modify the array
for (int num : marks) {
// only changes num, not the array element
num = num*2;
}
- Only iterates forward over the array in single steps
Source: Geekforgeeks
- The
default
keyword specifies some code to run if there is no case match - When Java reaches a
break
keyword, it breaks out of the switch block. This will stop the execution of more code and case testing inside the block.
int day = 4;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
}
// Outputs "Thursday" (day 4)
Source: W3School
From POP2:
Generic code is code that is parameterized by a type parameter
For example, an ArrayList is a generic class which takes a type argument To declare an ArrayList, we write e.g.
ArrayList<String> list;
orArrayList<Integer> list
; An ArrayList supports various operations (add
,remove
,size
, ...) 👉 Behavior is independent of the types of the objects held in the list
Example:
// Generic class: "GenericOne"
public class GenericOne<T> {
// attribute
T obj;
// constructor
GenericOne( T o ) {
obj = o;
}
// method
void printType() {
System.out.println( "obj has type: " +
obj.getClass().getName());
}
// other methods
// ...
}
public static void main(String[] args) {
// instances of generic class
GenericOne<String> a = new GenericOne<String>("Joe");
GenericOne<Integer> b = new GenericOne<Integer>(89);
// method calls
a.printType()
b.printType()
}
// Output
obj has type: java.lang.String
obj has type: java.lang.Integer
Source: POP2, credit Hubie Chen
Motivation: We can't call the .convertToInt()
method (below) on arbitrary instances of type T
because the operation is only supported on numeric classes in Java (i.e. within superclass Number
). We get a compile error:
| Error:
| cannot find symbol
| symbol: method intValue()
| return num.intValue();
So we restrict T
to only support numeric classes, i.e. subclasses of Number
.
public class SomeGenericClass<T extends Numeric>
From POP2:
This mandates that T can only be instantiated by subclasses of
Number
extends
allows us to specify an upper boundsuper
allows us to specify a lower bound
From Stack Overflow:
I have an
X
in my hand. If I want to write myX
into aList
, thatList
needs to be either aList
ofX
or aList
of things that myX
can be upcast to as I write them in i.e. any superclass of X...List<? super X>If I get a
List
and I want to read anX
out of thatList
, that better be aList
ofX
or aList
of things that can be upcast toX
as I read them out, i.e. anything that extends XList<? extends X>
// public class Multiplier<T> { // <-- Doesn't work
public class Multiplier<T extends Number> {
// attribute
T num;
// constructor
Multiplier( T num ) {
this.num = num;
}
// getter method
T getNum() {
return num;
}
// method
int convertToInt() {
return num.intValue();
}
// other methods
// ...
}
General form of method declaration:
// Form: <type parameters> return_type name(parameters)
// Example 1
<T> void doSomething(T obj) {
// ...
}
// Example 2
<T, V extends T> boolean compareArrays(T[] a, V[] b) {
// ...
}
Here the type U
is not used explicitly in the method body, so we can simply replace it with ?
.
// Redundant use of `U`
<U extends Number> boolean absEqual(Reciprocate<U> o) {
return( Math.abs( num.doubleValue() )
== Math.abs( o.getNum().doubleValue() ) );
}
// Replace with wildcard `?` instead
boolean absEqual(Reciprocate<? extends Number> o) {
return( Math.abs( num.doubleValue() )
== Math.abs( o.getNum().doubleValue() ) );
}
From POP2 (briefly):
// interface definition
interface Containment<T> {
boolean contains( T obj );
}
// Implementation 1
class AClass<T> implements Containment<T> { // OK
// ...
}
// Implementation 2
class AClass implements Containment<T> { // not OK class
// ...
}
// Implementation 3
AClass implements Containment<Integer> { // OK
// ...
}
// Implementation 4
class AClass<T extends Number> implements Containment<T> { // OK
// ...
}
// Implementation 4
class AClass<T extends Number> implements Containment<T extends Number> { // not OK
// ...
}
From W3School:
A lambda expression is a short block of code which takes in parameters and returns a value.
Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
Source: W3School
The simplest lambda expression contains a single parameter
and an expression
:
parameter -> expression
Expressions
are limited. They have to immediately return a value, and they cannot contain variables, assignments or statements such as if
or for
.
To use more than one parameter, wrap them in parentheses:
(parameter1, parameter2) -> expression
To do more complex operations, a code block can be used with curly braces. If the lambda expression needs to return a value, then the code block should have a return statement.
(parameter1, parameter2) -> { code block }
Example:
// Some ArrayList instance:
// e.g. ArrayList<String> lst = ArrayList<String>();
lst.removeIf( s -> lst.indexOf(s) % 2 == 0);
From POP2:
A lambda expression:
- is an anonymous, unnamed method in Java
- often used to implement a method defined by a functional interface
A functional interface:
- is an interface that contains exactly one abstract method
- E.g. the interface
Runnable
is a functional interface; it defines just one method,run()
, which is abstract - A functional interface can be used to define a target type for a lambda expression
interface MyValue
{
double getValue();
}
interface IntTest
{
boolean test( int a, int b );
}
public class LambdaDemo {
public static void main(String[] args) {
MyValue myVal;
myVal = () -> 98.6;
System.out.println( "A constant value: " + myVal.getValue());
IntTest isFactor;
isFactor = (d, n) -> (n % d) == 0;
if( isFactor.test( 2, 10 ))
{
System.out.println( "2 is a factor of 10." );
}
IntTest lessThan = (n, m) -> (n < m);
if( lessThan.test( 2, 10 ))
{
System.out.println( "2 is less than 10." );
}
// example of block lambda
// lambda returns true if d is the smallest factor of n
// which is strictly greater than 1
IntTest isSmallestFactor = (d, n) -> {
if( d <= 1 ) return false;
if( !isFactor.test( d, n )) return false;
for( int i = 2; i < d; i++ )
{
if( isFactor.test( i, n )) return false;
}
return true;
};
for( int i = 0; i <= 9; i++ )
{
System.out.println( "isSmallestFactor.test on " + i + ",9: " +
isSmallestFactor.test( i, 9 ));
}
}
}
Source: POP2, credit Hubie Chen
java.util.function
has several predefined functional interfacesUnaryOperator<T>
- defines method apply which applies a unary operation to an object of type T and returns the result (of type T)BinaryOperator<T>
- similar to previous interface, but for applying an operation to two objectsConsumer<T>
- defines methodaccept();
applies an operation to an object of type TPredicate<T>
- defines method test which applies an operation to an object of type T and returns a boolean value
From java.util.function
:
There are several basic function shapes, including:
Function
(unary function fromT
toR
),Consumer
(unary function fromT
tovoid
),Predicate
(unary function fromT
toboolean
), andSupplier
(nullary function toR
).Function shapes have a natural arity based on how they are most commonly used. The basic shapes can be modified by an arity prefix to indicate a different arity, such as:
BiFunction
(binary function fromT
andU
toR
).There are additional derived function shapes which extend the basic function shapes, including:
UnaryOperator
(extendsFunction
), andBinaryOperator
(extendsBiFunction
).
See more at section java.util.function
(down).
import java.util.function.*;
public class PredefinedDemo {
public static void main(String[] args) {
BinaryOperator<Integer> mult = (a, b) -> a * b;
Consumer<Integer> printer = (a) -> System.out.println( a );
for( int i = 0; i <= 5; i++ ) {
printer.accept( mult.apply( i, 3 ));
}
Predicate<Integer> isEven = (n) -> (n % 2) == 0;
for( int i = 0; i <= 5; i++ ) {
System.out.println( isEven.test( mult.apply( i, 3 )));
}
}
}
Source: POP2, credit Hubie Chen
Variables defined in the scope enclosing a lambda expression can be used inside the lambda expression
Only local variables that are “effectively final” can be so used.
interface IntFunc {
int func( int n );
}
public class VariableCapture {
public static void main(String[] args) {
int num = 10;
// can't modify num here
IntFunc lambda = (n) -> {
// can't modify num here
int v = num + n;
return v;
};
System.out.println( lambda.func( 8 ));
lambda = getAdder( 100 );
System.out.println( lambda.func( 8 ));
}
public static IntFunc getAdder( int a ) {
IntFunc lambda = (n) -> { return n + a; };
return lambda;
}
}
Source: POP2, credit Hubie Chen
From POP2:
A lambda expression can throw an exception.
If it throws a checked exception, the functional interface must declare that the abstract method throws it
import java.io.*;
interface IOAction
{
boolean ioAction( Reader rdr ) throws IOException;
}
// recall that Reader is an abstract class for dealing with character streams
public class LambdaException {
public static void main(String[] args) {
IOAction action = (r) -> {
int ch = r.read();
return true;
};
}
}
Source: POP2, credit Hubie Chen
A method reference provides a way to refer to a method without executing it. A method reference (when evaluated) provides an instance of a functional interface
Kind | Syntax | Examples |
---|---|---|
Reference to a static method | ContainingClass::staticMethodName |
Person::compareByAge MethodReferencesExamples::appendStrings |
Reference to an instance method of a particular object | containingObject::instanceMethodName |
myComparisonProvider::compareByName myApp::appendStrings2 |
Reference to an instance method of an arbitrary object of a particular type | ContainingType::methodName |
String::compareToIgnoreCase String::concat |
Reference to a constructor | ClassName::new |
HashSet::new |
Syntax:
- Reference to a static method:
ClassName::methodName
- Reference to an instance method of an object:
objectReference::methodName
- Reference to a constructor:
Classname::new
If we have:
interface MyFunc {
MyClass func( String s );
}
and we have that class MyClass
has a corresponding
constructor:
class MyClass {
MyClass( String s ) {
// some code here
// ...
}
Then, we could write:
MyFunc mf = MyClass::new;
Bigger example:
interface IntPredicate
{
boolean test( int n );
}
class ValueStore
{
private int value;
ValueStore( int x )
{
value = x;
}
void updateValue( int x )
{
value = x;
}
boolean isValue( int a )
{
return a == value;
}
static boolean isPositive( int n )
{
return n > 0;
}
}
public class ReferenceDemo {
static boolean evaluate( IntPredicate pred, int num )
{
return pred.test( num );
}
public static void main(String[] args) {
IntPredicate p = ValueStore::isPositive;
System.out.println( p.test( 3 ));
System.out.println( p.test( -3 ));
System.out.println( evaluate( p, -3 )); // behaves like previous line
ValueStore store = new ValueStore( 7 );
p = store::isValue;
System.out.println( p.test( 7 ));
store.updateValue( 10 );
System.out.println( p.test( 7 ));
}
}
Source: POP2, Hubie Chen
From GeekforGeeks:
An exception is an unwanted or unexpected event, which occurs during the execution of a program i.e at run time, that disrupts the normal flow of the program’s instructions. In Java, there are two types of exceptions:
- Checked exceptions
- Unchecked exceptions
Inheritance structure:
- Object
- Throwable
- Exception
- Checked exception (e.g. IO or Compile time exception)
- Unchecked exception (e.g. NullPointerException or Runtime exception)
- Error
- Virtual Machine error
- Assertion error
These are the exceptions that are checked at compile time. If some code within a method throws a checked exception, then the method must either handle the exception or it must specify the exception using the throws
keyword.
public static void main(String[] args)
throws IOException
{
// Creating a file and reading from local repository
FileReader file = new FileReader("C:\\test\\a.txt");
// Reading content inside a file
BufferedReader fileInput = new BufferedReader(file);
// Printing first 3 lines of file "C:\test\a.txt"
for (int counter = 0; counter < 3; counter++)
System.out.println(fileInput.readLine());
// Closing all file connections
// using close() method
// Good practice to avoid any memory leakage
fileInput.close();
}
Source: GeekforGeeks
These are the exceptions that are not checked at compile time. Consider the following Java program. It compiles fine, but it throws ArithmeticException when run. The compiler allows it to compile because
ArithmeticException
is an unchecked exception.In Java exceptions under
Error
andRuntimeException
classes are unchecked exceptions, everything else underThrowable
is checked.
public static void main(String args[])
{
// Here we are dividing by 0
// which will not be caught at compile time
// as there is no mistake but caught at runtime
// because it is mathematically incorrect
int x = 0;
int y = 10;
int z = y / x;
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:5)
Java Result: 1
Source: GeekforGeeks
Invocation of a superclass constructor must be the first line in the subclass constructor.
The syntax for calling a superclass constructor is:
super();
the superclass no-argument constructor is called, orsuper(parameter list);
: the superclass constructor with a matching parameter list is called.
Source: Oracles Java Tutorials
// < Child >.java
public class < Parent > {
// attributes
int param1;
int param2;
// constructor
< Parent >( int a, int b) {
param1 = a;
param2 = b;
}
}
// < Child >.java
public class < Child > extends < Parent > {
// constructor
< Child >( int param1, int param2) {
super(param1, param2); // calls parent constructor
}
}
🔗 Source: Java Reflection Tutorial – The ULTIMATE Guide, resources linked in SDP week 4 pre-lecture material
The concept of reflection in software means the ability to inspect, analyze and modify other code at runtime.
🔗 Source: Java Reflection Tutorial – The ULTIMATE Guide
From a class object we can retrieve all kind of information like declared methods, constructors, visible fields, annotations, types.
In order to retrieve the class information from a single instance we can write (in this case, for the String class):
Class<String> stringclass = String.class;
or using the java.lang.Class.forName(String)
method:
Class.forName( "java.lang.String" )
It is also possible to create new instances of a given class using the method java.lang.Class.newInstance()
passing the right arguments:
String newInstanceStringClass = stringclass.newInstance();
String otherInstance = (String)Class.forName( "java.lang.String" ).newInstance();
The java.lang.Class.newInstance()
method can be used only when the class contains a public default constructor or a constructor without arguments.
🔗 Source: Java Reflection Tutorial – The ULTIMATE Guide
Interfaces can be accessed like a class using their qualified name. All methods available for classes are available for interfaces as well.
Assuming that the InterfaceExample
element is an interface.
System.out.println( "interface name: " + InterfaceExample.class.getName() );
One obvious difference between classes and interfaces is that interfaces cannot be instantiated using reflection via the newInstance()
method.
🔗 Source: Java Reflection Tutorial – The ULTIMATE Guide
Primitive types like int, float, double, etc. can be accessed and used almost like any other classes.
It is possible to retrieve a class object from a primitive type as for any other non primitive type:
Class<Integer> intClass = int.class;
But it is not possible to create new instances for primitive types using reflection.
It is possible to check if a given class belongs to a primitive type or not using the method java.lang.Class.isPrimitive()
System.out.println( "is primitive: " + intClass.isPrimitive() );
🔗 Source: Java Reflection Tutorial – The ULTIMATE Guide
Classes offer several methods to access their fields at runtime. The most important ones are:
java.lang.Class.getDeclaredFields()
: It returns an array with all declared fields for the class. It returns all private fields as well.java.lang.Class.getFields()
: It returns an array with all accessible fields for the class.java.lang.Class.getField(String)
: It returns a field with the name passed as parameter. It throws an exception if the field does not exist or is not accessible.java.lang.Class.getDeclaredField(String name)
: It returns a field with the given name, if the field does not exist it throws an exception.
These methods return an array of elements (or a single one) of the type java.lang.reflect.Field
. This class contains several interesting methods that can be used at runtime that allow a programmer to read the properties and the values of the specific field.
Example use case:
Class<String> stringclass = String.class;
Field[] fields = stringclass.getDeclaredFields();
for( Field field : fields ) {
System.out.println( "*************************" );
System.out.println( "Name: " + field.getName() );
System.out.println( "Type: " + field.getType() );
if( field.isAccessible() ) {
System.out.println( "Get: " + field.get( stringer ) );
}
System.out.println( "Modifiers:" + field.getModifiers() );
System.out.println( "isAccesible: " + field.isAccessible() );
}
Field fieldHashCode = stringclass.getDeclaredField( "hash" );
fieldHashCode.setAccessible( true );
Object value = fieldHashCode.get( stringer );
int valueInt = fieldHashCode.getInt( stringer );
System.out.println( value );
System.out.println( valueInt );
The output or the program would be:
*************************
Name: value
Type: class [C
Modifiers:18
isAccesible: false
*************************
Name: hash
Type: int
Modifiers:2
isAccesible: false
*************************
Name: serialVersionUID
Type: long
Modifiers:26
isAccesible: false
*************************
Name: serialPersistentFields
Type: class [Ljava.io.ObjectStreamField;
Modifiers:26
isAccesible: false
*************************
Name: CASE_INSENSITIVE_ORDER
Type: interface java.util.Comparator
Modifiers:25
isAccesible: false
0
0
🔗 Source: Java Reflection Tutorial – The ULTIMATE Guide
Using the method java.lang.Class.getMethods()
all visible or accessible methods for a given class are retrieved.
In order to retrieve all visible methods for a given class we can do the following:
Class<String> stringclass = String.class;
Method[] methods = stringclass.getMethods();
We can also retrieve an specific method using its name and the type of the arguments it is expecting to receive:
Class<String> stringclass = String.class;
Method methodIndexOf = stringclass.getMethod( "indexOf", String.class );
For a given method (an instance of the type java.lang.reflect.Method
), we can access all its properties. The following snippet shows a couple of them like name, default values, return type, modifiers, parameters, parameter types or the exceptions thrown, we can also check if a method is accessible or not:
for( Method method : methods ) {
System.out.println( "****************************************************" );
System.out.println( "name: " + method.getName() );
System.out.println( "defaultValue: " + method.getDefaultValue() );
System.out.println( "generic return type: " + method.getGenericReturnType() );
System.out.println( "return type: " + method.getReturnType() );
System.out.println( "modifiers: " + method.getModifiers() );
Parameter[] parameters = method.getParameters();
System.out.println( parameters.length + " parameters:" );
for( Parameter parameter : parameters ) {
System.out.println( "parameter name: " + parameter.getName() );
System.out.println( "parameter type: " + parameter.getType() );
}
Class<?>[] parameterTypes = method.getParameterTypes();
System.out.println( parameterTypes.length + " parameters:" );
for( Class<?> parameterType : parameterTypes ) {
System.out.println( "parameter type name: " + parameterType.getName() );
}
Class<?>[] exceptionTypes = method.getExceptionTypes();
System.out.println( exceptionTypes.length + " exception types: " );
for( Class<?> exceptionType : exceptionTypes ) {
System.out.println( "exception name " + exceptionType.getName() );
}
System.out.println( "is accesible: " + method.isAccessible() );
System.out.println( "is varArgs: " + method.isVarArgs() );
}
It is also possible to instantiate given methods for specific objects passing the arguments that we want, we should assure that the amount and type of the arguments is correct:
Object indexOf = methodIndexOf.invoke( stringer, "called" );
This last feature is very interesting when we want to execute specific methods at runtime under special circumstances.
Package: java.lang
Provides classes that are fundamental to the design of the Java programming language:
- The most important classes are
Object
, which is the root of the class hierarchy, and Class
, instances of which represent classes at run time.
The class Math
provides commonly used mathematical functions such as sine, cosine, and square root.
The classes String
, StringBuffer
, and StringBuilder
similarly provide commonly used operations on character strings.
Class Throwable
encompasses objects that may be thrown by the throw statement. Subclasses of Throwable
represent errors and exceptions.
Class: java.lang.reflect.Array
N.B: The package java.lang.reflect provides classes and interfaces for obtaining reflective information about classes and objects.
public final class Array
extends Object
The Array class provides static methods to dynamically create and access Java arrays.
In Java, all arrays are dynamically allocated.
/* In one step:
* <type>[] <name> = new <type>[<size>];
*/
int[] arr = new int[20];
int[][] arr2D = new int[10][20]; //a 2D array or matrix
int[][][] arr3D = new int[10][20][10]; //a 3D array
/*
* In two steps:
* <type>[] <name>;
* <name> = new <type>[<size>];
*/
int[] arr;
arr = new int[20];
/*
* As array literal:
* <type>[] <name> = new <type>[]{ element, element, element, ... };
*/
int[] arr = new int[]{ 1,2,3,4,5,6,7,8,9,10 };
String[] suits = { "clubs", "diamond", "hearts", "spades" };
// arr[i][j] = arr[👇][👉]
int[][] arr = {
{ 00, 01, 02, 03, },
{ 10, 11, 12, 13, },
{ 20, 21, 22, 23, },
{ 30, 31, 32, 33, },
};
jshell> arr[0][0] ==> 0
jshell> arr[0][1] ==> 1
jshell> arr[1][0] ==> 10
jshell> arr[1][2] ==> 12
jshell> arr[3][0] ==> 30
Source: Geekforgeeks
Since arrays are objects in Java, we can find their length using the object property length
. Instead of s.length()
, which is a String method that computers the length of a String.
Source: Geekforgeeks
For detail see: obj.clone()
in this doc.
Deep copy and shallow copy:
When you clone a single-dimensional array, such as
Object[]
, a “deep copy” is performed with the new array containing copies of the original array’s elements as opposed to references.A clone of a multi-dimensional array (like
Object[][]
) is a “shallow copy,” however, which is to say that it creates only a single new array with each element array a reference to an original element array, but subarrays are shared.
Source: Geekforgeeks
Context:
- Every array type implements the interface Cloneable (Source: Geekforgeeks).
- Since the Array class extends the Object class (see class signature below), it inherits the
obj.clone()
method defined in the Object class.
public final class Array
extends Object
Class: java.lang.Object
public class Object
- Class Object is the root of the class hierarchy.
- Every class has Object as a superclass.
- All objects, including arrays, implement the methods of this class.
protected Object clone()
throws CloneNotSupportedException
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
The general intent is that, for any object x
, the expression:
x.clone() != x
will be true,x.clone().getClass() == x.getClass()
will be true, andx.clone().equals(x)
will be true.
N.B:
public boolean equals(Object obj)
Indicates whether some other object is "equal to" this one, true/false).
The equals method implements an equivalence relation on non-null object references:
- It is reflexive: for any non-null reference value x, x.equals(x) should return true.
- It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
- It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
- It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
- For any non-null reference value x, x.equals(null) should return false.
@Override // overrides Object equals() method (for my own objects definition)
public boolean equals(Object obj) {
// reflexivity
if(this == obj) { return true; }
// comparing apples and pears
if((obj == null) || (obj.getClass() != this.getClass())) { return false; }
// Can now safely cast Pair type onto obj
Pair otherPair = (Pair) obj;
// equal is x and y are equal
return x == otherPair.get_x() && y == otherPair.get_y();
}
@Override
public int hashCode() {
int hash = 7;
return x * hash - y * hash;
}
When we override
equals()
, it is recommended to also override thehashCode()
method. If we don’t do so, equal objects may get different hash-values; and hash based collections, including HashMap, HashSet, and Hashtable do not work properly.
Source: Geekforgeeks
@Override
public int hashCode() {
int hash = 7;
return x * hash - y * hash;
}
public final Class<?> getClass()
Returns the runtime class of this Object.
public String toString()
Returns a string representation of the object.
In general, the toString method returns a string that "textually represents" this object:
- The result should be a concise but informative representation that is easy for a person to read.
- It is recommended that all subclasses override this method.
Class: java.lang.Character
The Character class wraps a value of the primitive type char
in an object. An object of class Character
contains a single field whose type is char
.
Two parameter types:
- int codepoint (unicode)
- char ch (character)
public static boolean isAlphabetic(int codePoint)
Mostly used with s.codePointAt(i)
e.g.
Character.isAlphabetic(s.codePointAt(i))
public static boolean isLetter(char ch)
A character is considered to be a letter if its general category type, provided by Character.getType(ch)
, is any of the following:
- UPPERCASE_LETTER
- LOWERCASE_LETTER
- TITLECASE_LETTER
- MODIFIER_LETTER
- OTHER_LETTER
public static boolean isDigit(char ch)
A character is a digit if its general category type, provided by Character.getType(ch)
, is DECIMAL_DIGIT_NUMBER.
public static boolean isLowerCase(char ch)
A character is lowercase if its general category type, provided by Character.getType(ch)
, is LOWERCASE_LETTER
public static boolean isUpperCase(char ch)
A character is uppercase if its general category type, provided by Character.getType(ch)
, is UPPERCASE_LETTER.
public static boolean isWhitespace(char ch)
A character is a Java whitespace character if and only if it satisfies one of the following criteria: It is a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or PARAGRAPH_SEPARATOR) but is not also a non-breaking space ('\u00A0', '\u2007', '\u202F').
- It is '\t', U+0009 HORIZONTAL TABULATION.
- It is '\n', U+000A LINE FEED.
- It is '\u000B', U+000B VERTICAL TABULATION.
- It is '\f', U+000C FORM FEED.
- It is '\r', U+000D CARRIAGE RETURN.
- It is '\u001C', U+001C FILE SEPARATOR.
- It is '\u001D', U+001D GROUP SEPARATOR.
- It is '\u001E', U+001E RECORD SEPARATOR.
- It is '\u001F', U+001F UNIT SEPARATOR.
public static char toLowerCase(char ch)
Converts the character argument to lowercase using case mapping information from the UnicodeData file.
public static char toUpperCase(char ch)
Converts the character argument to uppercase using case mapping information from the UnicodeData file.
Class: java.lang.String
The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.
Strings are constant (immutable); their values cannot be changed after they are created.
public char charAt(int index)
Returns the length of this string. The length is equal to the number of Unicode code units in the string.
public char charAt(int index)
Returns the char value at the specified index. An index ranges from 0 to length() - 1.
public int indexOf(int ch)
Returns the index within this string of the first occurrence of the specified character ch
.
public int indexOf(int ch,
int fromIndex)
Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.
public int codePointAt(int index)
Returns the character (Unicode code point) at the specified index. The index refers to char values (Unicode code units) and ranges from 0 to length() - 1.
public String toLowerCase()
Converts all of the characters in this String to lower case using the rules of the default locale.
public String toUpperCase()
Converts all of the characters in this String to upper case using the rules of the default locale.
public int compareTo(String anotherString)
Compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings.
- negative integer: if
s
lexicographically precedes the argument strings2
, e.g. pseudo-codea.compareTo( z ) < 1
- positive integer: if
s
lexicographically follows the argument strings2
, e.g. pseudo-codez.compareTo( a ) > 1
- 0: when the
s.equals(s2)
returns true, , e.g. pseudo-codea.compareTo( a ) == 1
Compares two strings lexicographically, ignoring case differences. This method returns an integer whose sign is that of calling compareTo with case folded versions of the strings where case differences have been eliminated by calling Character.toLowerCase(Character.toUpperCase(int)) on each Unicode code point.
String[] split(String regex, int limit)
Use regex101 to test matches.
String entireLine = "Joey ate an apple; then,";f
entireLine.split( "[^a-zA-Z]" ); // { "Joey", "ate", "an", "apple", "", "then" }
Splits this string around matches of the given regular expression. The array returned by this method contains each substring of this string that is terminated by another substring that matches the given expression or is terminated by the end of the string. The substrings in the array are in the order in which they occur in this string. If the expression does not match any part of the input then the resulting array has just one element, namely this string.
The limit
parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array.
-
If the
limit
is positive then the pattern will be applied at mostlimit
- 1 times, the array's length will be no greater thanlimit
, and the array's last entry will contain all input beyond the last matched delimiter. -
If the
limit
is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded. -
If the
limit
is negative then the pattern will be applied as many times as possible and the array can have any length.
The string "boo:and:foo"
, for example, yields the following results with these parameters:
Regex | Limit | Result |
---|---|---|
: | 2 | { "boo", "and:foo" } |
: | 5 | { "boo", "and", "foo" } |
: | -2 | { "boo", "and", "foo" } |
o | 5 | { "b", "", ":and:f", "", "" } |
o | -2 | { "b", "", ":and:f", "", "" } |
o | 0 | { "b", "", ":and:f" } |
String[] split(String regex)
Splits this string around matches of the given regular expression.
This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero.
Trailing empty strings are therefore not included in the resulting array.
The string "boo:and:foo"
, for example, yields the following results with these expressions:
Regex | Result |
---|---|
: | { "boo", "and", "foo" } |
o | { "b", "", ":and:f" } |
Class: java.lang.StringBuilder
public final class StringBuilder
extends Object
implements Serializable, Comparable<StringBuilder>, CharSequence
A mutable sequence of characters. The principal operations on a StringBuilder are the append
(at end) and insert
(at index) methods, which are overloaded so as to accept data of any type.
If sb
refers to an instance of a StringBuilder, then sb.append(x)
has the same effect as sb.insert(sb.length(), x)
.
Use sb.toString()
to convert the object into an immutable String.
Constructor: sb.StringBuilder()
sb.StringBuilder(String str)
Constructs a string builder initialized to the contents of the specified string.
StringBuilder sbEmpty = new StringBuilder();
StringBuilder sbExisting = new StringBuilder("Hello");
Returns a string representing the data in this sequence.
Appends the string representation of the Object argument.
Exists with various methods signatures:
append(boolean b)
: Appends the string representation of the boolean argument to the sequence.append(char c)
: Appends the string representation of the char argument to this sequence.append(double d)
: Appends the string representation of the double argument to this sequence.append(float f)
: Appends the string representation of the float argument to this sequence.append(int i)
: Appends the string representation of the int argument to this sequence.append(long lng)
: Appends the string representation of the long argument to this sequence.append(Object obj)
: Appends the string representation of the Object argument.append(String str)
: Appends the specified string to this character sequence.
Removes the characters in a substring of this sequence. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the sequence if no such character exists. If start is equal to end, no changes are made.
public StringBuilder deleteCharAt(int index)
Removes the char at the specified position in this sequence. This sequence is shortened by one char.
public StringBuilder replace(int start, int end, String str)
Parameters:
start
- The beginning index, inclusive.end
- The ending index, exclusive.str
- String that will replace previous contents.
Class: java.lang.Thread
public class Thread
extends Object
implements Runnable
A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.
There are two ways to create a new thread of execution. [Our] way to create a thread is to declare a class that implements the Runnable
interface. That class then implements the run
method. An instance of the class can then be allocated, passed as an argument when creating Thread
, and started.
The
Runnable
interface defines one method:public void run()
TheThread
class defines a number of methods, e.g.:
- constructors:
Thread(Runnable job)
,Thread(Runnable job, String name)
- starts a thread:
void start()
- reports whether the thread is running:
final boolean isAlive()
- suspends a thread for the given duration:
static void sleep(long milliseconds)
From POP2 lecture:
We’ll use the
Thread
class & theRunnable
interface to create and start threads.Our recipe:
- Create a class that implements
Runnable
. Runnable defines only one method:public void run()
- Create an instance of the class (“a job”)
- Create an instance of
Thread
, passing it the instance from 2- Start the
Thread
instance!We can think of a thread (an instance of
Thread
) as a worker; for it to be useful, we need to give it a job!
Example:
// TestRunnable.java
public class TestRunnable implements Runnable {
// defines the class that implements the run() method of the `Runnable` interface
public void run() {
/*
try
{ Thread.sleep(1000); }
catch( InterruptedException e )
{ e.printStackTrace(); }
*/
printsmth();
}
void printsmth() {
System.out.println( "I'm active." );
}
// try this both and without sleeping
}
// MainTestRunnable.java
public class MainTestRunnable {
// example 1
public static void main(String[] args) {
System.out.println("Hello World, from main()!");
// an instance of the class (that implements Runnable) we defined above
Runnable job = new TestRunnable();
// an instance of `Thread` to which we pass the instance of the class above
Thread thread = new Thread(job);
// starts the `Thread` instance
thread.start();
System.out.println( "Finishing in main()." );
}
}
Source: POP2, credit to Hubie Chen
In a class that implement Runnable
, we can declare a method as synchronized
to synchronize different threads' access to it.
If we have an instance of Thread with an instance of that class as an argument:
- only 1 thread can be in the
synchronized
method at a time - (in fact) only 1 thread can be in any synchronized method (of the instance) at a time
💡 Note: We can only synchronize with methods if we wrote the method ourselves. If we use a library method, we don't want to modify the library's method declaration. In that case, we can use synchronized blocks (see next).
// Counter.java
public class Counter implements Runnable {
// attributes
int start;
int end;
// constructor
Counter( int start, int end ) {
this.start = start;
this.end = end;
}
// implements run()
synchronized public void run() {
// simply prints counter from 1 to n
for (int i = this.start; i <= this.end; i++) {
System.out.println(
Thread.currentThread().getName()
+ " i: "
+ i);
}
}
}
public class MainCounter {
public static void main(String[] args) {
// create instances of Counter
Counter counterA = new Counter( 1, 10 );
// creates threads
Thread threadA1 = new Thread( counterA );
Thread threadA2 = new Thread( counterA );
// starts the threads
threadA1.start();
threadA2.start();
}
}
// Output without `synchronized void run()`
Thread-0 i: 1
Thread-1 i: 1
Thread-0 i: 2
Thread-1 i: 2
Thread-0 i: 3
Thread-1 i: 3
Thread-0 i: 4
Thread-0 i: 5
Thread-0 i: 6
Thread-1 i: 4
Thread-0 i: 7
Thread-1 i: 5
Thread-1 i: 6
Thread-1 i: 7
Thread-1 i: 8
Thread-1 i: 9
Thread-0 i: 8
Thread-0 i: 9
Thread-0 i: 10
Thread-1 i: 10
// Output **with** `synchronized void run()`
Thread-0 i: 1
Thread-0 i: 2
Thread-0 i: 3
Thread-0 i: 4
Thread-0 i: 5
Thread-0 i: 6
Thread-0 i: 7
Thread-0 i: 8
Thread-0 i: 9
Thread-0 i: 10
Thread-1 i: 1
Thread-1 i: 2
Thread-1 i: 3
Thread-1 i: 4
Thread-1 i: 5
Thread-1 i: 6
Thread-1 i: 7
Thread-1 i: 8
Thread-1 i: 9
Thread-1 i: 10
We can only use synchronize
with methods if we wrote the method ourselves. If we use a library method, we can't modify the library's method declaration. In that case, we can use synchronized blocks when we call that method.
Example:
synchronized( object ) {
// code that is synchronized
// ...
}
Using synchronized blocks allows us to synchronize part of a method
synchronized void someMethodInAClass() {
// synchronized code here
}
// ...is equivalent to...
void someMethodInAClass() {
synchronized( this ) {
// code here
}
}
```java
// Counter.java
public class Counter implements Runnable {
// attributes
int start;
int end;
// constructor
Counter( int start, int end ) {
this.start = start;
this.end = end;
}
// implements run()
public void run() {
synchronized ( this ) {
// simply prints counter from 1 to n
for (int i = this.start; i <= this.end; i++) {
System.out.println(
Thread.currentThread().getName()
+ " i: "
+ i);
}
}
}
}
// MainCounter.java
public class MainCounter {
public static void main(String[] args) {
// create instances of Counter
Counter counterA = new Counter( 1, 10 );
// creates threads
Thread threadA1 = new Thread( counterA );
Thread threadA2 = new Thread( counterA );
// starts the threads
threadA1.start();
threadA2.start();
}
}
// Output without `synchronized ( this ) { ... }`
Thread-0 i: 1
Thread-1 i: 1
Thread-0 i: 2
Thread-1 i: 2
Thread-1 i: 3
Thread-1 i: 4
Thread-0 i: 3
Thread-0 i: 4
Thread-0 i: 5
Thread-0 i: 6
Thread-1 i: 5
Thread-1 i: 6
Thread-1 i: 7
Thread-1 i: 8
Thread-1 i: 9
Thread-1 i: 10
Thread-0 i: 7
Thread-0 i: 8
Thread-0 i: 9
Thread-0 i: 10
// Output **with** `synchronized ( this ) { ... }`
Thread-0 i: 1
Thread-0 i: 2
Thread-0 i: 3
Thread-0 i: 4
Thread-0 i: 5
Thread-0 i: 6
Thread-0 i: 7
Thread-0 i: 8
Thread-0 i: 9
Thread-0 i: 10
Thread-1 i: 1
Thread-1 i: 2
Thread-1 i: 3
Thread-1 i: 4
Thread-1 i: 5
Thread-1 i: 6
Thread-1 i: 7
Thread-1 i: 8
Thread-1 i: 9
Thread-1 i: 10
public final boolean isAlive()
Tests if this thread is alive. A thread is alive if it has been started and has not yet died.
Returns:
- true if this thread is alive; false otherwise.
From POP2:
This method returns true if the thread (on which it’s called) is still running, and false otherwise
Causes the current thread to wait until it is awakened, typically by being notified or interrupted.
From POP2:
waits until another thread invokes a notify method
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
From POP2:
waits until notified or the given amount of time (in milliseconds) has passed
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.
From POP2:
Call to notify() awakens one waiting thread. Doesn’t give up caller’s lock (but after caller gives up lock, another thread can take it)
Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.
From POP2:
Call to notifyAll() awakens all threads – can be used when potentially many threads are waiting for a task to finish
thread1.join()
basically means that subsequent threads that wants to start (thread2.start()
) have to wait for thread1
to complete. Meanwhile, the code execution doesn't stop at .join()
but the threads are made to wait.
This is illustrated with the below 5 second delay counter in each thread.
// JoinExample.java
public class JoinExample implements Runnable {
// attributes
int sec; // number of loop repetitions and thus seconds
// constructor
JoinExample( int sec ) {
this.sec = sec;
}
// implements run() from Runnable
public void run() {
for (int i = 1; i <= this.sec; i++) { // repeat 5 times (i.e. delay 5 seconds)
try {
// make Thread wait for 1 second during each iteration of the loop
Thread.sleep(1000); // 1000ms = 1sec
// print current number of the iteration to console
System.out.println(
Thread.currentThread().getName()
+ ": "
+ i
+ " second(s) "
);
} catch (Exception e) {
System.out.println(
"Exception has been caught"
+ e);
}
}
}
}
// MainJoinExample.java
public class MainJoinExample {
public static void main(String[] args) {
// create JoinExample instance
JoinExample secondsDelayer = new JoinExample( 5 ); // 5 second delay
// create Thread instances with JoinExample (each will count 5 seconds)
Thread thread1 = new Thread( secondsDelayer );
Thread thread2 = new Thread( secondsDelayer );
Thread thread3 = new Thread( secondsDelayer );
// start first thread
thread1.start();
try {
thread1.join();
System.out.println("Thread just finished");
} catch (Exception e) {
System.out.println(
"Exception has been caught"
+ e
);
}
// start second thread
thread2.start();
try {
thread2.join();
System.out.println("Thread just finished");
} catch (Exception e) {
System.out.println(
"Exception has been caught"
+ e
);
}
// start third thread
thread3.start();
try {
thread3.join();
System.out.println("Thread just finished");
} catch (Exception e) {
System.out.println(
"Exception has been caught"
+ e
);
}
}
}
// with `join()`
Thread-0: 1 second(s)
Thread-0: 2 second(s)
Thread-0: 3 second(s)
Thread-0: 4 second(s)
Thread-0: 5 second(s)
Thread just finished
Thread-1: 1 second(s)
Thread-1: 2 second(s)
Thread-1: 3 second(s)
Thread-1: 4 second(s)
Thread-1: 5 second(s)
Thread just finished
Thread-2: 1 second(s)
Thread-2: 2 second(s)
Thread-2: 3 second(s)
Thread-2: 4 second(s)
Thread-2: 5 second(s)
Thread just finished
// without `.join()`
Thread just finished
Thread just finished
Thread just finished
Thread-1: 1 second(s)
Thread-0: 1 second(s)
Thread-2: 1 second(s)
Thread-0: 2 second(s)
Thread-1: 2 second(s)
Thread-2: 2 second(s)
Thread-0: 3 second(s)
Thread-2: 3 second(s)
Thread-1: 3 second(s)
Thread-0: 4 second(s)
Thread-2: 4 second(s)
Thread-1: 4 second(s)
Thread-1: 5 second(s)
Thread-2: 5 second(s)
Thread-0: 5 second(s)
Thrown to indicate that the requested operation is not supported.
Example:
public class Penguin extends Bird implements SwimmingAnimal, MoltingAnimal {
// ...
public void fly() {
throw new UnsupportedOperationException();
}
}
public class PenguinTest {
//...
@Test
public void testItCantActuallyFly() {
Penguin penguin = new Penguin(5);
assertThrows(UnsupportedOperationException.class, penguin::fly);
}
}
Source: SDP > worksheet 1
Package summary: Package java.lang.reflect
Provides classes and interfaces for obtaining reflective information about classes and objects. Reflection allows programmatic access to information about the fields, methods, and constructors of loaded classes
Classes in this package, along with
java.lang.Class
accommodate applications such as debuggers, interpreters, object inspectors, class browsers, and services such as Object Serialization and JavaBeans that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class.
🔗 Source: Package summary: Package java.lang.reflect
The Reflection API allows a Java program to inspect and manipulate itself; it comprises the
java.lang.Class
class and thejava.lang.reflect
package, which represents the members of a class withMethod
,Constructor
, andField
objects.
🔗 Source: BBK > SDP > week 4 worksheet
Package: java.io
Class: java.io.FileReader
Reads text from character files using a default buffer size. The FileReader is meant for reading streams of characters. For reading streams of raw bytes, consider using a FileInputStream.
We use the FileReader class, which extends InputStreamReader which extends Reader
Commonly used contructor:
FileReader( String filename ) throws FileNotFoundException
We often use a FileReader
wrapped in a BufferedReader
to read more efficiently.
Class: java.io.BufferedReader
Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines. The buffer size may be specified, or the default size may be used. The default is large enough for most purposes.
In general, each read request made of a Reader causes a corresponding read request to be made of the underlying character or byte stream. It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. For example,
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
will buffer the input from the specified file. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.
Use String[] split(String regex, int limit)
to split entireLine
into a String[] with each matching word.
String entireLine;
try( BufferedReader br = new BufferedReader( new FileReader( "test.txt" ))) {
while(( entireLine = br.readLine()) != null ) {
// do something with entireLine read
}
} catch( IOException exc ) {
System.out.println( "I/O Error: " + exc );
}
Example from POP2:
public static void main(String[] args) {
String s;
try( BufferedReader br = new BufferedReader( new FileReader( "test.txt" ))) {
int lineNr = 0;
while(( entireLine = br.readLine()) != null ) {
System.out.println( "" + lineNr + ": " + entireLine );
lineNr++;
}
} catch( IOException exc ) {
System.out.println( "I/O Error: " + exc );
}
}
Source: POP2, credit to Hubie Chen (08-code-io)
public int read() throws IOException
Reads a single character.
Overrides: read
in class Reader
Returns: The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached
public String readLine() throws IOException
Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), a carriage return followed immediately by a line feed, or by reaching the end-of-file (EOF).
Returns: A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached without reading any characters
public void close() throws IOException
Closes the stream and releases any system resources associated with it. Once the stream has been closed, further read()
, ready()
, mark()
, reset()
, or skip()
invocations will throw an IOException. Closing a previously closed stream has no effect.
Class: java.io.FileWriter
We use the FileWriter class which extends class OutputStreamWriter which extends abstract class Writer.
Two commonly used constructors:
FileWriter( String filename )
FileWriter( String filename, boolean append )
append
set to true --> output appended to end of file
append
set to false --> file overwritten
try( FileWriter fw = new FileWriter( "test.txt" )) {
// write to file
} catch( IOException exc ) {
System.out.println( "I/O error: " + exc );
}
Example:
public static void main(String[] args) {
String str;
BufferedReader br = new BufferedReader( new InputStreamReader( System.in ));
System.out.println( "Enter text; 'stop' to quit." );
try( FileWriter fw = new FileWriter( "test.txt" ))
{
do {
str = br.readLine();
if( str.equals( "stop" )) break;
str = str + "\n";
fw.write( str );
} while( true );
}
catch( IOException exc )
{
System.out.println( "I/O error: " + exc );
}
}
Source: POP2, credit to Hubie Chen (08-dist-io)
public void write(String str) throws IOException
Writes a string.
Throws: IOException - If an I/O error occurs
Writes a portion of a string.
Parameters:
str
- A Stringoff
- Offset from which to start writing characterslen
- Number of characters to write
Package: java.util
Contains the collections framework, some internationalization support classes, a service loader, properties, random number generation, string parsing and scanning classes, base64 encoding and decoding, a bit array, and several miscellaneous utility classes.
Class: Arrays
This class contains various methods for manipulating arrays (such as sorting and searching). This class also contains a static factory that allows arrays to be viewed as lists.
The methods in this class all throw a NullPointerException, if the specified array reference is null, except where noted.
Returns a string representation of the contents of the specified array. The string representation consists of a list of the array's elements, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (a comma followed by a space). Elements are converted to strings as by String.valueOf(int). Returns "null" if a is null.
Returns a string representation of the "deep contents" of the specified array. If the array contains other arrays as elements, the string representation contains their contents and so on. This method is designed for converting multidimensional arrays to strings.
Returns true if the two specified arrays of ints are equal to one another. Two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal. In other words, two arrays are equal if they contain the same elements in the same order. Also, two array references are considered equal if both are null.
Parameters:
a
- one array to be tested for equalitya2
- the other array to be tested for equality
Returns:
- true if the two arrays are equal
Returns true if the two specified arrays are deeply equal to one another. Unlike the equals(Object[],Object[]) method, this method is appropriate for use with nested arrays of arbitrary depth.
The sorting algorithm is a Dual-Pivot Quicksort by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm offers O(n log(n)) performance on all data sets, and is typically faster than traditional (one-pivot) Quicksort implementations.
Searches the specified array of ints for the specified value using the binary search algorithm. The array must be sorted (as by the sort(int[]) method) prior to making this call. If it is not sorted, the results are undefined. If the array contains multiple elements with the specified value, there is no guarantee which one will be found.
The comparison is consistent with equals, more specifically the following holds for arrays a and b:
Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
Class: ArrayList<E>
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
<E>
= the type of elements in this list
Resizable-array implementation of the List
interface. Implements all optional list operations, and permits all elements, including null
. (This class is roughly equivalent to Vector
, except that it is unsynchronized.)
Constructor: ArrayList()
ArrayList<String> lString = new ArrayList<String>()
ArrayList<Integer> lInteger = new ArrayList<Integer>()
Constructs an empty list with an initial capacity of ten.
Elements in an ArrayList are actually objects.
To use other types, such as
int
, you must specify an equivalent wrapper class:Integer
. For other primitive types, use:Boolean
for boolean,Character
for char,Double
for double, etc:
Source: W3School
Inserts the specified element at the specified position in this list.
Parameters:
index
- index at which the specified element is to be insertedelement
- element to be inserted
Throws:
- IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())
Appends the specified element to the end of this list.
Parameters:
e
- element to be appended to this list
Returns:
- true (as specified by Collection.add(E))
Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's Iterator. The behavior of this operation is undefined if the specified collection is modified while the operation is in progress.
Parameters:
c
- collection containing elements to be added to this list
Returns:
- true if this list changed as a result of the call
Inserts all of the elements in the specified collection into this list, starting at the specified position. Shifts the element currently at that position (if any) and any subsequent elements to the right (increases their indices). The new elements will appear in the list in the order that they are returned by the specified collection's iterator.
.lenth()
for ArrayList, use .size()
instead.
public int size()
Returns the number of elements in this list.
Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged. More formally, removes the element with the lowest index i such that Objects.equals(o, get(i)) (if such an element exists). Returns true if this list contained the specified element (or equivalently, if this list changed as a result of the call).
Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).
Returns:
- the element that was removed from the list
See in Interface Colletion<E>
method c.removeIf(Predicate<?superE>filter)
in this doc.
Removes all of the elements from this list. The list will be empty after this call returns.
public int indexOf(Object o)
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
if ( ! lst.contains( str ) ) {
...
}
lst.remove( lst.get( lst.size() - 1 ) ); // remove last element in list
Replaces the element at the specified position in this list with the specified element.
ArrayList<String> lst = new ArrayList<String>(); // assume this is full of strings
lst.set( 2, "abc" ); // replaces string at index 2 with "abc"
Class: Collections
public class Collections extends Object
This class consists exclusively of static methods that operate on or return collections.
Return type: void (operation on same object)
Example:
ArrayList<String> lst = new ArrayList<String>(); // assume this contains String elements
Collections.sort( lst ); // sorts the ArrayList alphabetically
Return type: void (operation on same object)
When you want to specify a comparator to sort by.
Example:
class Simpson implements Comparable<Simpson> {
String name;
Simpson(String name) {
this.name = name;
}
@Override
public int compareTo(Simpson simpson) {
return this.name.compareTo(simpson.name);
}
}
//
public class SimpsonSorting {
public static void main(String... sortingWithList) {
List<SimpsonCharacter> simpsons = new ArrayList<>();
simpsons.add(new SimpsonCharacter("Homer "));
simpsons.add(new SimpsonCharacter("Marge "));
simpsons.add(new SimpsonCharacter("Bart "));
simpsons.add(new SimpsonCharacter("Lisa "));
Collections.sort(simpsons); // Now you can use sort because the comparator is defined
simpsons.stream().map(s -> s.name).forEach(System.out::print);
Collections.reverse(simpsons);
simpsons.stream().forEach(System.out::print);
}
}
Source: InfoWorld
Interface: Comparator<T>
Type Parameters:
T
- the type of objects that may be compared by this comparator
Functional Interface:
- This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
A comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order.
Parameters:
o1
- the first object to be compared.o2
- the second object to be compared.
Returns:
- a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
The implementor must ensure that signum(compare(x, y)) == -signum(compare(y, x))
for all x and y.
The implementor must also ensure that the relation is transitive: ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0.
It is generally the case, but not strictly required that (compare(x, y)==0) == (x.equals(y))
.
Class: Scanner
A simple text scanner which can parse primitive types and strings using regular expressions.
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods.
The default whitespace delimiter used by a scanner is as recognized by Character.isWhitespace()
.
Scanner(File source)
: Constructs a new Scanner that produces values scanned from the specified file.Scanner(String source)
: Constructs a new Scanner that produces values scanned from the specified input stream.Scanner(InputStream source)
: Constructs a new Scanner that produces values scanned from the specified string.- (more available)
Sets this scanner's delimiting pattern to a pattern constructed from the specified String.
String input = "1 fish 2 fish red fish blue fish";
Scanner sc = new Scanner(input).useDelimiter("\\s*fish\\s*");
Closes this scanner.
sc.hasNext()
variations
- sc.hasNextInt()
- sc.hasNextLine()
sc.hasNext(String pattern)
: Returns true if the next token matches the pattern constructed from the specified string.
Finds and returns the next complete token from this scanner.
sc.next(String pattern)
: Returns the next token if it matches the pattern constructed from the specified string.- [
sc.nextInt()
]: Scans the next token of the input as an int. sc.nextLine()
: Advances this scanner past the current line and returns the input that was skipped.
Interface: Collection<E>
public interface Collection<E>
extends Iterable<E>
The root interface in the collection hierarchy.
Removes all of the elements of this collection that satisfy the given predicate.
For context, Interface Predicate<T>
is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
Interface: Map<K,V>
- An object that maps keys to values.
- A map cannot contain duplicate keys;
- each key can map to at most one value.
Type Parameters:
K
: the type of keys maintained by this mapV
: the type of mapped values
This interface takes the place of the Dictionary class, which was a totally abstract class rather than an interface.
Class: HashMap<K,V>
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
HashMap< String , Set<Integer> > map = new HashMap< String , Set<Integer> >();
This implementation provides constant-time performance for the basic operations (get
and put
), assuming the hash function disperses the elements properly among the buckets.
Useful methods:
m.get(Object key)
m.put(K key, V value)
m.size()
m.remove(Object key)
m.clear()
m.clone()
m.containsKey(Object key)
m.containsValue(Object value)
m.entrySet()
returnsSet<Map.Entry<K,V>>
m.keySet()
returnsSet<K>
// HashMap<K, V> m = new HashMap();
for (Map.Entry<K, V> pair: m.entrySet()) {
// pair.getKey()
// pair.getValue();
}
Source: zetcode.com
// HashMap<K, V> m = new HashMap();
Iterator< Map.Entry<K, V> > it = items.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<K, V> pair = it.next();
// pair.getKey()
// pair.getValue();
}
Source: zetcode.com
Interface: Set<E>
public interface Set<E>
extends Collection<E>
A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1
and e2
such that e1.equals(e2)
, and at most one null
element.
All known implementing classes:
- AbstractSet
- HashSet
- LinkedHashSet
- TreeSet
- more excl. for simplicity
Class: HashSet<E>
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable
This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits the null element.
Constructs a new, empty set.
Constructs a new set containing the elements in the specified collection c
.
public boolean add(E e)
Adds the specified element to this set if it is not already present.
If this set already contains the element, the call leaves the set unchanged and returns false.
public void clear()
Removes all of the elements from this set. The set will be empty after this call returns.
public Object clone()
Returns a shallow copy of this HashSet instance: the elements themselves are not cloned.
public boolean contains(Object o)
Returns true if this set contains the specified element.
public boolean isEmpty()
Returns true if this set contains no elements.
public boolean remove(Object o)
Removes the specified element from this set if it is present.
Returns true if this set contained the element (or equivalently, if this set changed as a result of the call).
public int size()
Returns the number of elements in this set (its cardinality).
public Object[] toArray()
Returns an array containing all of the elements in this collection.
Package: java.util.function
Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method, called the functional method for that functional interface, to which the lambda expression's parameter and return types are matched or adapted. Functional interfaces can provide a target type in multiple contexts, such as assignment context, method invocation, or cast context:
// Assignment context
Predicate<String> p = String::isEmpty;
The interfaces in this package are annotated with FunctionalInterface. This annotation is not a requirement for the compiler to recognize an interface as a functional interface, but merely an aid to capture design intent and enlist the help of the compiler in identifying accidental violations of design intent.
Functional interfaces often represent abstract concepts like functions, actions, or predicates. In documenting functional interfaces, or referring to variables typed as functional interfaces, it is common to refer directly to those abstract concepts, for example using "this function" instead of "the function represented by this object".
There are several basic function shapes, including:
Function
(unary function fromT
toR
),Consumer
(unary function fromT
tovoid
),Predicate
(unary function fromT
toboolean
), andSupplier
(nullary function toR
).
Function shapes have a natural arity based on how they are most commonly used. The basic shapes can be modified by an arity prefix to indicate a different arity, such as:
BiFunction
(binary function fromT
andU
toR
).
There are additional derived function shapes which extend the basic function shapes, including:
UnaryOperator
(extendsFunction
), andBinaryOperator
(extendsBiFunction
).
defines method apply()
which applies a unary operation to an object of type T and returns the result (of type T)
similar to previous interface, but for applying an operation to two objects
defines method accept()
; applies an operation to an object of type T
defines method test()
which applies an operation to an object of type T and returns a boolean value
Package summary: java.util.stream
💡 Great TLDR and explanation in the docs above ☝️
Classes to support functional-style operations on streams of elements. The key abstraction introduced in this package is stream.
The classes
Stream
,IntStream
,LongStream
, andDoubleStream
are streams over objects and the primitiveint
,long
, anddouble
types.Streams differ from collections in several ways:
- No storage. A stream is not a data structure that stores elements; instead, it conveys elements from a source such as a data structure, an array, a generator function, or an I/O channel, through a pipeline of computational operations.
- Functional in nature. An operation on a stream produces a result, but does not modify its source. For example, filtering a Stream obtained from a collection produces a new Stream without the filtered elements, rather than removing elements from the source collection.
- Laziness-seeking. Many stream operations, such as filtering, mapping, or duplicate removal, can be implemented lazily, exposing opportunities for optimization
- Possibly unbounded. While collections have a finite size, streams need not
- Consumable. The elements of a stream are only visited once during the life of a stream. Like an Iterator, a new stream must be generated to revisit the same elements of the source.
Streams can be obtained in a number of ways. Some examples include:
- From a Collection via the
stream()
andparallelStream()
methods;- From an array via
Arrays.stream(Object[])
;- From static factory methods on the stream classes, such as
Stream.of(Object[])
,IntStream.range(int, int)
orStream.iterate(Object, UnaryOperator)
;- The lines of a file can be obtained from
BufferedReader.lines()
;- Streams of file paths can be obtained from methods in
Files
;- Streams of random numbers can be obtained from
Random.ints()
;
Docs: package java.util.stream
Stream operations are divided into
- intermediate operations, and
- terminal operations, and are combined to form stream pipelines.
A stream pipeline consists of:
- a source (such as a
Collection
, an array, a generator function, or an I/O channel); - intermediate operation(s) (zero or more) such as
Stream.filter
orStream.map
which return a new stream. They are always lazy; executing an intermediate operation such asfilter()
does not actually perform any filtering, but instead creates a new stream that, when traversed, contains the elements of the initial stream that match the given predicate. Traversal of the pipeline source does not begin until the terminal operation of the pipeline is executed. - a terminal operation such as
Stream.forEach
orStream.reduce
, such asStream.forEach
orIntStream.sum
, may traverse the stream to produce a result or a side-effect. After the terminal operation is performed, the stream pipeline is considered consumed, and can no longer be used; if you need to traverse the same data source again, you must return to the data source to get a new stream.
Intermediate operations are further divided into:
- stateless operations, such as filter and map, which retain no state from previously seen element when processing a new element -- each element can be processed independently of operations on other elements.
- stateful operations, such as distinct and sorted, may incorporate state from previously seen elements when processing new elements.
See in this doc: Method references (e.g. ClassName::methodName
)
Example:
List<String> words = List.of("hi", "bat", "ear", "hello", "iguana",
"beaver", "winterland", "elephant", "eye", "qi");
Stream<String> sl = words.stream();
sl.forEach( s -> System.out.println(" " + s) );
List<String> words = List.of("hi", "bat", "ear", "hello", "iguana",
"beaver", "winterland", "elephant", "eye", "qi");
Stream<String> sl = words.stream();
sl.forEach( System.out::println );
import org.junit.Test;
import static org.junit.Assert.*;
import java.io.*;
import java.util.*;
public class dist03Test {
@Test
public void testBetween() {
assert Between.between(1, 1).equals("");
assert Between.between(1, 2).equals("");
assert Between.between(1, 3).equals("");
assert ! Between.between(2, 4).equals("");
// EDGE CASES
assert Between.between(2, 4).equals("3");
assert Between.between(2, 4).equals("3");
// BASE CASES
assert Between.between(3, 10).equals("5 7 9");
assert Between.between(7, 1).equals("5 3");
}
@Test
public void testAnagrams() {
// BASE CASES
assert Anagrams.anagrams( "roam", "roman") == 'n';
assert Anagrams.anagrams( "The Shining", "Highest inn" ) == '!';
assert Anagrams.anagrams( "William Shakespeare", "Willie makes phrases" ) == 's';
assert Anagrams.anagrams( "ebb", "ebb-flow" ) == 'w';
}
@Test
public void testHashMap() {
// BASE CASES: 1
Map<Character, Integer> mTest = new HashMap<Character, Integer>();
mTest.put('a', 1);
mTest.put('b', 2);
Map<Character, Integer> m = Anagrams.countLettersInMap("bab");
assert m.equals(mTest);
// BASE CASES: 2
mTest = new HashMap<Character, Integer>();
mTest.put('b', 1);
m = Anagrams.countLettersInMap("b");
assert m.equals(mTest);
// BASE CASES: 3
mTest = new HashMap<Character, Integer>();
mTest.put('b', 1);
m = Anagrams.countLettersInMap("b!");
assert m.equals(mTest);
// EDGE CASES: 1 (empty string)
mTest = new HashMap<Character, Integer>();
m = Anagrams.countLettersInMap("");
assert m.equals(mTest);
// EDGE CASES: 1 (non alphabetic character)
mTest = new HashMap<Character, Integer>();
m = Anagrams.countLettersInMap(" ");
assert m.equals(mTest);
// EDGE CASES: 1 (non alphabetic character)
mTest = new HashMap<Character, Integer>();
m = Anagrams.countLettersInMap("!");
assert m.equals(mTest);
}
@Test
public void testRoman() {
// From checker
assert Roman.convert( 7 ).equals("VII");
// From instructions
assert Roman.convert( 314 ).equals( "CCCXIV" );
assert Roman.convert( 3490 ).equals( "MMMCDXC" );
}
}
void someTest() {
// test exception is thrown (uses lambda expression)
assertThrows(yourException.class,
() -> whatEverShouldThrowAnException());
More formally:
@Test
void exceptionTesting() {
MyException thrown = assertThrows(
MyException.class,
() -> myObject.doThing(),
"Expected doThing() to throw, but it didn't"
);
assertTrue(thrown.getMessage().contains("Stuff"));
}
// version with longer code logic
public void itShouldThrowNullPointerExceptionWhenBlahBlah() {
assertThrows(NullPointerException.class,
()->{
//do whatever you want to do here
//ex : objectName.thisMethodShoulThrowNullPointerExceptionForNullParameter(null);
});
}
Source: Stack Overflow