Home/Blog/Interview Prep/Top 20 Java coding interview questions for 2024
Home/Blog/Interview Prep/Top 20 Java coding interview questions for 2024

Top 20 Java coding interview questions for 2024

Mehvish Poshni
Apr 01, 2024
16 min read

Become a Software Engineer in Months, Not Years

From your first line of code, to your first day on the job — Educative has you covered. Join 2M+ developers learning in-demand programming skills.

Coding interviews are aimed at gauging how well-prepared a candidate is in terms of language proficiency, foundational knowledge, problem-solving skills, and soft skills. For a position that explicitly mentions a language, such as a job listing for a Java developer, it makes even more sense to spend some time and energy polishing Java skills by exploring the common interview questions asked in such interviews. Doing this not only allows us to benefit directly from the experience of others but more importantly, it’s an opportunity to learn things that we are not aware are gaps in our knowledge.

Java interview questions#

In this blog, we cover 20 Java language-specific interview questions on a variety of topics. We’re also including answers to these questions to help you prepare for them. For more interview questions, check out the links at the end of this blog.

Let’s go!

1. What are Java varargs?#

Varargs stands for variable arguments. In order to pass a variable number of arguments of the same type to a method, a varargs variable can be used. The syntax consists of including three ellipses after a data type followed by the variable name.

boolean... variableName

A variable name declared in this manner as a method parameter can then be used inside the method as an array that contains arguments of the declared data type. The method findMax on line 4 in the widget below inputs an arbitrary number of integers and finds the maximum.

class Compute {
// Finds the max of the input parameters
public float findMax(int... scores) {
int max = -1;
// Finds the max of all input parameters received in the scores variable
for (int i : scores) {
if (max < i) max = i;
}
return max;
}
}
class Main {
public static void main(String[] args) {
Compute compute = new Compute();
System.out.println(compute.findMax(1, 2, 3, 4, 5));
System.out.println(compute.findMax(10, 20, 30));
System.out.println(compute.findMax());
}
}

2. What’s the @ operator in Java?#

The @ operator is used for specifying Java annotations that essentially represent metadata associated with Java code, such as a Java method, class, or interface. Some annotations (introduced in Java 7 and Java 8) also apply to other annotations and are called meta annotations.

Java annotations are optional but useful for better code readability. The annotations are also readable by the compiler, and in some cases, errors and warnings are given by the compiler where there is a mismatch between the code and the intent specified by the annotation. For example, consider the following code:

abstract class UniversalGreeting {
@Deprecated
public abstract void hello();
}
class French extends UniversalGreeting {
public void hello() {
System.out.println("Bonjour");
}
//@Override
public void goodbye() {
System.out.println("Au revoir");
}
}
class Main {
public static void main(String[] args) {
French fr = new French();
fr.hello();
}
}
  • On line 3, the annotation @Deprecated conveys that the method hello() is deprecated.
  • The annotation @Override on line 13 that’s commented out specifies that the method following it has to override an existing method. If the method being overridden is missing from the parent class, the compiler will give an error. Uncomment line 13 to see this.

It is also possible to define custom Java annotations for custom behavior required at compile-time or runtime.


3. How are strings managed in Java?#

A Java string can be created using the String class or directly as string literals (like “Hello”). In Java, strings are immutable objects (unchangeable). String literals are created in an area of heap memory called a string pool. This ensures that any two literals with the same content refer to the same object. This must be kept in mind when programming with Java strings.

In the following code, using the == operator works when comparing literals (see line 6), but does not work when an explicit String object is compared with a string literal (see line 10). The method str.equals("Hello") can be used instead as shown on line 13 to check for semantic equivalence.

import java.lang.String;
class StringExample {
public static void main(String[] args) {
if ("Hello!" == "Hello!") {
System.out.println("Same strings.");
}
String str = new String("Hello!");
if (str == "Hello!") {
System.out.println("Different strings.");
}
if (str.equals("Hello!")) {
System.out.println("Semantically, the strings are equal.");
}
}
}

4. How is the equals() method different from the == operator?#

All classes inherit, directly or indirectly, from the Object class. The equals() method is implemented in the Object class to be identical to the == operator. A consequence of this is that for reference variables, comparisons made with the default equals() method will only hold true when the two reference variables contain the same address. Depending on our application, we might want two objects to be equal as long as they are equivalent in some sense. For example, we might want to override the definition of equals() in the following code if we’d like two ordered pairs with the same x and y coordinates to represent the same point in the plane.

