Files
ReadLines
ReadFile and convert to stream
Stream
Array to stream
- Group employees of a company and group them by their facility
- Join string
Once the stream has been ended, we can’t execute it again.
Method | Purpose |
map | Transforms the elements in the stream by applying a given function to each element. |
filter | Filters elements in the stream based on a predicate (a boolean-valued function). |
forEach | Performs an action for each element in the stream. |
collect | Transforms the stream into a different kind of result, like a Collection or an object. |
reduce | Performs a reduction on the stream elements using a binary operator and returns an Optional. |
findFirst | Returns an Optional for the first entry in the stream. |
anyMatch | Returns whether any elements of this stream match the provided predicate. |
allMatch | Returns whether all elements of this stream match the provided predicate. |
noneMatch | Returns whether no elements of this stream match the provided predicate. |
findAny | Returns an Optional describing some element of the stream, or an empty Optional if the stream is empty. |
count | Returns the count of elements in the stream. |
sorted | Returns a stream consisting of the elements of the original stream, sorted according to natural order or a provided comparator. |
flatMap | Transforms each element of the stream into a stream of other objects. |
distinct | Returns a stream consisting of the distinct elements of the original stream. |
limit | Returns a stream that is no longer than a given size n. |
skip | Returns a stream consisting of the remaining elements of the original stream after discarding the first n elements. |
peek | Returns a stream consisting of the elements of the original stream, additionally performing an action on each element as elements are consumed from the resulting stream. |
Collect results
Method | Purpose |
toList() | Collects stream elements in a List. |
toSet() | Collects stream elements in a Set. |
toMap() | Returns a Collector that accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements. |
collectingAndThen() | Collects stream elements and then transforms them using a Function |
summingDouble() , summingLong() , summingInt() | Sums-up stream elements after mapping them to a Double /Long /Integer value using specific type Function |
reducing() | Reduces elements of stream based on the BinaryOperator function provided |
partitioningBy() | Partitions stream elements into a Map based on the Predicate provided |
counting() | Counts the number of stream elements |
groupingBy() | Produces Map of elements grouped by grouping criteria provided |
mapping() | Applyies a mapping operation to all stream elements being collected |
joining() | For concatenation of stream elements into a single String |
minBy()/maxBy() | Finds the minimum/maximum of all stream elements based on the Comparator provided |
If we are sure that our function is going to return a primitive, instead of using
map()
use mapToInt()
, mapToLong()
or mapToDouble()
.anyMatch()
allMatch()
noneMatch()
sometimes we need to get the matched element instead of just verifying if it is present or not. The finding operations are used for this purpose. There are two basic finding operations in streams, i.e.,
findFirst()
and findAny()
Numeric operations
Static Polymorphism | Dynamic Polymorphism |
Polymorphism that is resolved during compile time is known as static polymorphism. | Polymorphism that is resolved during run time is known as dynamic polymorphism. |
Method overloading is used in static polymorphism. | Method overriding is used in dynamic polymorphism. |
Optional
Method | Purpose |
empty() | Returns an empty Optional instance. |
of(T value) | Returns an Optional with the specified present non-null value. |
ofNullable(T value) | Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional . |
get() | If a value is present in this Optional , returns the value, otherwise throws NoSuchElementException . |
isPresent() | Returns true if there is a value present, otherwise false. |
ifPresent(Consumer<? super T> consumer) | If a value is present, performs the given action with the value, otherwise does nothing. |
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) | If a value is present, performs the given action with the value, otherwise performs the given empty-based action. |
map(Function<? super T,? extends U> mapper) | If a value is present, applies the provided mapping function to it, and if the result is non-null, returns an Optional describing the result. |
flatMap(Function<? super T,? extends Optional<? extends U>> mapper) | If a value is present, applies the Optional -bearing function to it, returns that result, otherwise returns an empty Optional . |
filter(Predicate<? super T> predicate) | If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional . |
orElse(T other) | Returns the value if present, otherwise returns other . |
orElseGet(Supplier<? extends T> other) | Returns the value if present, otherwise returns the result produced by the supplying function. |
orElseThrow() | If a value is present, returns the value, otherwise throws NoSuchElementException . |
orElseThrow(Supplier<? extends X> exceptionSupplier) | If a value is present, returns the value, otherwise throws an exception produced by the exception supplying function. |
- Check a string is between two length
caveat: can’t compile if both interface having the same default method
An interface that has a single abstract method (Can have one or more final methods)is called a functional interface.
Any interface that has only one abstract method can be annotated with the
@FunctionalInterface
annotation (not necessary).Interface vs abstract class
Interfaces and abstract classes are both used to achieve abstraction but with some of the key differences:
Interfaces | Abstract Classes |
Support multiple inheritance | Don’t support multiple inheritance |
All members are public | Can have private , protected and public members |
All data members are static and final | Can have non-static and non-final members too |
Can’t have constructors | Constructors can be defined |
Difference between Collection and Collections
The differences between a Collection and Collections are given below.
- A Collection is an interface, whereas Collections is a class.
- A Collection interface provides the standard functionality of a data structure to List, Set, and Queue. However, the Collections class provides the utility methods that can be used to search, sort, and synchronise collection elements.
Sort a ArrayList
ArrayList
Let object comparable
- Need to override compareTo() method to
- Custom Comparator
- Lambda function
LinkedList
Internal implementation of linkedList
Thread safe List
Difference between a HashSet and TreeSet
- The HashSet allows one null element, whereas a TreeSet does not allow a null element.
- The elements are stored in random order in a HashSet, whereas it is stored in sorted order in TreeSet.
- HashSet is faster than Treeset for the operations like add, remove, contains, size, etc.
HashMap
Resizing a HashMap
If the current capacity is 16, and the load factor is 0.75, then the HashMap will be resized when it has 12 elements (16 * 0.75). and the size is doubled.
If the size of the
LinkedList
in a particular bucket becomes more than TREEIFY_THRESHOLD
, then the LinkedList is converted to a red-black tree
.the class that is being used as a key must override both
equals()
and hashcode()
methods.TreeMap
- The entries in TreeMap are sorted in the natural ordering of its keys.
- It does not allow null keys, however there can be null values.
- The TreeMap is not thread-safe, although it can be made thread-safe using the
synchronizedMap()
method of the Collections class.
LinkedHashMap
Store the elements in a Map in insertion order
- It does not allow duplicate keys.
- It may have one null key and multiple null values.
- It is non-synchronized.
Setting accessOrder to false means that the storage order is based on insertion order rather than access order. This is the default value, which means that the order in which items are stored in the LinkedHashMap is sorted based on the order in which put method is called.
Insert Elements to LinkedHashMap
put()
- inserts the specified key/value mapping to the map
putAll()
- inserts all the entries from the specified map to this map
putIfAbsent()
- inserts the specified key/value mapping to the map if the specified key is not present in the map
Using entrySet(), keySet() and values()
entrySet()
- returns a set of all the key/value mapping of the map
keySet()
- returns a set of all the keys of the map
values()
- returns a set of all the values of the map
Here, accessOrder is a boolean value. Its default value is
false
. In this case entries in the linked hashmap
are ordered on the basis of their insertion order. However, if true
is passed as accessOrder, entries in the linked hashmap
will be ordered from least-recently accessed to most-recently accessed.ConcurrentHashMap
vs SynchronizedMap
.- In a
SynchronizedMap
, the entire Map is locked. So every read/write operation needs to acquire a lock, which makes it very slow. On the other hand in aConcurrentHashMap
, only a segment of the Map is locked. Two parallel threads can access or update elements in a different segment, so it performs better.
SynchronizedMap
returns Iterator, which fails fast on concurrent modification.ConcurrentHashMap
doesn’t throw aConcurrentModificationException
if one thread tries to modify it while another is iterating over it.
ConcurrentHashMap
does not allow null keys or null values whileSynchronizedMap
allows one null key.
IdentityHashMap
are:- The
IdentityHashMap
stores the elements in random order.
- The
IdentityHashMap
allows a single null key.
- The
IdentityHashMap
is not thread-safe.
The differences between a
HashMap
and IdentityHashMap
.IdentityHashMap
uses reference equality to compare keys and values while HashMap uses object equality to compare keys and values.
IdentityHashMap
does not use thehashCode()
method. Instead it usesSystem.identityHashCode()
to find the bucket location.
- IdentityHashMap does not require keys to be immutable as it does not rely on the
equals()
andhashCode()
methods. To safely store the object inHashMap
, keys must be immutable.
- The default initial capacity of
HashMap
is 16; whereas, for IdentityHashMap, it is 32.
EnumMap
EnumMap
does not allow null keys, but it allows null values.
- The keys are stored in their natural order. In the case of an Enum, the natural order of keys means the order where enum constant is declared inside Enum type.
- The
EnumMap
is not synchronized.
- All keys of each
EnumMap
instance must be keys of a single Enum type.
- Iterators returned by the collection views are inconsistent. They will never throw
ConcurrentModificationException
, and they may or may not show the effects of any modifications to the map that occur while the iteration is in progress.
- Java
EnumMap
implementation provides constant-time performance for the basic operations (like get and put).
The
binarySearch()
method are:- The array that is passed to the method should be sorted. If the array is not sorted, then the result is undefined.
- This method returns the index where the element is present in the array. If the element is not present in the array, then the index of the first element greater than the key is returned.
- If the array contains multiple elements with the specified value, there is no guarantee which one will be found.
- ClassCastException is thrown if the search key is not comparable to the elements of the array.
Collections
Following is the list of methods available to make Collections unmodifiable:
unmodifiableList(List<? extends T> list)
unmodifiableSet(Set<? extends T> s)
unmodifiableMap(Map<? extends K, ? extends V> m)
unmodifiableCollection(Collection<? extends T> c)
unmodifiableSortedMap(SortedMap<K,? extends V> m)
unmodifiableSortedSet(SortedSet<T> s)
The Collections class provides us with the following methods that can be used to make our existing collection thread-safe.
synchronizedCollection(Collection<T> c)
synchronizedList(List<T> list)
synchronizedMap(Map<K,V> m)
synchronizedSet(Set<T> s)
synchronizedSortedMap(SortedMap<K,V> m)
synchronizedSortedSet(SortedSet<T> s)
not taken any argument(
Supplier
), not returned any value(Consumer
), or returned only a boolean(Predicate
).A non-final, local variable whose value is never changed after initialization is known as effectively final.
Exception
Checked exceptions
checked by the compiler during compilation
- IOException
- ClassNotFoundException
Unchecked exceptions
- ArithmeticException
- ArrayIndexOutOfBounds
- NumberFormatException
- ArithmeticException
- NullPointerException
For checked exception(like IOException), we should require the client to check it and provide recovery actions if possible.
For unchecked exception (service unavailable), doesn’t require to check, and we can implement retry actions.
Generate random number
Parallel programming
Create process
- The
Runtime.exec()
method can be used to create a new process in Java. It takes the command and arguments as input and returns theProcess
object.
2. The
ProcessBuilder
class. First, create a List
containing the command and any arguments for the process. Then, create a new ProcessBuilder
object, passing the List
as a parameter to the constructor. Finally, call the start()
method on the ProcessBuilder
object to start the new process.Here is an example:
This example creates a new process that runs the
ls -la
command in the terminal.Create Thread
- Create a new thread by extending the
Thread
class and overriding therun()
method. Then, create an instance of the new class and call thestart()
method.
- Implement the
Runnable
interface and pass an instance of the new class to theThread
constructor. Then, call thestart()
method.
ThreadPool
schedular tasks
Require the returned value
Ensure multithread safe
Thread-safe data structures or collections
ConcurrentHashMap
and CopyOnWriteArrayList
. These data structures are designed to be used in multi-threaded environments and can handle concurrent access to their elements without any issues.synchronized
To ensure multithread safe, we can use the
synchronized
keyword to mark a method or a code block as critical section. This will ensure that only one thread can access the critical section at a time, preventing race conditions and other concurrency problems. Lock
Condition
condition.await
, condition.signal
can only used with lock. wait/notify
To use
wait()
and notify()
to coordinate between threads, we need to have a shared object as the lock: it must use with synchronized
.CountDownLatch
CountDownLatch is used in scenarios where the main thread needs to wait for other business threads to complete before it can proceed with execution. The general usage is as follows:
- Initialize with a specified integer (number of counters).
- The main thread executes the latch.await(); method, waiting for other threads to complete. Other threads must call latch.countDown(); to decrement the counter.
- The main thread's code following latch.await(); can only continue executing when the counter value reaches 0.
CyclicBarrier
CyclicBarrier
is a synchronization utility class in the Java Concurrency package. It allows a group of threads to wait for each other until all threads reach a specific barrier point, and then continue executing together. Its constructor takes an integer as a parameter, which represents the number of threads that need to wait.Semaphore
The function of Semaphore is "flow control", which is used to "allow only a certain number of threads to execute simultaneously at the same time".
When initializing Semaphore, an integer needs to be specified to represent the number of threads that can be executed simultaneously at the same time;
Before each thread starts executing, it needs to call semaphore.acquire(); to obtain a permit;
After each thread ends, it needs to call semaphore.release(); to release a permit.
Read/Write Lock
ReentrantReadWriteLock
It allows multiple threads to read a shared resource concurrently, but restricts access to only one thread when writing. It can improve performance in scenarios where read operations are much more frequent than write operations.
Queue
Method | Throw Exception | Return Special Value | Blocking | Timeout Exit |
Insert | boolean add(E e) | boolean offer(E e) | void put(E e) throws InterruptedException | boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException |
Remove | void remove() | poll() | E take() throws InterruptedException | E poll(long timeout, TimeUnit unit) throws InterruptedException |
Examine | element() | peek() | Not available | Not available |
What is the difference between ArrayBlockingQueue and LinkedBlockingQueue?
ArrayBlockingQueue
is a bounded blocking queue that is internally implemented as a fixed-length array. When created, the capacity of the queue must be specified. Once the queue is full, further enqueue operations will be blocked until elements are removed from the queue.
LinkedBlockingQueue
is an unbounded blocking queue that is internally implemented as a linked list. If no capacity is specified when creating a LinkedBlockingQueue, an unbounded queue is created, meaning the queue's capacity can grow indefinitely. If a capacity is specified, a bounded queue is created, meaning the queue's capacity is fixed and cannot exceed the specified capacity. If an attempt is made to add an element to a full bounded queue, the operation will block until space becomes available.
- Dequeue operations are blocked when the queue is empty and enqueue operations are blocked when the queue is full.
How does a blocking queue avoid thread safety issues?
A blocking queue avoids thread safety issues through internal synchronization mechanisms such as
ReentrantLock
and Condition
. These mechanisms ensure that enqueue and dequeue operations can only be performed by one thread when the queue is full or empty, thus avoiding potential race condition issues that arise when multiple threads access the queue concurrently.Check dead lock
- Find the Java process ID:
Run
jps -l
in the terminal. This command lists all the Java processes running on your system with their respective process IDs (PIDs) and fully qualified class names. Look for the process related to your application and note its PID.
- Generate a thread dump:
Run
jstack <PID>
in the terminal, replacing<PID>
with the process ID you found in step 1. This command will generate a thread dump for the specified Java process, which contains information about the state of all the threads in that process. You can redirect the output to a file by using the following command:
- Search for deadlocks:
A deadlock occurs when two or more threads are waiting for each other to release resources, causing them to be stuck indefinitely. In the thread dump, you can look for threads in the
BLOCKED
state and their associated lock objects.
To search for deadlocks, you can use the
grep
command:If you find any blocked threads, examine their stack traces in the thread dump to identify the resources they are waiting for and the threads holding those resources.
Reflection
- Get the declared methods of a class
- Initialize an object
- invoke methods
- access and change field