https://github.com/senocak/cracking-the-java-coding-interview
Cracking the Java Coding Interview
https://github.com/senocak/cracking-the-java-coding-interview
java jdk jdk11 jdk17 jdk21 jdk23 jdk8 jvm
Last synced: about 1 year ago
JSON representation
Cracking the Java Coding Interview
- Host: GitHub
- URL: https://github.com/senocak/cracking-the-java-coding-interview
- Owner: senocak
- Created: 2024-08-01T11:17:00.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-04-09T11:43:06.000Z (about 1 year ago)
- Last Synced: 2025-04-09T12:34:03.414Z (about 1 year ago)
- Topics: java, jdk, jdk11, jdk17, jdk21, jdk23, jdk8, jvm
- Homepage: https://www.youtube.com/watch?v=kXWl_Tv5wiU&list=PLX8CzqL3ArzX0zXLKycnQslZaF6viV0oQ
- Size: 233 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Cracking the Java Coding Interview
## 1. What is Java?
Short Answer
A programming language
Lesser Short Answer
An object-oriented programming language with some lists of functional programming in it and actually more and more. Object-oriented programming means four things `abstraction`, `encapsulation`, `inheritance` and `polymorphism` that Java supports all that. One restriction though, it does not support multiple linear returns meaning that one class can only extend one other class. And I have a last one for you, Java is a statically typed language meaning that the type of any variable you create or receive is known ad compiled time even if you define the type with vowel the compiler will guess the type of this variable for you
## 2. What is the Object class in Java?
Short Answer
The super class of every class you can create
Less Short Answer
When you create a class you can explicitly extend another class with the `extends` keyword. You can even declare that you extend the object class, this is fine it's dumb because you don't need it but it's legal.
Remember a class can only extend one class in Java, multiple linear returns is not allowed. If you do not declare that your class extends anything, which is fine, then the compiler will make your class extend the object class for you so in the end every class in Java extends the Object class
## 3. Can you cite methods from the Object class?
Short Answer
`toString()`, `equals()` and `hashCode()`
Less Short Answer
There are more. `getClass()` gives you the class of the subject `wait()`, `notify()` and `notifyAll()` these are used in concrete programming and never call these methods unless you really know what you're doing here. `finalize()`, that one you should not override it anymore because it is deprecated and whatever you put in this method is most of the time buggy, most of the time, and the last one is `clone()` same stay away from this method so in a nutshell `toString()`, `equals()` and `hashCode()` these are the most used ones
## 4. What are the differences between String and array of chars (char[])?
Short Answer
String is an object with many useful methods, An array only has methods from object and they are not very useful
Less Short Answer
String of character is non-modifiable in Java, once you've created one you cannot modify it. The size of an array is fixed, once created you cannot add elements to it, but you can replace one element by another.
- String is a class with useful methods that chat[] has not
- String is non-modifiable
How can you compare string? Just use their `equals()` method, trying to compare an array with its `equals()` method doesn't do what you would expect. You need to use `equals()` from the arrays factory class(`Arrays.equals()`) and the same goes for the `toString()` method, you need to use `toString()` from the same arrays factory class(`Arrays.toString()`) to properly print an array.
One last word, you can create a string a prominent array of chars by calling `new String()` and passing this array as an argument
```java
char[] letters = {'h', 'e', 'l', 'l', 'o'};
String hello = new String(letters);
```
## 5. How do you sum the elements of an array?
Answer
Two solutions are, a dumb one & old-fashioned that everyone knows, and a great one
- The first one iterate over the array, add the elements to the sum variable, don't forget to set it to zero at the start and you're done and the result is 10.
```java
int[] ints = {0, 1, 2, 3, 4};
int sum = 0;
for (int element: ints) {
sum += element;
}
System.out.println("sum = " + sum); // sum = 10
```
- The second one, make your stream from your array and just call `sum()`, of course the result is the same and by the way you can also call `min()`, `max()` and `average()` on the stream. Yes this is the one I prefer, it's simpler cleaner and more readable
```java
int[] ints = {0, 1, 2, 3, 4};
int sum = Arrays.stream(ints).sum();
System.out.println("sum = " + sum); // sum = 10
double average = Arrays.stream(ints).average().orElseThrow();
System.out.println("average = " + average); // average = 2.0
```
## 6. What is the JVM?
Short Answer
Java Virtual Machine
Lesser Short Answer
The piece of software that can run your Java code. The JVM does many things for you besides running your application among many other things. It handles the memory of your application with an element called the `Garbage Collector` or `GC`. It optimizes the code that you're running with another element called the `Just In Time` compiler or `JIT` and it handles the security of your application making sure that no undesired code can sneak in and be executed on your behalf.
One last word, if someone talks to you about HotSpot that's the name of the open sourced jvm developed by defaults at the Open JDK.
## 7. How can you sort an array?
Short Answer
There is a method for that called `Arrays.sort(tab)` that's all. Pass your retreat and that's it.
Less Short Answer
When you need to sort something, forget about writing a sort algorithm yourself. What about the best sorting algorithm?, that's actually a tough question but you don't need to worry about that because a `Arrays.sort(...)` does the job for you. Now if you really want to shine during an interview, you can cite three algorithms, `QuickSort`, `HeapSort` and `TimSort`. The one used in a `Arrays.sort(...)` is called `Dual Pivot Quicksort`.
One last word, never cite `BubbleSort` unless you want to say that it's a terrible algorithm
## 8. What is the main characteristic of the String class?
Short Answer
This class(String) is non-modifiable
Less Short Answer
There is no way to modify an instance of the string class that one it has been created so if you call `"string".toUpperCase()`, it does not change a string, it creates a new strings that holds the results. If you really want a string of characters that you can modify then you can use a specific class called `StringBuilder`. It's not a string it actually wraps an array of chars or bytes you can modify the content of this array and you can create a string from it by calling `toString()` on it.
One last word, you use a plus(`+`) to concatenate strings, forget about using the old string builder pattern, it's useless well most of the time
## 9. What is the difference between equally call(==) and equals()?
Short Answer
Equally called(==) compare the references and equals() calls a method
Less Short Answer
If you compare strings with equal equal(==), you may get the answer false even if the strings have the same value. In a nutshell equal equal(==) is good to compare things that are not objects, int, long and alike.
You should never compare floats or double with equal equal(==) when you need to compare floats or double, what you should be doing is compute the absolute value of their differences and check if it is lesser than a very small value.
```java
float d1, d2;
if(Math.abs(d1 - d2) < 1e-7) {
// d1 and d2 are equals
}
```
One last thing everything is a reference in Java so most of the time calling equal equal(==) on object is wrong
## 10. What is the relationship between equals() and hashCode()
Short Answer
Java specification says, if two objects are equals then they should have the same `hashCode()`
Less Short Answer
It means that when you override `equals()` then you should always override `hashCode()` as well. The Java spec says two objects that are equals must have the same hash code but the contrary is not true, you can have two objects with the same hash code but that are different.
One last thing, always use your IDE to write these methods, first your IDE, do not forget to override both methods and second it will give you a better implementation than the one you will write well most of the time
## 11. How can you duplicate an array?
Short Answer
You have two solutions `Arrays.copyOf()` and `System.arrayCopy()`
Less Short Answer
You have a clone method on Arrays `array.clone()` internally, it returns an object that is cast to the right type so performance wise it's not ideal. Both `Arrays.copyOf()` and `System.arrayCopy()` need a destination array in which they copy your source array. `Arrays.copyOf()` of can truncate your source array if it's bigger than the destination array or compact it if it's smaller. `System.arrayCopy()` has a richer API. It can copy a portion of your source array in the destination array.
One last word, `Arrays.copyOf()` calls `System.arrayCopy()` internally, so you can use the one you prefer
## 12. How can you reverse a String?
Short Answer
Wrap it in a `StringBuilder` and call `reverse()`
Less Short Answer
The String.class is non-modifiable, so you cannot change what the string is. All you can do is create another string and that is the reverse of the first one, looping over the letters of your string to reverse it is actually what the reverse method from `StringBuilder` is doing so don't bother re-inventing the wheel, it's there for you to use it. StringBuilder is a modifiable class so the letters are reversed internally.
One last word, to get the reversed string, you just need to call `toString()` on your StringBuilder object
## 13. What is the functional interface?
Short Answer
An interface with only one abstract method
Less Short Answer
Functional interfaces can be implemented with `Lambda Expressions`. Java is a statically typed language so all your variables have a type and all these types are known at compile time. The type of a Lambda is always a functional interface, no exception. A functional interface can contain any number of default all static methods, it can have any method from the object class as abstract methods and only one abstract method that is the one that your Lambda has to implement.
One last word, you can add the `@FunctionalInterface` annotation on your interface, the compiler will then tell you if you got it right or not
## 14. What is the difference between overriding and overloading?
Short Answer
`overriding` has to do with inheritance, `overloading` does not
Less Short Answer
`Overloading` is the same method with different parameters, `overriding` is the redefinition of a method from a superclass in a subclass. When your code calls a method with different overloads, the compiler decides which method to call so overloading is result at compile time. This is called early binding. Overriding is not, the compiler cannot resolve the call, it is result at runtime this is called late binding.
One last word, you can prevent a method from being overridden by declaring it final with the `final` keyword, you cannot prevent the method from having different overloads
## 15. What is a Map?
Short Answer
An object that maps keys to values
Less Short Answer
Map is an interface from the `collections` framework, it's canonical implementation is a `HashMap`. You cannot have duplicates among the keys of a map and a given key can map a single value. There is no concept of multi-map in the `collections` framework where a key can be bound to several value, but you can map a key to a list of values. Only use non-modifiable objects for your keys, small strings, a few characters are enough or longs prefer them over integers even for small values.
One last word, the `HashMap` class supports null keys and null values but please don't do that, it will put you in trouble
## 16. What is an ArrayList?
Short Answer
An implementation of the List interface backed by an array
Less Short Answer
ArrayList is sometimes called the dynamic array because when the internal array of an ArrayList becomes full, it is transparently copied in a larger array. Be careful though because this array can only grow, it never shrinks so when all the ArrayList can become really fat in your application and eat up a lot of memory.
One last thing, ArrayList is your best choice for List implementation, forget about LinkedList. LinkedLists are good for Stacks, we'll talk more on that another time
## 17. What is Finally? & Explain Finally?
Short Answer
`Finally` marks a block after a try block that is always executed when the try block exits
Less Short Answer
Always means even if there is a return, a continue, a break or an exception that causes the try block to exit. The finally block is the key tool to properly clean up resources that are not `Auto Closable`, your best choice to open an auto closable resource is the try-with-resources statement because it takes care of the closing of this resource for you. Resources that are not Auto-Closable should be released in a finally block that's the case for `ReentrantLock` for instance or for `Semaphores`.
```java
class Scratch {
public static void main(String[] args) {
System.out.println("average = " + age());
}
private static int age() {
try {
return 1;
} finally {
return 2;
}
}
}
// average = 2
```
One last word, in case of a return in the try block the finally block is evaluated after the return
## 18. How to make a class Immutable?
Short Answer
Use `records` if you can
Less Short Answer
If you cannot use record, make all the fields of this class `final` and don't forget to make this class `final` also because if you don't someone could add some mutable state to this class using inner returns and pass it around using polymorphism. Do not forget to make defensive copies of the modifiable objects you get as arguments in your constructor like Lists, Maps and the alike and the same for your accessors make sure they do not leak references to your internal state that could be modifiable, use a defensive copy where you need it.
One last thing, String, Integer, Long and all the wrapper classes of the jdk are non-modifiable, you can check them to see how they work
## 19. What is the difference between String and StringBuffer and StringBuilder?
Short Answer
`String` is non-modifiable, `StringBuilder` is modifiable and `StringBuffer` is thread safe
Less Short Answer
`StringBuffer` is rarely used. `StringBuilder` is nice for certain string manipulations like reversing(`reverse()`) a string or inserting(`insert()`) a character. Should you use StringBuilder to concatenate strings? Most of the time no, if you're using Java 9 and later, string concatenation with plus(+) has been optimized. If you're using Java 8, then in many cases concatenation with plus is in fact compiled with `StringBuilder`
One last word, if you are joining string elements from a List or an Array consider using `String.join()` the `StringJoiner` class and the `Collectors.joining()` collector.
## 20. How to make a Singleton?
Short Answer
One pattern, you use an `enum` with a single value
Less Short Answer
The pattern that uses a class with a private constructor, a private static field and a factory method that tests if the private field is new or not is more complex either non-thread safe or buggy or both. Making it thread safe using a double check locking is also buggy, just look for this bug on your favorite search engine. Using an enum is super simple, thread safe, guaranteed bug free at the jvm level and recommended by the best experts.
One last word, this any based pattern is used in many places in the jdk, you can check the source code of the `Comparator.naturalOrder()` factory method for example
## 21. What is a static method?
Short Answer
A method declared with the `static` keyword
Less Short Answer
A method that you can invoke without creating any object. You can invoke a static method with a class name, you can even invoke a static method through a null object. A static method cannot call a `non-static` method from the same class. Static methods are useful to implement processors or computations, some classes only have static methods like Math, Arrays or Collections.
```java
class Scratch {
public static void main(String[] args) {
Scratch scratch = null;
scratch.print();
}
private static void print() {
System.out.println("print...");
}
}
```
One last word, static methods are sometimes called Factory methods because they can be used to create objects in a certain way like `List.of()` that creates an empty list. Classes with only static methods are sometimes called Factory classes.
## 22. How can you find a character in a String?
Short Answer
There is a method for that called `indexOf()`
Less Short Answer
The `string.indexOf()` method has several overloads, one just take a character in the form of an int, another char and int because Java supports Unicode and some characters cannot be encoded on a single char, another one takes a string because `indexOf()` can also find small strings in bigger strings. Both can also take an index used to start the search from, indexOf returns the index or the first occurrence of the character or the string so if you want to find all the occurrences of a single letter you can loop in that way.
```java
public static void main(String[] args) {
String s = "abcabcabd";
int index = s.indexOf('b');
System.out.println("index: " + index);
while (index > 0) {
index = s.indexOf('b', index + 1);
}
System.out.println("index: " + index);
}
```
One last word, is the character or the string is not found index of returns -1
## 23. What is a method reference?
Short Answer
Another way of writing a Lambda expression
Less Short Answer
There are four kinds of method references;
- `static method references`, this operator can be written in that way, and it also works with other types
```java
DoubleUnaryOperator op = d -> Math.sqrt(d);
DoubleUnaryOperator op = d -> Math::sqrt;
```
- `bound method references`, the classical `System.out::println` is a bound method reference
```java
Consumer c = s -> System.out.println(s);
Consumer c = System.out::println;
```
- `unbound method references`, are they may look like static calls like this one, but they are not so be careful
```java
ToIntFunction f = s -> s.length();
ToIntFunction f = String::length;
```
- `constructor method references` like this one
```java
Supplier> sup = () -> new ArrayList<>();
Supplier> sup = () -> ArrayList::new;
```
One last word, to translate a method reference to Lambda, you need to know its exact type. One very last word, method references are there to improve the readability of your code so if you feel your code is actually less readable with them don't use them
## 24. What is the default method?
Short Answer
It's a regular method written in an interface
`Default method = Concrete methods in an interface`
Less Short Answer
Default methods have been added to the language in Java 8.
`Java 7: no default methods`
Prior to that all the methods in an interface had to be `abstract` so the abstract keyword for abstract methods is not mandatory in interfaces, for regular concrete methods you need to add the default keyword thus their name default method. Apart from that default methods are just regular methods. A default method from an interface can be used by any object that implements that interface, and they can be overridden in any concrete class.
One last word, in Java 8 default methods can only be `public` starting with Java 9 they can also be `private`
## 25. What does JIT mean?
Short Answer
JIT stands for `Just In Time Compiler`
Less Short Answer
What you have in a class file is the byte code of your class, this bytecode is first interpreted by your Java Virtual Machine. Running your Java code in that way is super slow so a first JIT compiler called `C1` compiled it to machine language. The C1 compiler does a nice job but your compiled code can be optimized even further. That's the job of a second JIT compiler `C2`. C2 carefully analyzes the way your code is running and compiles it again to leverage some more optimization.
One last word, if at some point C2 sees that it can do better, it will de-optimize your code and optimize it again
## 26. What kind of method can you override?
Short Answer
Instance methods
Less Short Answer
`static` methods cannot be overridden because you call them using an explicit class name so even if a Class B extends a Class A and defines the same static method you can still call each of them. Instance method can be overridden as long as they are non-private, non-final and that their class can be extended. The obvious way to prevent a class from being extended is to make it `final`, but you can also declare it's NoArgConstructor private.
```java
class Scratch {
public static void main(String[] args) {
System.out.println("A: " + A.name());
System.out.println("B: " + B.name());
// A: A
// B: B
}
}
class A {
public static String name() {
return "A";
}
}
class B extends A {
public static String name() {
return "B";
}
}
```
- Safe way: copy the method declaration
One last word, the safest way to override a method, just to copy its declaration in your extending class with the written type, the parameters and the exceptions, but you can be more certain than that and that will be for another time
## 27. What is the signature of a method?
Short Answer
Its name and its parameters
Less Short Answer
Neither the return type of a method nor its declared exceptions are part of its signature because all the methods of a given class must have different signatures, you can have several methods with the same name as long as they have different parameters and these methods can have different written types, but it is not legal to have two methods with the same name, same parameters and just a different return type because they would have the same signature.
```java
class Scratch {
public void print(String name) {
System.out.println("print:" + name);
}
// Compiled Error: 'print(String)' is already defined in 'Scratch'
public String print(String name) throws Exception {
System.out.println("print:" + name);
return name;
}
}
```
One last word, this rule holds even if one of this method is abstract because it would force the implementation to break this rule
```java
abstract class AbstractScratch {
public abstract void print(String name);
// Compiled Error: 'print(String)' is already defined in 'AbstractScratch'
public abstract String print(String name) throws Exception;
}
```
## 28. What is a marker interface?
Short Answer
An interface with no method that is just here to Mark a class
Less Short Answer
Being a marker interface is not really a language or an API notion, it's just a way of describing the nature of some interfaces. There are several examples in the JDK of such interfaces `serializable` of course that allows the instance of a class to be serialized and the `cloneable` that allows instances of a class to be cloned.
One last thing, because there is no method in these interfaces, you need to check if the object you have is an instance of this interface. It can be done with `instanceOf()` or directly at the class level with the method is assignable from defined on the class of Class (`Class.isAssignableFrom()`)
## 29. What is the difference between Collection and Set?
Short Answer
There are no duplicate elements in the Set
Less Short Answer
`Collection` and `Set` are interfaces from the collections framework. `Set` extends Collection all the instance method defined in the Set interface override method from collection and are re-defined to modify the semantic. They do not work in the same way. The set interface is implemented by `HashSet` which has another very interesting property, its implementation of the `contains()` method is super fast, much faster than the one from ArrayList.
One last word, if you need both the iterability property of ArrayList and the fast container implementation, you may take a look at the `LinkedHashSet` class which unfortunately is not a List.
## 30. How does finalize() work?
Short Answer
It does not work
Less Short Answer
`finalize()` has been deprecated in Java 9 and deprecated for removal in Java 18, so stop using it. `finalize()` is supposed to be a method called by some undefined elements when the garbage collector detects that an object is not reachable anymore.
Here are two of the major issues with finalizer; First, the thread running finalized is not specified those are that you can get race conditions in this method. Second, it may take a lot of time for this method to be called, the correctness of your code should never rely on the fact that finalize is called.
One last word, there is a replacement pattern called `The Cleaner Pattern`, you can check the cleaner class for more information
## 31. What are the main features of java 8?
Short Answer
Lambda Expressions
Less Short Answer
This version so Lambda expression added to the language but there are many other things that have been added to Java 8. The collections frameworks has been rewritten with many new features and methods. The stream API is a very clean implementation of `map`, `filter`, `reduce` that you can use in parallel. The completable future API is an asynchronous programming model added to the JDK and many many small things here and there to make your developer life better.
One last word, Java 8 was released in March 2014 as of this recording that was 9 years ago if you're still working on this version, you should really consider moving to a more recent one
## 32. Do streams and collections have common methods?
Short Answer
Yes and no, they do have one method that is called the same and take the same parameter
Less Short Answer
This method is called `foreach()`, it takes a consumer and you have it on both the `stream` interface and the `iterable` interface that being said even if they are basically doing the same thing, these methods are not implemented in the same way. Most of the time you can call directly `collections.foreach(...)` instead of calling `collections.stream().foreach()` that makes you save the creation of the stream object if you don't use it why would you want to create it.
```java
List letters = List.of("h", "e", "l", "l", "o");
letters.forEach(System.out::println);
letters.stream().forEach(System.out::println);
```
One last word, even if collections and streams are there to process data there are many differences between them but that's for another time
## 33. How can you tell that a string is an anagram of another string?
Short Answer
The easy way, sort the letters of the strings and just compare them
Less Short Answer
There is actually a much smarter way of doing that you can map each letter to prime number, for instance map A to 2, B to 3, C to 5 etc, then multiply all these numbers either two numbers you get are the same these strings are anagrams. It comes from the fact that the decomposition of an integer in a product of prime number is unique. The first method has a complexity of `n*log(n)` the second one is just `n` which is faster.
```
C -> 5
A -> 2
T -> 71
CAT -> 5*2*71 = 710
ACT- -> 2*5*71 = 710
```
One last word, be careful not to overflow when you're doing the multiplication, it can happen for long strings of characters
## 34. On what kind of source can you build a Stream?
Short Answer
There is no short answer, there are many sources
Less Short Answer
You can create streams on the following;
Collections of course this is the most common way but the jdk offers much more than that because you can also create a stream on the lines of a text file on the characters of a string of characters. On the elements of a string you split using a regular expression and several others plus. The stream API gives you what you need to connect the stream on your own source of data.
- Collections and array
- Lines of a text files
- Regular expressions
- You can build your own
One last word, be careful that the processing of a stream should not modify its source while it is consuming it. If you do that then the result you will get is unpredictable
## 35. What is the groupingBy()?
Short Answer
A collector, you can use to build maps that are in fact histograms from the elements of a stream
Less Short Answer
The pattern is `stream().collect(...)` and pass `Collectors.groupingBy(...)` and then you need to pass a function to this groupingBy(). This function maps each element of your stream to a key that is then added to your map. The corresponding element is itself added to a list bound to this key so if several elements of your streams are mapped to the same key you will find them together in this list.
```java
cities().stream().collect(Collectors.groupingBy(City::state))
// -> Map>
```
One last word, you can post process this list with another collector, pass as a second argument to this groupingBy(), this other collector is called the Downstream Collector.
## 36. What is the difference between FIFO and LIFO?
Short Answer
`FIFO` is a queue, `LIFO` is a stack
Less Short Answer
`FIFO` stands for `F`irst `I`n `F`irst `O`ut and `LIFO` stands for `L`ast `I`n `F`irst `O`ut.
There are two interfaces in the jdk to model these, queue, that models the FIFO that is extended by `deque` and that's the second interface that models for LIFO. The preferred implementation for both of these interfaces is `ArrayDeque` but it's not thread safe. If you need a thread safe implementation you can use a `ConcurrentLinkedQueue` for queue or `ConcurrentLinkedDeque` for deque.
One last word, there is a Stack class in a jdk that is an extension of the Vector class. Both `Stack` and `Vector` have been deprecated a long time ago, so you should not use them anymore
## 37. What is the GOF?
Short Answer
The nickname of the fundamental book on design patterns
Less Short Answer
The full title of this book is `Design patterns; Elements Of Reusable Object-Oriented Software`. It was published in 1994. The four authors are `Erich Gamma`, `Richard Helm`, `Ralph Johnson` and `John Vlissides`. This book contains a 23 design patterns in three categories;
- Creational: with the Builder, the Factory, the Singleton
- Structural; with the Adapter, the Decorator, the Proxy
- Behavioral; with the Iterator the Strategy, the Visitor.
One last word, this book is a must-read. The examples are written in C++ but it's easy enough to convert them to Java or to your favorite language
## 38. How can you create a Comparator?
Short Answer
Just use the factory methods of the `Comparator` interface
Less Short Answer
This interface has a bunch of factory methods to create comparators that compare objects using one of their fields, it also has default methods to modify the behavior of a given comparator. For instance, you can compare people using their last name and in case you have people with the same last name you can then compare them using their first name. In case you want to use this comparator to sort a list of people but need to sort them in the reverse order and then you can call reversed() on an existing comparator.
```java
var userComparator = Comparator
.comparing(User::lastName)
.thenComparing(User::firstName)
.reversed();
```
One last thing, null values are always painful to handle when you want to sort a list. The comparator interface has also a `nullsFirst()` and `nullsLast()`.
```java
var userComparatorWithNullsFirst = Comparator.nullsFirst(userComparator);
var userComparatorWithNullsLast = Comparator.nullsLast(userComparator);
```
## 39. Can you cite functional interfaces that existed before Java 8?
Short Answer
`Runnable`, `Comparator`, `Iterable`
Less Short Answer
They are actually more, the definition of a functional interface is such that some existing interfacers became functional with Java 8. Because you can implement a functional interface with a Lambda, it means that if you have old interfaces in your application that qualify for functional interfaces and then you can use lambdas to implement them without having to recompile them. That's why the `@FunctionalInterface` annotation is not mandatory on the functional interface.
One last word, you want more sure `Executor` even `Comparable` is a functional interface though I'm not sure that you want to implement this one with another expression
## 40. How can you open a file for writing some text?
Short Answer
There is a factory method for that in the `Files` class
Less Short Answer
There are actually two patterns; one from the old days of `java.io` and the less old one from `java.nio` and this is the one you should prefer. The exact pattern is the `Files.newBufferedWriter(...)` that takes a path as an argument, it has several overloads.
```java
var writer = Files.newBufferedWriter(
path,
StandardCharsets.ISO_8859_1,
StandardOpenOption.CREATE,
StandardOpenOption.APPEND
);
```
You can specify the Charsets used by your text file, the default value being utf-8 and you can specify some open options. Do you want to create the file if it does not exist and if it does do you want to erase its content or append to it?
One last word, what you get is still a buffered writer that you can still decorate if you need
## 41. What is the difference between a Sorted and an Ordered Collection?
Short Answer
Sorted means that you can compare your elements, Ordered means that you can access them using an index
Less Short Answer
It has to do with how you can iterate over the elements of your collection. The sorted collection gives you the smallest element first up to the largest one. If you add an element to a sorted collection, you may change the iteration order. An ordered collection on the other hand respects the order in which you add your elements so the first element is the first that has been added up to the last one.
One last word, ordered collections are modeled by the Lists in the collection framework, your favorite implementation is a `ArrayList` and sorted collections are modeled by NavigableSet implemented by `TreeSet`
## 42. How can you open a file for reading binary data?
Short Answer
There is a factory method for that on the `Files` class
Less Short Answer
The all patterns from Java 1.1 based on the decoration pattern are still there, but you should use the Files factory class to create your readers, writers, input stream and output stream.
```java
Files.newInputStream(path);
```
The implementations you will get are built on top of `java.nio` and they are going to give you better performances. You can still use The Decorator pattern if you need to build data input stream or data output streamed, gzip streams or streams that mixed text and data.
One last word, using the patterns from the Files factory class also give you final control on the opening of files on the `CharSet` you can use to read your text files and they are built to use the path object instead of file objects which is better
## 43. How can you print an array on the console?
Short Answer
Use the factory method from the `Arrays` class
```java
Arrays.toString(array);
```
Less Short Answer
An Array is an object but with a default `toString()` method that you cannot override so printing it on the console directly gives you something that you do not want. You can call `Arrays.toString()` and pass your array it will print the content of your array on called toString() on each element of this array if it is an object. If you are not happy with the formatting you then need to iterate on the elements of this array or create a stream on it and create the strings of characters you need.
```java
var result = Arrays.stream(new String[]{"one", "two"})
.map(Object::toString)
.collect(Collectors.joining(",", "{", "}"));
System.out.println(result); // {one,two}
```
One last word, you can use arrays in the foreach pattern, this pattern works for any object that implements the `iterable` interface, now interval declares a foreach method, but you cannot call it on arrays
## 44. How does a SortedSet work?
Short Answer
It is a Set that keeps its elements sorted
Less Short Answer
First point, it's a Set so it does not have any duplicates if you add two elements that are equal then the second one will not be added. Second point the elements you add must be Comparable or if they are not you must provide a comparator when you create your SortedSet. If you provide a comparator, it will be used even if your elements are comparable and when you iterate over them they will be sorted in the increasing order. As of Java 6, you should favor `NavigableSet` instead of SortedSet that gives you more method than total Sets.
One last word, the default implementation is `TreeSet` which implements a Red Black Tree
## 45. What pattern has been used to create the Java I/O API?
Short Answer
The Decorator Pattern
Less Short Answer
The Decorator Pattern is a `Structural Pattern` from the `Gang of Four` (GoF) book. A decorator is in fact a wrapper on an object that extends the class of that object, it may add more methods or change the way the existing methods are working. Wrapping an existing object means that it's constructor takes an object of the superclass as a parameter so it is both `an extension` and `a composition` for instance `BufferedReader` extends Reader and adds readline() method, plus the reading works with a buffer.
One last word, you should use the `Files` factory class to build the base objects, you need to read and write content to files, but you can still decorate them to add features to the base objects you get
## 46. What are the different categories of design patterns?
Short Answer
3 categories; `Creational`, `Structural`, `Behavioral`
Less Short Answer
It refers to the `Gang of Four` (GoF) book a must-read for every developer. Some creational patterns; `Factory`, `Builder` and `Singleton`, some structural patterns; `Decorator`, `Facade`, `Proxy`, some behavioral patterns; `Iterator`, `Template Method` and a well-known `Visitor`. The GoF gives you C++ implementations, some of them are updated but the ideas are still excellent.
One last word, there are many patterns that are so widely used that you use them even if you don't know them. That's the case for the Iterator Pattern or the Factory Pattern
## 47. How can you count how many times a letter appears in a String?
Short Answer
You need to iterate over the string in one way or another
Less Short Answer
Two ways; first, you can look for your letter in a string with `indexOf()` until you don't find it anymore. `indexOf()` may take an index where it will start its search that's a quick and efficient pattern. Second pattern, you can stream on the letters of the stream removing the letters that do not match and count the result, efficient, more functional, more readable, this is the one I prefer.
```java
public void countLoop(String sentence, int letter) {
int count = 0;
int index = sentence.indexOf(letter);
while (index >= 0) {
count++;
index = sentence.indexOf(letter, index + 1);
}
System.out.println(count);
}
public void countStream(String sentence, int letter) {
long count = sentence.chars()
.filter(c -> c == letter)
.count();
System.out.println(count);
}
```
One last word, the `count()` method return the long that you can safely cast to an end. A string of character is backed by an Array so there is no way you can have more than `Integer.MAX_VALUE` letters
## 48. What is a bucket in a Map?
Short Answer
A cell in an array
Less Short Answer
The HashMap class from the collections framework is backed by an `Array`, when you add a key to a HashMap a special hash code is evaluated for that key to choose which cell of the array will receive the key value pair. If there is already a different key value pair in this cell, this is called the `collision` and then a `LinkedList` is created to add this second pair and if there are too many, this LinkedList is actually replaced by your `Red Black Tree` to minimize collisions when the amount of key value pairs reaches `75%` of the size of the array then it is copied in a new larger array.
One last word, this copying incurs the re-hashing of all the keys present in a map which may be costly so be careful about that and try to create maps with the right size
## 49. What does Synchronized mean?
Short Answer
It is a keyword that prevents more than one thread to execute a given block of code at the same time
Less Short Answer
Synchronization has to do with concurrent programming, this block of code can be a delimited block inside the method or it can be the wall method static or not. All synchronized blocks need an object that they use as a key, you can use the same key for more than one synchronized block. In the case of a synchronized method then the key is the object itself or the class if the method is static. There are limitations with synchronized block that you don't have with `ReentrantLock` so we can use these objects instead.
One last word, never expose your key or your locks. It will help you prevent `Deadlocks` a situation that you absolutely want to avoid
## 50. What is the difference between a Collection and a Stream?
Short Answer
A collection contains an object, a stream is empty
Less Short Answer
A collection is meant to carry objects around with methods to handle them, most of the time your stream is an empty object that you can connect to a source of objects to process them. This source can be a collection, an array and many other things. You can even connect a stream to your own source of data if you need it. It will then process your elements one by one lazily. Some methods like `findAny()` or `allMatch()` can interrupt the processing of these objects.
One last word, there are actually two methods that need to remember the processed object; `distinct()` and `sorted()` so if you're using them then your stream will not be empty anymore
## 51. What is the difference between a File and a Path?
Short Answer
A File is a class and the Path is an interface
Less Short Answer
The File class is from Java 1.0 but is from `java.nio` released with Java 7. An instance of file is the same no matter what file system you're using because Path is an interface, the instance you build depends on the file system. You can get attributes that are specific to these file systems like security attributes. As of now, you should favor the use of path objects over file objects.
One last word, creating an instance of file all path does not create the corresponding file or directory on your disk, you need to call `createNewFile()` on the File class or the `Files.createFile()` Factory method that takes a path as an argument to do that
## 52. What is the difference between a Checked and an Unchecked Exception?
Short Answer
You need to write special code to handle the checked exception, not for unchecked exceptions
Less Short Answer
All your exceptions extend the `Exception.class` if an exception actually extends `Runtime` exception then it is an unchecked exception if it does not then it is checked exceptions. You need to handle your checked exceptions either by catching them or by declaring them in the `throws` clause of your methods and constructors. You do not need to do that for unchecked exceptions.
One last word, all these classes extend themselves the `Throwable.class` also extended by the `Error.class`. Errors are also unchecked exceptions but reserved for serious problems like Out Of Memory `OOM` error or Stack Overflow error
## 53. What is a Stream?
Short Answer
An object that implements the `map`, `filter`, `reduce` pattern
Less Short Answer
The stream consumes elements from a source and can do several operations, these operations are organized in a pipeline where each element is passed from one step of the pipeline to the next one. Mapping an element consists in transforming it, filtering consists in deciding if this element should be transmitted or not based on a predicate and reducing may consist in many things; summing the elements, extracting a min or a max or adding them to a list or a map.
One last word, the stream API allows you to conduct these computations in parallel, still you need to be careful with that as always when it comes to optimizations measure, don't guess
## 54. What is the hash code of an object?
Short Answer
A mapping of an object to an integer
Less Short Answer
The idea behind the hash code is to represent any object within it so that you can quickly tell if two objects are different by just comparing their hash code. Indeed, the specification says that two objects that are equal must have the same hash code but it turns out that two different objects may also have the same hash code so if two objects have different hash code then they cannot be equal but if they have the same hash code then you need to compare them to see if they are equal.
One last word, there are many ways of computing hash codes some are better than others, if you're not sure on what you need relying on your IDE to generate the hash code method is probably your safest choice.
## 55. What is an ExecutorService?
Short Answer
An object to which you can submit tasks to be executed in another thread
Less Short Answer
ExecutorService is an interface part of the `java.util.concurrent` API added to the `JDK 5` in 2004. It's the preferred way to run tasks in another thread. In fact, you shouldn't be creating threads by calling `new Thread()` anymore. A task can be either a `Runnable` or `Callable` that you can implement with a lambda expression, submitting a task gives you a Future object that you can use to get a result and exception if something goes wrong. All that you can use to interrupt the running of this task.
One last word, an ExecutorService is sometimes called the `Pool of Threads` and most of the time it is but it can also create threads on demand which is what it is doing for Virtual Threads for instance.
## 56. What is an Iterator?
Short Answer
An object used to iterate over the elements of a Collection
Less Short Answer
Iterator is an interface with three method; `hasNext()` that tells you if there are more objects to iterate over we should call this method first then if it returns true, you can call `next()` to get the next object and move the iterator one step. It also has a `remove()` method that can throw an `UnsupportedOperationException` you need that if your collection is immutable. Most of the time you use iterators for collections but iterators can actually be created without them. For instance, you can create a `RangeIterator` that can iterate over a range of integers.
```java
import java.util.Iterator;
public class RangeIterator implements Iterator {
private int index = 0;
public boolean hasNext() {
return index < end;
}
public Integer next() {
return index++;
}
}
```
One last word, the iterator pattern is actually a pattern from the `Gang of Four` (GoF) book. Did I already mention that this book is a must-read?
## 57. What are the 4 Java I/O based classes?
Short Answer
`Reader`, `Writer`, `InputStream` and `OutputStream`
Less Short Answer
These are the 4 abstract classes that define the basic operations for reading and writing characters and binary data. They have been designed in the mid 90s and you should not use them directly anymore. The preferred patterns that you should use are the factory methods from the `Files.class`, these are a `new BufferedReader()` and `new BufferedWriter()` for the reading and writing of characters and `new InputStream()` and `new OutputStream()` for the reading and writing of binary data. These factory methods give you instances built on top of `java.nio`
One last word, you can still decorate the instances you get following the general pattern of the `java.io` API
## 58. How many objects can you put in a collection?
Short Answer
It depends on the implementation you have
Less Short Answer
`Arraylist` is backed by an Array so the limit would be `Integer.MAX_VALUE`, you may be thinking that LinkedList would allow you to store more objects but in fact many things will fail for a LinkedList with more objects than `Integer.MAX_VALUE`. LinkedList counts its element with a field called `size` that is an int and bad things will happen if size reaches `Integer.MAX_VALUE`. The `toArray()` method from LinkedList will not work super well neither since Arrays are also indexed by int.
One last word, the same limit also exists from `Maps` but don't worry there is little chance that you can reach that limit without reaching other limitations in your application.
## 59. What is the maximum length of a String in Java?
Short Answer
It cannot be longer than `Integer.MAX_VALUE` because it is backed by an Array
Less Short Answer
First, that would be a very long string indeed and second the number of characters in a string may be different than the length of this array. The reason being there are many characters that are actually encoded on more than one byte.
One last word, the `String.class` changed in 2017 with Java9. The internal array used to be an array of chars 16 bits, it is now an array of bytes 8 bits. This optimization is called `Compact Strings` and can tremendously reduce the memory footprint of your application. One more reason to upgrade to the latest versions of the JDK.
## 60. How does a Set know that it already contains an element?
Short Answer
It uses the `hashCode()` of the object, if it finds something then it calls the `equals()` method
Less Short Answer
A HashSet stalls its objects in the cells of an Array. The index of the cell for a given object is computed from the `hashCode()` of this object. This process is very fast because it does not depend on the amount of elements you have in your Set. Of course there is a mechanism to handle collisions that is if two different objects happen to have the same hash code.
One last word, because of that HashSet will not work if you override `equals()` for your object without overriding `hashCode()` and one very last word, do not mutate an object once it has been added to a set because you will not be able to find it again
```java
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
class Scratch {
public static void main(String[] args) {
Set set = new HashSet<>();
Person person = new Person("John", 30);
set.add(person);
System.out.println("Set contains: " + set.contains(person)); // true
// Mutate the object after adding it to the Set
person.setName("Jane");
person.setAge(25);
// Try to find the object in the Set again
System.out.println("Set contains: " + set.contains(person)); // false
// The object is still in the Set, but we can't find it because its hash code has changed
System.out.println("Set elements: " + set);
}
}
/*
Set contains: true
Set contains: false
Set elements: [Jane (25)]
*/
```
## 60a. Ad Episode
Answer
Question number wait I actually did 60 questions that's one hour and one hour is probably longer than most Java coding interviews at least for the technical parts so that's great. Don't worry, there are so many possible questions to be asked that yes there is still plenty of content to cover.
I just would like to take a small break to let you know that I absolutely value your feedback and read all the comments you make so please keep them coming questions, suggestions, anything. Some questions in the comments actually became episodes so that's great thank you for that.
One last word, I created a playlist with all the episodes you can find a link in the descriptions and one very last word, next question 61 will be a real question so stay tuned for more
## 61. How is `Arrays.asList()` working?
Short Answer
`Arrays.asList()` wraps an array and exposes it as a List
- It does not copy it
Less Short Answer
First, you can call `Arrays.asList()` with a vararg but you can also pass an Array. Avoid passing an array of primitive types because what you will get is a list with a single element being the array itself. If you modify the array you pass then it will modify the list itself because as I said there is no defensive copy of this array. You can modify the elements of this list but you cannot `add` or `remove` elements from it because you know it's actually an Array.
One last word, so what you get with the `Arrays.asList()` is not an Unmodifiable List because you can still change its elements, if what you need is an Unmodifiable List you may consider using `List.of()`
## 62. Can you cite some methods from the Stream API?
Short Answer
The 3 basic methods are `map()`, `filter()` and `reduce()`
Less Short Answer
Those are that you will not use reduce match because you have many specialized method to reduce the elements of your stream like `toList()`, `forEach()`, `findFirst()` or `findAny()`. Other intermediate methods you can cite `flatMap()` of course `distinct()`, `sorted()` . 2 things you absolutely need to avoid. Avoid using `pick()` unless you need to debug your stream. `pick()` is useless in production, second don't do any side effect in any method of the stream API. It will put you in trouble.
One last word, you can also reduce your stream with the collector API, there are a bunch of available characters in the `Collectors` factory class and you can even create your own.
## 63. What is the `var` keyword in Java?
Short Answer
A keyword you can use in methods to avoid having to specify the type of a local variable
Less Short Answer
`var` is for local variables only, you cannot use it for fields for instance. You may use it for `Anonymous Classes` and in that case you will have access to the method you add in your Anonymous class that are not defined in the original type. The type of an Anonymous class is called the Non-Denotable type, you can add fields and method to it and access them if you declare your variable with the `var` keyword.
```java
var v = new Object() {
private int i = 0;
public int index() {
return i;
}
};
println("i = " + v.index());
```
One last word, you can use your IDE to see the type in further by the compiler and sometimes the result is unexpected
## 64. How can you create an Unmodifiable List?
Short Answer
With the factory method `List.of()`
Less Short Answer
There are actually several ways to do that but `List.of()` is the preferred one, be careful with the behavior of `Collections.unmodifiableList()` what it gives you is an unmodifiable view of a list but the list you give as an argument is not defensive copied so if you modify it then this modification will be seen through the view, on the other hand you can pass an array to `List.of()` that will be copied so no funny behavior there.
One last word, be careful because `List.of()` does not accept null values. Why would you put null values in a list? You will get an exception at runtime if you pass an array with a null value in it
## 65. How can you start a thread?
Short Answer
There is a `start()` method on a `Thread.class`
`Call start(), not run()`
Less Short Answer
Two things a thread is either built on a Runnable or is a Runnable itself, in both cases a common mistake is to call the run method instead of start. `run()` will execute your Runnable but in the current thread not in a new thread. Second, calling `start()` is okay for testing, learning and exploring how threads are working. In a production environment, you should not launch your threads by hand. You should use instead the `ExecutorService` Pattern.
One last word, JDK 21 adds new factory methods on the Thread class to create both `Platform` threads and `Virtual` threads, but that would be for another time
## 66. How can you create a file on the disk with Java I/O?
Short Answer
Use the `createFile()` factory method from the `Files.class`
```java
Files.createFile(...)
```
Less Short Answer
There is also a `createNewFile()` on the File class that is the legacy way of creating files. Creating a writer on output stream on a File can also create this file for you, once again the preferred pattern are in the Files factory class, you can check the `new BufferWriter()` or `new OutputStream()` factory methods they both take an open option arguments standard open options include read(), write(), append(), create() or createNew() among others.
One last word, depending on your file system, you can also pass 5 attributes to a file creation to handle security for instance
## 67. What is the class named Class?
Short Answer
The class that models classes
Less Short Answer
The JVM creates an instance of this class for each class it loads. The simplest ways to get a reference on the class objects is to call `getClass()` on any object but you can also use the class itself directly like `String.class` or call the `Class.forName("...")` method passing the name of the class as a string. In any case you always get the same reference to a given class there is only one instance of the Class.class that models the String class for instance.
```java
var c1 = "hello".getClass();
var c2 = String.class;
var c3 = Class.forName("java.lang.String");
```
One last word, the Class class is the entry point of the reflection API which gives you a way to manipulate objects reflectively, a technique that is used by many frameworks
## 68. How can you find duplicates in a List?
Short Answer
It really depends on what you need
Less Short Answer
You can check if your list has duplicates by putting this List in a Set and comparing the size of the set with the size of the list. You could also use a stream calling `distinct()` and count()` method on it which also builds the Set internally. If you need to find the duplicate elements themselves then you need to build an histogram of these elements, create a stream on the list and group the elements by themselves counting them with the counting character.
```java
List list = ...;
Map histo = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
```
One last word, these techniques are all using Maps, a Set is in fact a map. With maps you can solve this problem in one pass over your data but you consume more memory. As usual there is a trade-off between computing time and memory conception.
## 69. What is a Sealed type?
Short Answer
A type that knows all of its extensions
Less Short Answer
It can be any type interface, class or abstract class. You need to declare it with the `sealed` keyword and then declare the permitted types with the `permits` closer. Now there are constraints on these permitted types; first, they need to be declared in the same package or in the same module. Second they need to be either `final`, `sealed` or declared `non-sealed enum and records are actually final types so you cannot create an open hierarchy by accident, the non-sealed declaration is there for that.
```java
sealed interface Shape permits Circle, Square, RandomShape {}
final class Circle implements Shape {}
record Square implements Shape {}
non-sealed class RandomShape implements Shape {}
```
One last word, seal types are enforced both at `compile time` and at `runtime`
## 70. How is `List.of()` working?
Short Answer
It takes an Array or a vararg and makes a defensive copy to create an Unmodifiable List.
Less Short Answer
You can use it with a vararg to create a pre-filled list but you can also pass an array, in that case remember that if it is an array of primitive types what you get is a list with one element which is your array probably not what you want. This List implementation does not accept null values, sometimes your IDE can warn you about that but in certain cases it cannot and you will get an exception at runtime.
```java
public static void main(String[] args) {
int[] intArray = {1, 2, 3};
List intsList = List.of(intArray);
System.out.println(intsList.size()); // > 1
}
// or
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3};
List intsList = List.of(intArray);
System.out.println(intsList.size()); // > 3
}
```
One last word, you can also create sets with `Set.of()` that works in the same way as `List.of()` and modifiable defensive copy and null values not allowed.
## 71. What is the difference between Runnable and Thread?
Short Answer
`Runnable` is an interface and `Thread` is a class
Less Short Answer
The Runnable is a model for a task you can implement it with Lambda that does not take anything and returns nothing. You can execute this lambda by calling its `run()` method. You can then create a thread object passing your runnable as an argument and then execute this runnable in this thread by calling the `start()` method of that thread object. Be careful not to use the `thread.run()` method, it will execute your runnable but in the current thread.
```java
Runnable task = () -> System.out.println(Thread.currentThread().getName());
// or
Thread t = new Thread(task);
t.start();
t.run() // NO !!
// or
ExecutorService service = ...;
service.submit(task);
```
One last word, this pattern is okay for playing with threads and understanding how they work. In a real application, you should use the `ExecutorService` pattern instead of this one
## 72. What is the difference between `map()` and `flatMap()`?
Short Answer
These are 2 methods from the stream API to map objects of a given type to objects of another type
Less Short Answer
`map()` is super simple, it takes a function like `String::length` that maps strings of characters to their name.
```java
var lengthOfStrings = Stream.of("one", "two", "three")
.map(String::length)
.toList();
```
`flatMap()` works differently, it maps one-to-many relationships. The mapping function should itself return a stream of something and these streams are flattened by the flatMap() method, for instance given a stream of countries you can flatmap this stream to a stream of cities.
```java
record Country(List cities) { }
List countries = ...;
List cities = countries.stream()
.flatMap(country -> country.cities().stream())
.toList();
```
One last word, a mapping does not change the number of objects your stream processors, where a flatmap does. It can even produce zero elements
## 73. How is synchronization working?
Short Answer
It works with the key held by the object you synchronize your block of code with
Less Short Answer
This key is called the `monitor`, when a thread reaches a synchronized block or a method, it asks this object for its key. If the key is available, it takes it and run the code, if not it will have to wait until the key comes back. You absolutely want to avoid situations where the key never comes back usually because of `Deadlocks` but not only. In the case of an instance method, the object that holds the key is simply `this` and in the case of a static method, the object is the `class`.
One last word, try avoid synchronizing on objects that are public. That's a good rule to prevent Deadlocks, a situation you absolutely want to avoid
## 74. What is a generic type?
Short Answer
A type that is parameterized over times
Less Short Answer
Once defined along with the class, you can use this parameter in the class itself to define instance fields or instance methods. A single type can be parameterized over several types. Generics are massively used in athe JDK, all the collection framework, the stream API are using generics so you can check these classes to see how you can use them and how they were created.
```java
class Box {
void process() {
Class c = T.class; // NO !!
T t = new T(); // NO !!
T[] ts = new T[10]; // NO !!
}
}
```
One last word, the type `T` is actually erased, it is replaced by object at runtime so there is a number of things you cannot do in your code. You cannot try to get the class of T because it will just return object, you cannot call `new T()` or `new Array` neither
## 75. How can you stop a thread?
Short Answer
You can't and you should not
Less Short Answer
There are two methods on the thread class; `stop()` and `suspend()` that have been deprecated in Java 2 1998 that is more than 25 years ago. Now throw an `UnsupportedOperationException` so don't even think about using them. Why? the answer is actually not that simple. In short, they have been deprecated mainly for security reasons. Being able to stop a thread could put your application in an unpredictable state something you absolutely want to avoid.
One last word, you are not supposed to start no stop your threads by end anyway. The pattern you should be using is the `ExecutorService` pattern that takes care of your thread life cycle for you
## 76. How can you remove elements from a Stream?
Short Answer
Use the `filter()` method
Less Short Answer
Be careful though because the stream does not contain any object, it consumes objects from a source so saying removing objects from a stream is actually not correct what you're really doing is telling your stream do not process certain elements. Filtering uses a predicate that tests certain properties of the object and decide if it should be further processed or not. On this example, you only want to process the non-empty strings.
```java
Predicate isEmpty = String::isEmpty;
Predicate isNonEmpty = isEmpty.negate();
List strings = ...;
List nonEmptyStrings = strings.stream()
.filter(isNonEmpty)
.toList();
```
One last word, there are actually 2 other patterns that you can use to do that. `flatMap()` and `mapMulti()`. They are not really meant for that but in certain cases they can work better than filter
## 77. How is `Set.of()` working?
Short Answer
It builds a set of its arguments if there are no duplicates among them
Less Short Answer
The arguments are added one by one to an array of the right size using the `hashCode()` to detect any duplicates, if a duplicate is detected an `IllegalArgumentException` is immediately thrown. This method only requires one pass over your data because duplicates are not allowed in your arguments, it can create an array of the right size upfront making the memory conception minimal so all this is pretty optimal.
```java
public static void main(String[] args) {
int[] ints = {1, 2, 3};
Set set = Set.of(ints);
System.out.println(set.size()); // > 1
}
// or
public static void main(String[] args) {
Integer[] ints = {1, 2, 3};
Set set = Set.of(ints);
System.out.println(set.size()); // > 3
}
```
One last word, as usual be careful if you pass an array of primitive types because you will get a Set with a single element to your array which is usually not what you want.
## 78. How can you join Strings with a separator?
Short Answer
You have a `join()` a factory method for that on the String class directly.
```java
List strings = List.of();
var stringWithSeperator = String.join(",", strings);
```
Less Short Answer
There are 2 overloads of this method, they both take a `delimiter` as a first argument and then you can pass a varargs or an array that's the first overloader or an iterable typically a collection and that's the second overload. If you need to add a prefix or a postfix to your string of character and then you can check the `StringJoiner.class` you can also reuse this StringJoiner if you have many strings to process.
```java
List strings = List.of();
var joiner = new StringJoiner(",", "{", "}");
strings.forEach(joiner::add);
var stringWithSepPrefxSuffx = joiner.toString();
```
One last word, you can also check the collect `Collectors.joining()` pattern which does the same for the stream API. That's useful if you need to create this stream lazily without you having to buffer everything in a collection
```java
List strings = List.of();
var stringWithSepPrefxSuffx = strings.stream()
.collect(Collectors.joining(",", "{", "}"));
```
## 79. How can you modify your field using the Reflection API?
Short Answer
You can use the `set()` method of the field class to do that
`Field.set(obj, value)`
Less Short Answer
This method takes the instance you want to operate on and the value you want to fix, if you do not have access to this field because it is private for instance, you can still change it by calling its `Field.setAccessible(true)` passing true as an argument. It does not make the field public but suppresses the access controls made by the language.
One last word, you can actually mutate final fields in regular classes which this pattern which is really annoying but records are `protected` against that you cannot mutate them, one more reason to use records wherever you can
## 80. How can you declare a generic type on a Static Method?
Short Answer
You need to define the type parameter along with the method declaration
Less Short Answer
The type parameters you define on a class are only seen by the instance, fields and methods not by the static members. Suppose you have a Box class and you want to define the static method copy(). To define the type parameter for this method you need to add it after the static keyword not also that if you have several static methods, each one needs to declare its own type parameter.
```java
class Box {
private T t;
Box(T t) {
this.t = t;
}
static Box copy(Box box) {
return new Box<>(box.t);
}
}
```
One last word, you have many examples of that in the jdk, in the collections class for instance. They also use this word syntax question marks Super T `? super T` and question marks extensity `? extends` but that will be for another time
## 81. What does passing by value mean?
Short Answer
It means that what you pass to a method is the value not a reference to this value
Less Short Answer
The consequence is that if your method modify the argument it gets, the calling code does not see this modification, if what you pass is a primitive type changing it in your method does not change the value in a calling code. If what you pass is a reference changing the reference itself does not change it in a calling coder but if you change the content of the object reference then this change is seen in a calling code.
```java
class Scratch {
public static void main(String[] arg) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
System.out.println("3" + aDog.getName().equals("Max"));// true
System.out.println("4" + aDog.getName().equals("Fifi"));// false
System.out.println("5" + (aDog == oldDog)); // true
}
public static void foo(Dog d) {
System.out.println("1" + d.getName().equals("Max")); // true
// change d inside of foo() to point to a new Dog instance construct red with name member variable set to "Fifi"
d = new Dog("Fifi");
System.out.println("2" + d.getName().equals("Fifi")); // true
}
}
class Dog {
private String name;
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
1true
2true
3true
4false
5true
*/
```
One last word, Java passes by value always no exception
## 82. What is the difference between an intermediate and a terminal operation?
Short Answer
An intermediate operation returns a stream, the terminal operation returns something else including void
Less Short Answer
The stream processes the data from the source only when it executes its terminal operation. If you do not call the terminal operation no data is processed, you can only call one intermediate or terminal operation on a given stream object. It makes the storing of a stream in a local variable useless.
One last word, some terminal operations do not need to call the intermediate operations of your stream. The reason why you should not do any side effect in an intermediate operations, there are situations where they will not be executed
## 83. What list can you pass to a method that takes a List of Number `List`?
Short Answer
List is certainly not List even though Integer extends Number
Less Short Answer
Even if a Type U extends a type T, a `List` does not extend the List. The reason is that within the method that takes a list of numbers, you could add a float to that list but then if you pass a list of integers at runtime, you actually end up trying adding a float to a list of integers that would cause an exception.
```java
void process(List list) {
list.add(3.14f); // Legal
}
List ints = ...;
process(ints); // COMPILE ERROR
```
One last word, you could change your method and declare that it takes a list of question marks extends number(`List extends Number>`) and in that case you will be able to pass the list of Integer, Double and alike
```java
void process(List extends Number> list) {
...
}
List ints = ...;
process(ints); // ok
```
## 84. What is a DeadLock?
Short Answer
A situation where a first thread holds the lock and needs the second one to carry on its task and the second thread is holding that second lock and is waiting for the first one to carry on with its task
Less Short Answer
This situation is really very bad, most of the time your solution would be to reboot your application, so you absolutely want to avoid it. It can also occur with the second lock that is outside of your application like in your database for instance.
One last word, one word of sound to avoid that never expose your locks as a public elements. Always use private fields to store your locks, it will help you most of the time but not always unfortunately.
## 85. How can you create an object instance of a given class using the Reflection API?
Short Answer
There is a pattern for that called `getDeclaredConstructor()` that gives you a reference on the empty constructor of this class and called `newInstance()` on it.
Less Short Answer
The pattern that consists including `newInstance()` directly on the class itself has been deprecated in Java 9 mostly because it does not handle exceptions properly. If your class does not have an empty constructor then this pattern throws a `NoSuchMethodException` exception.
```java
class Box {
Box(String s) {
// ...
}
}
public static void main(String[] args) {
var c = Box.class;
var ctor = c.getDeclaredConstructor(String.class);
Box box = ctor.newInstance("Hello");
c.newInstance(); // @Deprecated(since="9")
}
```
One last word, you can also get a reference on the other constructors of your class by passing the parameters they take as classes to `getDeclaredConstructor()` method
## 86. What is the difference between a Collection and a List?
Short Answer
A List is ordered, a Collection is not
Less Short Answer
Ordered means that the order in which you iterate over the elements is stable from one iteration to the other and corresponds to the order in which you added the elements to your list. It is the case for all Lists because that's the specification but it's not the case for `HashSet` for instance and because the HashSet is a collection not all collections have this behavior. Adding elements to a HashSet may change the iteration order all the other elements so it's not even stable from one iteration to the other.
One last word, the consequence is that you can access the elements of your list using an index that wouldn't make sense for our Sets.
## 87. What is the difference between the `toList()` and collect `Collectors.toList()`?
Short Answer
Both are terminal operations of the stream API. `Collectors.toList()` producers an Arraylist and `toList()` produces a Non-modifiable List.
Less Short Answer
The fact that `Collectors.toList()` producers on ArrayList is actually not specified but it's the case. There are cases where `toList()` is actually more efficient, in a case where you know how many elements your stream is going to process, `toList()` can create an array of the right size up front, where `Collectors.toList()` relies on the automatic growing of your ArrayList.
One last word, the streamed `toList()` method produces a non-modifiable list that accepts null values, not all non-modifiable lists accept them `List.of()` doesn't for instance.
## 88. Can you compare Integers and Doubles with a Comparator of Numbers?
Short Answer
Yes
Less Short Answer
This is fine because what you are defining is a method that takes two parameters of type Number and it's fine to call it with any extension of number, actually you could use such a comparator to define the comparison between integers and floating point numbers for instance. Such a comparator is also okay to sort any list of integers of floating point numbers because all these types extended Number.
One last word, don't make your comparator a `Comparator extends Number>` because in that case you will not be able to call it with any other wrapper types. There is a good reason for that but that will be for another time
## 89. How can you model the Concurrent tasks in Java?
Short Answer
You have two interfaces for that `Runnable` and `Callable`
Less Short Answer
Both have functional interfaces so you can implement them with lambdas, neither of them take any parameter.
```java
Runnable runnable = () -> {doSomething();};
Callable callable = () -> {return anInt();};
```
A Runnable does not return anything and does not throw any exception. A Callable on the other hand can return a value and throw an exception.
Runnable is the only task you can pass to the constructor all the builder of a thread. Callable and Runnable can be passed through an `ExecutorService` or `StructuredTaskScope`.
```java
var thread = Thread.ofVirtual().start(runnable);
ExecutorService service = ...;
service.submit(runnable);
service.submit(callable);
```
One last word, when you submit a task to an ExecutiveService, you get a Future object in return something we will talk more about in the future precisely
## 90. What is an Annotation?
Short Answer
An interface with methods on which you can define default values
Less Short Answer
```java
@Retention(RetentionPolicy.RUNTIME) // when
@Target({
ElementType.FIELD,
ElementType.METHOD,
ElementType.CONSTRUCTOR
}) // where
@interface Range {
int begin() default 0;
int end();
}
```
You can define your own annotations easily with methods that may return default values, along with your annotation you need to define two things where you can add this annotation in your code and when you want to access it. There are currently 12 places where you can add an annotation for instance Fields, Classes, Methods or Parameters are among them then you can declare that you will need to use your annotation at runtime or only when your class is loaded or at compile time.
One last word, at Runtime you need to use the reflection API to get the annotations added to an element of your code, a technique used by many frameworks; Hibernate or SpringBoot just to name a few
## 91. What is a `? extends T`?
Short Answer
It is a type called the wild card that has been created to extend a parameter's type by itself with an extension of its parameter
Less Short Answer
Suppose you have two types `T` and `U` and `U extends T`, a class parameterized on U does not extend the same class parameterized on T. `Box does not extend Box`
```java
import java.util.List;
static List convert(List numbers) {
return numbers.stream()
.map(Number::longValue)
.toList();
}
public static void main(String[] args) {
List doubles = List.of();
// DOES NOT COMPILE !!!
var longs = convert(doubles);
// Required type: List
// Provided: List
}
```
Look at this convert method, it could accept a list of double. We can fix that with a list of question mark extends number `? extends Number` because list of double extends a list of question mark extend number.
```java
import java.util.List;
static List convert(List extends Number> numbers) {
return numbers.stream()
.map(Number::longValue)
.toList();
}
public static void main(String[] args) {
List doubles = List.of();
// OK
var longs = convert(doubles);
}
```
One last word, this technique is extensively used in a collection framework and in along the world, comparators, consumers, predicates functions their old use wild cards.
```java
public static void sort(List list, Comparator super T> c) {}
default Consumer andThen(Consumer super T> after) {}
default Predicate and(Predicate super T> other) {}
default Function compose(Function super V, ? extends T> before) {}
```
## 92. What is a Constructor?
Short Answer
An element of a class that is called when an instance of this class is built
Less Short Answer
Be careful, because the `Constructor` is not a method. It does not have a written type and is not compiled in the same way. You can have several overloads of a constructor in a class, all they need is declare different parameters. Constructors can throw exceptions so if you want to do some validation to prevent corrected objects to be built, you can do that in your Constructor.
One last word, you can write compact constructors in Records which is a very nice and very simple syntax to write constructors that only do some validation, one more reason to use Records wherever you want
## 93. What is a short-circuit method?
Short Answer
Several methods from the Stream API are called short-circuit methods
Less Short Answer
These method may interrupt the conceptions of the elements of your source. There are 2 intermediate operations `limit()` and `takeWhile()` and 5 terminal operations of `allMatch()`, `anyMatch()` and `noneMatch()` plus `findFirst()` and `findAny()` because elements are processed lazily and one by one by the stream API, short-circuit operations can prevent some elements to be read from your source which may be really bad if you are doing some side effects in your intermediate operations.
One last word, doing side effects in a stream intermediate or terminal operations is always a bad idea. Don't do it
## 94. What is an Atomic variable?
Short Answer
A wrapper on a primitive type or a reference with methods to mutate it in a thread safe and efficient way
Less Short Answer
The atomic variables are actually mappings of CPU operations also called `CASing` operations. CASing means `C`ompare `A`nd `S`wap. For instance, on atomic integer you can call `increment()` and `get()` that will increment the internal value and return it atomically. This operation is thread safe, it does not rely on synchronization which prevents thread contention.
One last word, atomic references are used to implement two thread safe structures from the collection framework; `ConcurrentSkipListMap` which is a Map and `ConcurrentSkipListSet` which is a Set, all these without any synchronization
## 95. What is a Record?
Short Answer
Something you should use all the time
Less Short Answer
It is a class that carries some immutable state declared along with its declaration. This state is called the Components of your record. A record cannot extend anything and cannot be extended but it can implement any interface. It cannot declare an instance field, static fields are okay and it can declare any method. The compiler gives you a constructor accesses that you can rewrite yourself and `toString()`, `equals()` and `hashCode()` for free. You can do some validation and deserialization, calls this constructor so no corrupt record in your application.
```java
record Range(int begin, int end) implements Serializable {
Range {
if (begin > end) {
throw new IllegalArgumentException("...");
}
}
int size() {
return end - begin;
}
}
```
One last word, use records wherever and whenever you can
## 96. How can you invoke a method using the Reflection API?
Short Answer
There is an `invoke()` method in the `Method.class`
Less Short Answer
We can get a specific method of a class with the `getMethod()` or `getDeclaredMethod()` of the class named Class. You need to pass the name of the method you want along with the types of its parameters. When you have a method object all you need to do is call the invoke() method passing first the object on which you want to invoke this method and then the arguments needed by this method. We can invoke a private method from outside the class by first calling the `setAccessible(true)` which removes the visibility checks.
```java
import java.lang.reflect.Method;
public static void main(String[] args) {
var c = String.class;
Method indexOf = c.getMethod("indexOf", String.class);
var message = "Hello world";
var index = indexOf.invoke(message, "world");
// output: 6
}
```
One last word, you also have another pattern to do that that uses the method and all class but that would be for another time oh
## 97. What is a ConcurrentModificationException?
Short Answer
An exception raised when you modify your collection while iterating over it
Less Short Answer
Be careful because despite the name, it has nothing to do with concurrent programming. Removing elements from a collection while iterating over it is generally not a great idea. There is a `remove()` method on iterator that you can use just make sure that it is supported by your implementation if what you need is to remove elements using your predicate for instance, you can use the `removeIf()` method that does exactly that.
```java
import java.util.ArrayList;
import java.util.List;
public static void main(String[] args) {
var list = List.of("1", "2");
list = new ArrayList<>(list);
var iterator = list.iterator();
while (iterator.hasNext()) {
var s = iterator.next();
list.remove(s); // Exception in thread "main" java.util.ConcurrentModificationException
list.removeIf(String::isEmpty);
if (s.isEmpty()) {
iterator.remove();
}
}
}
```
One last word, some implementations of collection can be okay with removing elements while iterating over them, especially the concurrent ones like `ArrayBlockingQueue` or `ConcurrentLinkedQueue` so be sure to check the javadoc on this one
## 98. What is a Collector?
Short Answer
An object provided by the Stream API that you can use to reduce streams using the `collect()` method
Less Short Answer
A collector is an implementation of the `Collector` interface, you can implement this interface yourself. You also have a collector's factory class with plenty of pre-built collectors that should cover most of your needs. You can do many things with collectors; you can create any sort of collections or maps, you can group your stream elements using keys and gather them in maps or you can join them in strings of characters. You even have collectors that can map, filter or flatMap the elements of your stream.
One last word, sometimes the stream API uses DownStream Collectors, this is a way to compose collectors but that will be for another time
## 99. What is a Daemon Thread?
Short Answer
A Thread
Less Short Answer
When you create a thread, you can decide to set its daemon property to true, the JVM will start its shutdown sequence if it does not have any more non-daemon thread running. The thread main for instance that runs your main method is a non-demand thread so when you exit your main method the JVM shuts down. Non-Daeman thread keep your JVM alive that can be created in ExecutorServices for instance so don't forget to shut them down or your JVM will never shut down. 2 examples of the Daemon thread; the ones that are running your Garbage Collector or your Just In Time(`JIT`) compiler.
One last word, you can set the daemon property of a platform thread but a virtual thread is always a daemon thread
## 100. What is a Race Condition?
Short Answer
A race condition occurs when two threads are writing and reading the same variable at the same time
Less Short Answer
This is a situation you need to take care of because it can put your application in an inconsistent state. Suppose that you are incrementing a simple counter, you first read its value increment it and write it back if two threads are doing that in two different calls of your CPU. They may be reading the same value and what you will see is one incrementation instead of two. To prevent race conditions, you need to guard your variables with synchronization or use atomic variables.
One last word, in Java, race conditions can only happen on the fields of your classes not on local variables. It can be different in other languages
## 101. How can you check if a class is an extension of another?
Short Answer
There is a method for that in a `Class.class`
Less Short Answer
This method is called `isAssignableFrom()` you call it on a class instance which could represent an interface by the way and pass another class instance as an argument. `isAssignableFrom()` checked if an instance of the argument class you pass can be assigned to a variable of the type you are calling this method on, for instance you can check if you can assign a string object to a variable of type comparable with the following code.
```java
public static void main(String[] args) {
var v = Comparable.class;
var checked = String.class;
boolean b = v.isAssignableFrom(checked);
// the compiler knows b is true!
// use it for types unknown
// at compile time
}
```
One last word, this is a method that you should use with types that you don't know at compile time, if you do then you probably don't need it
## 102. What is the type `? super T`?
Short Answer
This type represents all the types that are super types of T
Less Short Answer
This is the kind of type you need when you need to define the type of an object that you consume. Suppose that you have a list of polygon objects, you know that all the objects of this list can be cast to the polygon type. Processing them with a consumer of shape will then be okay thus the forEach() method take