class Pair {
int x;
int y;
// Constructor
Pair(int x, int y) {
this.x = x;
this.y = y;
}
}
class Main {
public static void main(String[] args) {
Pair p1 = new Pair(1, 2);
Pair p2 = new Pair(1, 2);
System.out.println("Does p1 equal p2? " + p1.equals(p2));
}
}

Note that according to The Java Language Specification, any implementation of equals() must test for equivalence under an equivalence relation. In particular, for objects that are not null, an implementation should ensure the following properties:

  • An object equals itself (reflexive).
  • If an object a equals b, then b equals a (symmetric).
  • If an object a equals b and b equals c, then a equals c (transitive).

5. Why must hashcode() be overridden whenever equals() is overridden?#

The method hashcode() returns an integer that’s used by Java collections, such as HashMap, HashSet, etc., to store an object against its numeric hash code. According to The Java Language Specification for hashcode(), whenever two objects are equal, they must have the same hash code.

In the following code, we override equals() for the class State. So, the two State objects on line 38 are equal, but because we made the mistake of not overriding hashcode(), we see that such an instance cannot be used for retrieving the required data from the hash map (see lines 40–43).

import java.util.HashMap;
class State {
String abbreviation = "";
String name = "";
State(String a, String n) {
this.abbreviation = a;
this.name = n;
}
@Override
public boolean equals(Object obj) {
State st = (State) obj;
if (
this.abbreviation.equals(st.abbreviation) && this.name.equals(st.name)
) {
return true;
} else {
return false;
}
}
}
class Main {
public static void main(String[] args) {
// Map to store data of a state against each state
HashMap<State, String> stateData = new HashMap<State, String>();
stateData.put(
new State("NY", "New York"),
"Voter registration deadlines for NY"
);
System.out.println(
"Are objects equal? " +
(new State("NY", "New York").equals(new State("NY", "New York")))
);
String retrieved = stateData.get(new State("NY", "New York"));
System.out.println(
"What does the object retrieve from the hashmap? " + retrieved
);
}
}

6. What are generic types?#

A generic type is a class or an interface that’s defined using one or more parameters that serve as placeholders for other types. For instance, in the following code, the appearance of T in angular brackets on line 3 indicates that the class MyClass is parametrized over the type T. This makes MyClass a generic class.

We create a generic type GenericQueue<T> on lines 3–16 and instantiate it by substituting the parameter T by a type argument as shown on line 21 and line 26 in the widget below.

import java.util.LinkedList;
class GenericQueue<T> {
LinkedList<T> queue = new LinkedList<T>(); // A list containing objects of type T
// Inserting an object of type T at the end
void enqueue(T t) {
queue.addLast(t);
}
// Removing an object of type T from the queue
T dequeue() {
return queue.removeFirst();
}
}
class Main {
public static void main(String[] args) {
GenericQueue<String> q1 = new GenericQueue<String>();
q1.enqueue("Asia");
q1.enqueue("Africa");
System.out.println(q1.dequeue());
GenericQueue<Integer> q2 = new GenericQueue<Integer>();
q2.enqueue(1);
q2.enqueue(2);
System.out.println(q2.dequeue());
}
}

Note: The type parameters, such as T in the code above, bind to non-primitive data types only.

The biggest advantage of using a generic type is that the same code can be reused multiple times for different types.


7. Are Java generic types variant or invariant?#

A Java type such as List<Integer> is neither a subtype of List<Object> nor its supertype, even though Integer is a subtype of Object.

Suppose Child is a subclass of the Parent class. In type theory:

  • If T<Child> is a subtype of T<Parent>, it is said to be covariant.
  • If T<Parent> is a subtype of T<Child>, it is said to be contravariant.
  • If a type is neither covariant nor covariant, it is said to be invariant.

Java generic types are invariant. So, in the following code, passing an instance of type Generic<Integer> to a method that expects an instance of type Generic<Object> gives a compiler error on line 13 and vice versa on line 12.

