for (int i = 0; i < arr.length; i += interval) { for (int j = i; j < i + interval && j < arr.length; j++) { // do something } // do something }
Calculate the submatrix sums fast
We can use a 2D prefix sum array. Each row of the 2D prefix sum array is a 1D prefix sum array for the corresponding row in the original matrix.
After initialization which takes $O(mn)$, calculating a submatrix sum takes $O(k)$, where k is the number of rows in the submatrix.
1 2 3 4 5 6 7 8
// given matrix[m][n] int[][] prefixSum = newint[m][n]; // init for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { // initialize each element in prefixSum[i] } }
int i = Integer.parseInt("000015640", 10); // 15640
Default initialization of an array in Java
Everything in a Java program not explicitly set to something by the programmer, is initialized to a zero value.
For references (anything that holds an object) that is null.
For int/short/byte/long that is a 0.
For float/double that is a 0.0
For booleans that is a false.
For char that is the null character '\u0000' (whose decimal equivalent is 0).
Initialize the capacity of a List
1
List<Integer> list = new ArrayList<>(10);
In this line of code, we initialize an array list with initial capacity of 10. Note that 10 is its capacity, not its size. So we still need to add elements one by one to this list. Assessing directly without adding any elements, such as directly calling list.get(1), will cause out-of-bound exceptions.
Reverse a List
1
Collections.reverse(list);
Create a List from an array
Take the return of Array.asList() as the parameter of ArrayList constructor.
1 2
int[] array = newint[10]; ArrayList<Integer> arraylIST = new ArrayList<>(Arrays.asList(array));
The point is that isLetter() will return false given a letter number. For example, roman numeral five (the letter looks like “V”). Certainly, for the English language, the distinction makes no difference.
Use Deque over Stack for LIFO stacks
We should use Deque rather than Stack for LIFO stacks.
1 2
Deque<Integer> dstack = new ArrayDeque<>(); Stack<Integer> sstack = new Stack<>(); // not recommended
There are many reasons to prefer Deque:
Deque is an interface but Stack is a class. So using Deque brings us more flexibility for future extension.
Stack is synchronized but Deque is not thread-safe. In the case of no need to ensure thread safety, Deque is more efficient.
Deque iterates elements from top to bottom. Stack iterates elements from bottom to top.
Most important: with Stack, we can access/insert/remove arbitrary elements in the LIFO stack by indexes, stack.get(index); stack.add(index, e); stack.remove(index), which breaks the LIFO rule. Although Deque does not absolutely obey the LIFO rule, it can only access/insert/remove the first/last element in the LIFO stack.
Print multi-dimensional arrays
1 2
System.out.println(Arrays.toString(arr)); // print a 1D array System.out.println(Arrays.deepToString(marr)); // print a multi-dimensional array
StringBuilder builder1 = new StringBuilder("abcdefg"); // if we want to delete c and add it back builder1.deleteCharAt(2); // "abdefg" builder1.insert(2, 'c'); // "abcdefg"
toCharArray() and getBytes()
toCharArray() is better if we are not dealing with characters outside of the Unicode BMP, which are encoded as two surrogate characters. getBytes() needs to specify encoding, which is prone to mistakes. Also, toCharArray() is faster because for Java 7 and newer, a String object contains a char array internally. toCharArray() just need to complete a copy operation.
Integer object comparison
For two Integer objects, == compares their references while < and > compare their values. To examinate whether they have the same value, we should use equals() or unbox them by intValue().
And, it is safe to use comparison operators (==, <, >) for comparing values between an int and an Integer object.
s.indexOf(pattern, fromIndex) returns the first index of given pattern from fromIndex (inclusive). If such pattern does not exist, it returns -1.
abstract keyword
If a class is declared abstract, it means that this class may be partially implementd. Thus, Java does not allow us to instantiate an abstract class. An abstract class can implement its constructor, functions (abstract or non-abstract) and have its variables.
An abstract function cannot have body. Any classes that declare any abstract functions must also be declared abstract. Any non-abstract classes that inherit abstract functions must implement all of them.
// the non-abstract subclass of an abstract class must implement all inherited abstract functions @Override publicvoidprintWorld(){ System.out.println("world"); } }
publicstaticvoidmain(String[] args){ // cannot instantiate an abstract class // Node n = new Node(); Node n = new ANode(1, "node1"); n.printHello(); n.printWorld(); }
Immutable objects
String and all primitive wrapper classes (Integer, Double, Long, Character, etc.) are immutable.
Inner class and nested class
An instance of inner class can exist only within an instance of its outerClass. The instance of the inner class has direct access to the methods and fields of its outer instance. A nested class can access all static resources of its outer class.
The difference between inner class and nested class is straightforward. Inner class has non-static features. Nested class has static features.
publicstaticvoidmain(String[] args){ // an instance of InnerClass can exist only within an instance of OuterClass // the instance of the inner class has direct access to the methods and fields of its outer instance TestInnerNested test = new TestInnerNested(); TestInnerNested.InnerClass inner = test.new InnerClass(); inner.print();
// a nest class can access all static resources of its outer class TestInnerNested.NestedClass nested = new TestInnerNested.NestedClass(); nested.print(); } }
Round a float number to n decimal places
Use DecimalFormat.
1 2 3
DecimalFormat df = new DecimalFormat("#.####"); df.setRoundingMode(RoundingMode.CEILING); System.out.println(df.format(15640.123456)); // 15640.1235
Traverse key-value pairs in a map
Use nested class Map.Entry<>.
1 2 3 4 5
Map<Integer, String> map = new HashMap<>(); for (Map.Entry<Integer, String> entry : map.entrySet()) { int key = entry.getKey(); String value = entry.getValue(); }
assert keyword
Do Not use assert in test. They can be activated at run-time by way of the -ea option on the java command, but are not turned on by default.
Split a string into at most 2 pieces
1
String[] arr = str.split(" ", 2);
Difference between Exception and RuntimeException
Any exception that derives from Exception is a checked exception. If a function throws an Exception in its body, it should also declare this behavior in this function declaration. Whereas a class that derives from RuntimeException is un-checked. RuntimeExceptions do not need to be explicitly handled by the calling code.
Generally RuntimeExceptions are exceptions that can be prevented programmatically.
floorEntry() and lowerEntry() of TreeMap
floorEntry(key) gets the entry corresponding to the specified key; if no such entry exists, returns the entry for the greatest key less than the specified key; if no such entry exists, returns null.
lowerEntry(key) returns the entry for the greatest key less than the specified key; if no such entry exists (i.e., the least key in the Tree is greater than the specified key), returns null.
Using a custom class as a key
To use a custom class as a key in Java Map, the custom class must define its equals and hashCode methods. Though Java provides an implicit implementation of these two methods for every class, the default implementation may lead to unexpected behaviors of Map (such as failing to find an existing key when inquiring with a new object with the same fields).