class Generic<T> {
public T t;
}
class Main {
public static void main(String[] args) {
Generic<Object> o = new Generic<Object>();
Generic<Integer> i = new Generic<Integer>();
paramBoundToInteger(o);
paramBoundToObject(i);
}
public static void paramBoundToObject(Generic<Object> o) {
System.out.println(
"An object of type Generic<Object> is passed an argument."
);
}
public static void paramBoundToInteger(Generic<Integer> i) {
System.out.println(
"An object of type Generic<Integer> is passed an argument."
);
}
}

8. How can we create a Java thread?#

A thread can be created by either extending the Thread class or by implementing the Runnable interface. The latter option is especially useful if we’re already inheriting from a class other than Thread.

In the following code, we can see both approaches:

  • The class MyThread extends from Thread and an instance of MyThread is created to run the thread.
  • The class YourThread implements the Runnable interface. Its instance is passed to a Thread constructor to create a thread.
// One way to create a thread
class MyThread extends Thread {
public void run() {
System.out.println(
"I am a thread created via extension of the Thread class"
);
}
}
// Another way
class YourThread implements Runnable {
public void run() {
System.out.println("I am a thread implemented via Runnable");
}
}
class Main {
public static void main(String[] args) {
// MyThread is a subclass of Thread
MyThread mt = new MyThread();
mt.start();
// YourThread implements Runnable
Thread yt = new Thread(new YourThread());
yt.start();
}
}

9. What kind of methods can be defined in a Java interface?#

In older Java versions, it used to be the case that the interfaces strictly contained method signatures for which implementations were not provided. Such methods are called abstract methods. A class that implements an interface needs to provide the definitions of all abstract functions in the interface.

Starting with Java 8, we can implement certain methods within an interface. These methods are specified with the default and static keywords and are known as default methods and static methods, accordingly. For instance, in the following code, the interface defined on lines 1–14 defines an abstract, a default, and a static method:

interface MyInterface {
// An abstract method with no implementation given
public void acknowledge();
// A default method
public default void greet() {
System.out.println("Hello!");
}
// A static method
public static void farewell() {
System.out.println("Good bye!");
}
}
class MyClass implements MyInterface {
// Implementation given for the abstract method in the interface
@Override
public void acknowledge() {
System.out.println("Nod :)");
}
}
class Main {
public static void main(String[] args) {
MyClass mc = new MyClass();
mc.greet();
mc.acknowledge();
MyInterface.farewell(); // Static method is invoked on the class and not an instance
}
}

Note that a static method that belongs to an interface, much like a static method that belongs to a class, is not inherited.


10. What’s a functional interface?#

An interface that contains exactly one abstract function is a functional interface. A functional interface can include multiple default and static methods. It’s a good programming practice to use the annotation @FunctionalInterface to mark an interface as a functional interface.

Some well-known examples of functional interfaces are Comparable with the abstract method compareTo, and Runnable with the abstract method run.

In Java 8, java.util.function contains, among others, the following four useful functional interfaces that we should be familiar with.

Interface

Description of abstract method

Function

Takes an input and returns a value.

Predicate

Takes an input and returns true or false.

Consumer

Takes an input and returns nothing.

Supplier

Takes no input and returns a value.


11. What’s a Java lambda expression?#

Lambda expressions, introduced in Java 8, are objects that implement a functional interface. The syntax of a lambda specifies the definition of the sole abstract method of a functional interface.

This syntax consists of three parts:

  • The first is a list of arguments enclosed in parentheses. The parentheses can be omitted if only a single argument is present.
  • The list of arguments is followed by the arrow operator ->.
  • The arrow operator -> is followed by a block of code included within braces {}. The braces can be omitted in case the block consists of just a single expression corresponding to the value being returned.

For example, the following lambda takes two numeric arguments and returns the sum of these.

(int a, float b) -> {return a+b;};

Note: The types of variables in the lambda can be specified explicitly but can also be inferred from the surrounding context.

The following code shows two different ways to write the same lambda expression. The lambda expressions on line 5 and lines 7–10 take no argument. They simply print a message and return nothing. Note that the right-hand sides give an implementation of the run method of the Runnable interface. The objects created on line 5 and lines 7–10 therefore implement the Runnable interface and can be used to create threads on line 12 and line 14.

class Main {
public static void main(String[] args) {
//The body is an expression
Runnable r1 = () -> System.out.println("I am r1");
//The body consists of two statements
Runnable r2 = () -> {
System.out.println("I am r2");
return;
};
Thread t1 = new Thread(r1);
t1.start();
Thread t2 = new Thread(r2);
t2.start();
}
}

12. How is the forEach loop useful?#

The forEach loop can be used to iterate over a collection. Its argument must be an instance that’s an implementation of the Consumer functional interface. A lambda argument passed as an argument to the loop is applied to each element of the collection. For instance, in the following code on line 11, the lambda expression is applied to each element, i, in a list. The input i is consumed, and nothing is returned.

import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Alpha");
list.add("Beta");
list.add("Gamma");
// For each element i, true is printed if it contains the capital letter A
list.forEach(i -> System.out.println(i.contains("A")));
}
}

A forEach loop can also be passed a method reference which specifies the function that can be applied to each element of the iterable on which it is invoked. For instance, the following line of code prints each element in the list:

list.forEach(System.out::println);

13. What type of variables must be final or effectively final when used in a lambda?#

There are three types of variables in Java.

  • Instance variables: These belong to individual class instances.
  • Static variables: These belong to the class.
  • Local variables: These are declared in methods or blocks of code.

All three types of variables, when in scope, can be used in a lambda expression. However, the local variables can be used only if they are either explicitly declared final or they undergo no change after their first assignment. So, for all practical purposes, they are treated by the compiler as effectively final. The lambda expression on lines 10–19 below use variables of all three kinds, but if we comment out line 22 the local variable does not remain effectively final, resulting in a compiler error.

class Main {
static int staticVar = 1;
boolean instanceFlag = true;
public static void main(String[] args) {
Main m = new Main();
int localVar = 0;
MyInterface lambda = () -> {
System.out.println(
"Static: " +
Main.staticVar +
"\nInstance: " +
m.instanceFlag +
"\nLocal: " +
localVar
);
};
// If uncommented locaVariable does not remain effectively final and will produce a compiler error
// localVar = 3;
Main.staticVar = 10;
m.instanceFlag = false;
lambda.foo();
}
}
@FunctionalInterface
interface MyInterface {
void foo();
}

14. How can we clone an object in Java?#

Cloning an object means making a copy of that object. The Object class defines a method clone() that is inherited by all other classes since the Object class is at the top of the inheritance hierarchy for Java. However, clone() defined for the Object class only makes shallow copies and must be overridden if deep copies are required.

A class whose instances are required to be cloned must implement the Cloneable interface, otherwise, calling clone() on such instances will throw the CloneNotSupported exception.

In the following code, we show two classes Whole and Part that implement the Cloneable interface. In the Part class, we just call the clone() function of the superclass (see line 12). On the other hand, the class Whole contains a data member of type Part. If we were to use the clone() method of the superclass, it would make a copy of the address stored in the reference variable part instead of making its deep copy. So we explicitly make a deep copy of part on line 34.

class Part implements Cloneable {
int id;
// Part constructor
Part(int id) {
this.id = id;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Whole implements Cloneable {
String model;
float price;
Part part;
// Whole constructor
Whole(String model, float price, Part part) {
this.model = model;
this.price = price;
this.part = part;
}
@Override
public Object clone() throws CloneNotSupportedException {
// Calling super.clone() would makes a shallow copy of the Part object
Whole w = (Whole) super.clone();
// All data members must be deep copied
w.part = (Part) this.part.clone();
return w;
}
}
class Main {
public static void main(String[] args) {
try {
Whole w1 = new Whole("A", 10, new Part(4));
Whole w2 = (Whole) w1.clone();
w1.part.id = 3; // Modifying part.id in w1
System.out.println(w1.model + " " + w1.price + " " + w1.part.id);
System.out.println(w2.model + " " + w2.price + " " + w2.part.id);
} catch (CloneNotSupportedException e) {
System.out.println(e);
}
}
}

15. What’s an inner class, and why is it used?#

A nested Java class that’s not static is called an inner class. An instance of an outer class must be created first in order to create an instance of an inner class, as shown on lines 34–35 in the widget below.

Inner classes are useful for organizing code with the aim of ensuring encapsulation.

// Outer class of Employee
class Employee {
String first = null;
String last = null;
// Employee constructor
Employee(String f, String l) {
this.first = f;
this.last = l;
}
// Inner class Dependent contained within the outer class Employee
public class Dependent {
String name = "";
//Dependent constructor
Dependent(String n) {
name = n;
}
// To print dependent information
void print() {
System.out.println(name + " is a dependent of " + first + " " + last);
}
}
}
class Main {
public static void main(String[] args) {
Employee emp = new Employee("John", "Doe");
Employee.Dependent dep1 = emp.new Dependent("Jane");
Employee.Dependent dep2 = emp.new Dependent("Jack");
dep1.print();
dep2.print();
}
}

In the code above, we use the public access modifier with the inner class. But just like for other data members, we could have also used the private or protected access modifiers with the inner class.


16. What’s an anonymous class?#

An anonymous class is a nested class that has no name and is defined and instantiated all at once. For this reason, an anonymous class can be instantiated only once. Note that an anonymous class is used to either extend another class or implement an interface. To create an anonymous class instance, the new operator is applied to the name of its superclass or the name of the interface being implemented, as shown on lines 11–23 in the widget below.

interface MyInterface {
public void foo();
public void bar();
}
class Main {
public static void main(String[] args) {
// Creating an instance of an anonymous class
MyInterface foobar = new MyInterface() {
private String name = "foobar";
@Override
public void foo() {
System.out.println("Foo");
}
@Override
public void bar() {
System.out.println("Bar");
}
};
// Using the foobar object
foobar.foo();
foobar.bar();
}
}

17. What’s the difference between an iterable and an iterator?#

An iterable is an object that implements the Iterable interface. All Java collections implement this interface. This enables us to iterate over these collections using an iterator returned by the iterator() method, as well as by using the forEach() method.

An iterator, on the other hand, is an object that implements the Iterator interface. It supports the hasNext() method which can be used for checking if there is a non-null element at the next position in the collection. If the element exists, it can be retrieved using the next() method. It also supports the remove() method, which can be used for safely removing an element from the iterable during the iteration. The element removed is the same as the one returned by the previous call to next(). The following code shows how these methods can be used on lines 15–18.

import java.util.ArrayList;
import java.util.Iterator;
class Main {
public static void main(String[] args) {
ArrayList<String> shapes = new ArrayList<>();
shapes.add("Pentagon");
shapes.add("Hexagon");
shapes.add("Heptagon");
shapes.add("Octagon");
Iterator<String> it = shapes.iterator();
String shape = "";
while (it.hasNext()) {
System.out.println(it.next());
it.remove();
}
}
}

Note that when an iterator is in use, direct additions or removals from a collection can result in a ConcurrentModificationException exception being thrown. The iterators that implement this behavior are called fail-fast iterators.


18. What’s the difference between a HashMap and a TreeMap?#

Both are Java collections used for storing key-value pairs. Internally, the HashMap class is implemented like a hash table, but the TreeMap class is implemented as a red-black tree, which is a balanced binary search tree. So retrieval, addition, and checking for containment of an element is O(1)O(1) for HashMap vs. O(logn)O(\log n) for TreeMap. Searching is asymptotically the same at O(logn)O(\log n) for both.

On the other hand, a tree map has a distinct advantage over a hash map in that the keys stored in it are ordered, and if an application has a need for ordering data, then it’s a better fit. The order in which the keys are stored is said to be the natural order and is specified by the implementation of compareTo in the Comparable interface. By default, the numeric keys in a tree map are stored under the usual ordering on the set of real numbers. Keys that are strings are ordered alphabetically.

The following example shows a few method calls that retrieve ordered data from a tree map.

import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> treemap = new TreeMap<>();
treemap.put("A", 1);
treemap.put("Z", 5);
treemap.put("B", 2);
treemap.put("D", 4);
treemap.put("C", 3);
System.out.println("TreeMap: " + treemap);
System.out.println("First entry: " + treemap.firstEntry()); // The "smallest" entry
System.out.println("Last entry: " + treemap.lastEntry()); // The "greatest" entry
System.out.println("Keys in descending order: " + treemap.descendingKeySet());
System.out.println("Tail end of the map starting at C: " + treemap.tailMap("C"));
System.out.println("Ceiling of M: " + treemap.ceilingKey("M")); // The "smallest" entry that's equal to or greater than "M"
}
}

19. What purpose does the synchronized keyword serve?#

The synchronized keyword is applied to code blocks or methods to ensure that each such code block can be executed by only one thread at a time. Each code block is synchronized over an object shown as follows:

class Counter {

  int count = 0;

  void setCount() {
    synchronized (count) {
      // Code block synchronized over the variable count
    }
  }
}

The synchronized keyword can also be applied directly to a method name. In such a case, the method is synchronized on the this object. For instance, in the following code, the increment() method defined on lines 6–16 is synchronized on the this object.

class Counter {
int count = 0;
// A method synchronized on the this object
public synchronized void increment(String threadName) {
System.out.println(this.count + " " + threadName);
this.count++;
// Monitor (lock) on this object is not released while this thread is suspended
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println(e);
}
return;
}
}
class MyThread extends Thread {
String name;
Counter counter;
// MyThread constructor
MyThread(String n, Counter c) {
name = n;
counter = c;
}
@Override
public void run() {
for (int i = 0; i <= 4; i++) {
this.counter.increment(this.name);
}
}
}
class Main {
public static void main(String[] args) {
Counter c = new Counter();
MyThread t1 = new MyThread("Ping", c);
MyThread t2 = new MyThread("Pong", c);
t1.start();
t2.start();
}
}

A thread that enters the code of one of the synchronized methods has the lock over the this object, and all other threads are blocked from entering and executing any method or code block synchronized on the same object.

Once the thread holding the lock exits the code block, the lock over the object is released.

If we remove the synchronized keyword from line 6, we note that in one execution (see below), the first thread prints 0 Ping, then the second thread prints 0 Pong, followed by the first thread printing 2 Ping. The fact that 0 was printed twice and 1 was never printed indicates that the threads were switched while increment() was still being executed.

Output for an execution where the synchronized keyword is removed
Output for an execution where the synchronized keyword is removed

20. Is a variable made thread-safe when declared using the volatile keyword?#

No. In a multithreaded environment, it’s possible that a variable is cached, and a write to the cached copy takes place by one thread while its older value is still visible and being read by other threads. Once the new value is updated in the main memory, only then does it become visible to other threads. To provide a consistent view to all threads, a variable is declared volatile. A volatile variable is always updated in the main memory instead of the cache. But it does not ensure thread safety.


What next?#

The interview questions above are by no means exhaustive, and are a reflection of a trajectory that can be taken by an interviewer as one question leads to another, sometimes related question.

At Educative, we offer a carefully curated array of interview courses. Some of these help improve problem-solving skills and strengthen basic foundations, while others help with language proficiency.

We wish you a happy journey and leave you with the following suggestions for your Java interview preparation:

Cover
The Java Interview Handbook: 300+ Interview Questions

It’s very common to have interviews testing your knowledge of a programming language you claim to be an expert in. If you've got an interview coming up on Java soon and need to get up to speed, this is the ideal course for you. You'll refresh your memory on everything from the basics to more advanced functionality you’re likely to be asked about. Even if you're using Java every day, you may not have been exposed to parts of it in some time, so it's always useful to make sure you're updated. This course features more than 300 of the most commonly asked core Java interview questions that you're likely to face as an experienced software engineer. You'll get to explore questions by topic, as well as see detailed answers for each one, and plenty of live code examples where relevant. Get started today.

15hrs
Intermediate
147 Playgrounds
55 Quizzes
Cover
Java Multithreading for Senior Engineering Interviews

Concurrency in Java is one of the most complex and advanced topics brought up during senior engineering interviews. Knowledge of concurrency and multithreading can put interviewees at a considerable advantage. This course lays the foundations of advanced concurrency and multithreading and explains concepts such as Monitors and Deferred Callbacks in depth. It also builds simple and complete solutions to popular concurrency problems that can be asked about in interviews like the Reader-Writer Problem and the Dining Philosopher Problem. While prior knowledge of concurrency is not required to follow through with this course, familiarity with the very basics of concurrency would be helpful.

15hrs
Beginner
177 Playgrounds
23 Quizzes
Cover
Collections in Java

Collection is one of the most important topics for Java programming. Without the proper knowledge of every collection type in Java, it becomes difficult for you to decide which option to pick in a particular scenario. This course will give you a great understanding of all collection types available in the Collections Framework like lists, linked lists, sets, and hashmaps. After completing this course, you will know how data can be modified within a collection, how to sort a collection, and how it can be made thread-safe. You will also cover the internal working of each Java collection so you can work with them more efficiently.

5hrs
Intermediate
106 Playgrounds
5 Quizzes

  

Free Resources