Let's run through each part of the code. First, createSharedListViaStream:

public static List<SchoolObj> createSharedListViaStream(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
    // We create a stream of elements from the first list.
    List<SchoolObj> listOneList = listOne.stream()
    // We select any elements such that in the stream of elements from the second list
    .filter(two -> listTwo.stream()
    // there is an element that has the same name and school as this element,
        .anyMatch(one -> one.getName().equals(two.getName()) 
            && two.getSchool().equals(one.getSchool())))
    // and collect all matching elements from the first list into a new list.
    .collect(Collectors.toList());
    // We return the collected list.
    return listOneList;
}

After running through the code, it does exactly what you want it to do. Now, let's run through createSharedListViaLoop:

public static List<SchoolObj> createSharedListViaLoop(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
    // We build up a result by...
    List<SchoolObj> result = new ArrayList<SchoolObj>();
    // going through each element in the first list,
    for (SchoolObj one : listOne)
    {
    // going through each element in the second list,
        for (SchoolObj two : listTwo)
        {
    // and collecting the first list's element if it matches the second list's element.
            if (one.getName().equals(two.getName()) && one.getSchool().equals(two.getSchool()))
            {
                result.add(one);
            }
        }
    }
    // We return the collected list
    return result;
}

So far, so good... right? In fact, your code in createSharedListViaStream is fundamentally correct; instead, it is your createSharedListViaLoop that may be causing discrepancies in output.

Think about the following set of inputs:
List1 = [SchoolObj("nameA","SchoolX"), SchoolObj("nameC","SchoolZ")]
List2 = [SchoolObj("nameA","SchoolX"), SchoolObj("nameA","SchoolX"), SchoolObj("nameB","SchoolY")]

Here, createSharedListViaStream will return the only element of the first list that appears in both lists: SchoolObj("nameA","SchoolX"). However, createSharedListViaLoop will return the following list: [SchoolObj("nameA","SchoolX"),SchoolObj("nameA","SchoolX")]. More precisely, createSharedListViaLoop will collect the correct object, but it will do so twice. I suspect this to be the reason for the output of createSharedListViaStream to be "incorrect" based on comparison to the output of createSharedListViaLoop.

The reason that createSharedListViaLoop does this duplication is based on the lack of termination of its inner for loop. Although we iterate over all elements of the first list to check if they are present in the second, finding a single match will suffice to add the element to the result. We can avoid redundant element addition by changing the inner loop to the following:

for (SchoolObj one : listOne)
    {
    for (SchoolObj two : listTwo)
    {
        if (one.getName().equals(two.getName()) && one.getSchool().equals(two.getSchool()))
        {
            result.add(one);
            break;
        }
    }
}

Additionally, if you don't want duplicate Objects in your list (by location in memory), you can use distinct like so:

List<SchoolObj> result = ...;
result = result.stream().distinct().collect(Collectors.toList());

As a final caution, the above will keep the results distinct in the following scenario:

List<SchoolObj> list = new ArrayList<>();
SchoolObj duplicate = new SchoolObj("nameC", "schoolD");
listOne.add(duplicate);
listOne.add(duplicate);
list.stream().distinct().forEach(System.out::println); 
// prints:
// nameC schoolD

However, it will not work in the following scenario, unless you override the equals method for SchoolObj:

List<SchoolObj> list = new ArrayList<>();
listOne.add(new SchoolObj("nameC", "schoolD"));
listOne.add(new SchoolObj("nameC", "schoolD"));
list.stream().distinct().forEach(System.out::println); 
// prints (unless Object::equals overridden)
// nameC schoolD
// nameC schoolD
Answer from Avi on Stack Overflow
🌐
How to do in Java
howtodoinjava.com › home › collections framework › java arraylist › compare two lists in java: equality, differences, common items
Compare Two Lists in Java: Equality, Differences, Common Items
1 week ago - To compare lists ignoring order, we sort copies of both lists and compare the copies with equals(). Sorting keeps duplicates, so [a, a, b] and [a, b, b] stay different, which is the correct result.
🌐
Baeldung
baeldung.com › home › java › java list › finding the differences between two lists in java
Finding the Differences Between Two Lists in Java | Baeldung
April 29, 2026 - As an example, imagine we have a list of students who applied for an exam, and another list of students who passed it. The difference between those two lists would give us the students who didn’t pass the exam. In Java, there’s no explicit way of finding the differences between two lists in the List API, though there are some helper methods that come close.
Discussions

lambda - Java 8: More efficient way of comparing lists of different types? - Stack Overflow
Now I wonder, if there is a more ... the comparison using other Java 8 statements, for example allMatch() or some Predicate or something else. ... Sebastian S. 1,60966 gold badges2525 silver badges4242 bronze badges 6 ... @TagirValeev I want to ensure that the List people ... More on stackoverflow.com
🌐 stackoverflow.com
April 25, 2017
Comparing two Arraylists
If you would like to compare the items of two lists. You can create a loop and then you can compare each item step by step. If you would like to compare two lists independently from each other. You can use Java Comparator class with sort function. You can define code logic which has sorting rules. With this way, you can compare the fields of class whatever you want. I hope this is your expected answer ? More on reddit.com
🌐 r/javahelp
5
3
January 25, 2018
java - Comparing two lists and getting differences - Stack Overflow
I have two lists. They contain objects of different types, but both types contain id and name, and id is what I am comparing on. List one is fetched from DB, and list two is sent from frontend. ... More on stackoverflow.com
🌐 stackoverflow.com
Java Compare Two Lists - Stack Overflow
I have two lists ( not java lists, you can say two columns) For example **List 1** **Lists 2** milan hafil dingo iga iga dingo ... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 3
20

Let's run through each part of the code. First, createSharedListViaStream:

public static List<SchoolObj> createSharedListViaStream(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
    // We create a stream of elements from the first list.
    List<SchoolObj> listOneList = listOne.stream()
    // We select any elements such that in the stream of elements from the second list
    .filter(two -> listTwo.stream()
    // there is an element that has the same name and school as this element,
        .anyMatch(one -> one.getName().equals(two.getName()) 
            && two.getSchool().equals(one.getSchool())))
    // and collect all matching elements from the first list into a new list.
    .collect(Collectors.toList());
    // We return the collected list.
    return listOneList;
}

After running through the code, it does exactly what you want it to do. Now, let's run through createSharedListViaLoop:

public static List<SchoolObj> createSharedListViaLoop(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
    // We build up a result by...
    List<SchoolObj> result = new ArrayList<SchoolObj>();
    // going through each element in the first list,
    for (SchoolObj one : listOne)
    {
    // going through each element in the second list,
        for (SchoolObj two : listTwo)
        {
    // and collecting the first list's element if it matches the second list's element.
            if (one.getName().equals(two.getName()) && one.getSchool().equals(two.getSchool()))
            {
                result.add(one);
            }
        }
    }
    // We return the collected list
    return result;
}

So far, so good... right? In fact, your code in createSharedListViaStream is fundamentally correct; instead, it is your createSharedListViaLoop that may be causing discrepancies in output.

Think about the following set of inputs:
List1 = [SchoolObj("nameA","SchoolX"), SchoolObj("nameC","SchoolZ")]
List2 = [SchoolObj("nameA","SchoolX"), SchoolObj("nameA","SchoolX"), SchoolObj("nameB","SchoolY")]

Here, createSharedListViaStream will return the only element of the first list that appears in both lists: SchoolObj("nameA","SchoolX"). However, createSharedListViaLoop will return the following list: [SchoolObj("nameA","SchoolX"),SchoolObj("nameA","SchoolX")]. More precisely, createSharedListViaLoop will collect the correct object, but it will do so twice. I suspect this to be the reason for the output of createSharedListViaStream to be "incorrect" based on comparison to the output of createSharedListViaLoop.

The reason that createSharedListViaLoop does this duplication is based on the lack of termination of its inner for loop. Although we iterate over all elements of the first list to check if they are present in the second, finding a single match will suffice to add the element to the result. We can avoid redundant element addition by changing the inner loop to the following:

for (SchoolObj one : listOne)
    {
    for (SchoolObj two : listTwo)
    {
        if (one.getName().equals(two.getName()) && one.getSchool().equals(two.getSchool()))
        {
            result.add(one);
            break;
        }
    }
}

Additionally, if you don't want duplicate Objects in your list (by location in memory), you can use distinct like so:

List<SchoolObj> result = ...;
result = result.stream().distinct().collect(Collectors.toList());

As a final caution, the above will keep the results distinct in the following scenario:

List<SchoolObj> list = new ArrayList<>();
SchoolObj duplicate = new SchoolObj("nameC", "schoolD");
listOne.add(duplicate);
listOne.add(duplicate);
list.stream().distinct().forEach(System.out::println); 
// prints:
// nameC schoolD

However, it will not work in the following scenario, unless you override the equals method for SchoolObj:

List<SchoolObj> list = new ArrayList<>();
listOne.add(new SchoolObj("nameC", "schoolD"));
listOne.add(new SchoolObj("nameC", "schoolD"));
list.stream().distinct().forEach(System.out::println); 
// prints (unless Object::equals overridden)
// nameC schoolD
// nameC schoolD
2 of 3
9

You can filter in one list if contains in another list then collect.

List<SchoolObj> listCommon = listTwo.stream()
                                         .filter(e -> listOne.contains(e)) 
                                         .collect(Collectors.toList());

You need to override equals() method in SchoolObj class. contains() method you will uses the equals() method to evaluate if two objects are the same.

@Override
public boolean equals(Object o) {
    if (!(o instanceof SchoolObj))
        return false;
    SchoolObj n = (SchoolObj) o;
    return n.name.equals(name) && n.school.equals(school);
}

But better solution is to use Set for one list and filter in another list to collect if contains in Set. Set#contains takes O(1) which is faster.

Set<SchoolObj> setOne = new HashSet<>(listOne);
List<SchoolObj> listCommon = listTwo.stream()
                                     .filter(e -> setOne.contains(e)) 
                                     .collect(Collectors.toList());

You need to override hashCode() method also along with equals() in SchoolObj class for Set#contains.(assuming name and school can't be null)

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + name.hashCode();
    result = prime * result + school.hashCode();
    return result;
}

Here you will get details how to override equals and hashCode in a better way

🌐
Javaprogramto
javaprogramto.com › 2020 › 04 › how-to-compare-two-arraylist-for-equality-in-java.html
How to compare two ArrayList for equality in Java 8? ArrayList equals() or containsAll() methods works?
June 13, 2021 - ... In this article, We'll learn how to compare two ArrayLists for checking Objects equality. ArrayList has an equal() method that takes one argument type of Object. This equals() method compares the passed list object with the current list object.
🌐
DevQA
devqa.io › java-compare-two-arraylists
Java Compare Two Lists
To compare two lists for equality just in terms of items regardless of their location, we need to use the sort() method from the Collections() class. ... import java.util.Arrays; import java.util.Collections; import java.util.List; public class ...
🌐
DZone
dzone.com › coding › languages › how to compare list objects in java 7 vs. java 8
How to Compare List Objects in Java 7 vs. Java 8 - DZone
June 1, 2018 - Instead of writing logic for iterating over the stream elements and checking whether each object matches the criteria, Java 8 Streams allow declarative matching of objects in the stream. We need to define a Predicate instance with the comparison logic and provide this Predicate as an input to the matching methods.
🌐
WeTalkIt
wetalkitorg.wordpress.com › 2020 › 02 › 03 › how-to-compare-two-lists-in-java
How to compare two Lists in Java - WeTalkIt - WordPress.com
February 25, 2020 - In this paragraph, we will use a very powerfull method to compare two lists of elements in just a few line of code. The containsAll method will check, if all our employees (intern and extern) are also contain in the list of just intern employees. It returns false, when there are some employees (extern), that are not in the list of intern employees and true when we just have intern employees in the list allEmployees. Another to resolve this problem is the use of of the Java Stream Api. Since Java 8, we can use the Stream api on most common java problem.
🌐
amitph
amitph.com › home › java › comparing two lists in java
Comparing Two Lists In Java - amitph
November 22, 2024 - We may want to compare the two Lists to find the Students who equally perform well in Sports and Maths or the Sports toppers which are poor in Maths. There is no direct way to compare Java Lists to find their commonality or particularity in Java.
Find elsewhere
Top answer
1 of 3
24

Your question’s code does not reflect what you describe in the comments. In the comments you say that all names should be present and the size should match, in other words, only the order may be different.

Your code is

List<Person> people = getPeopleFromDatabasePseudoMethod();
List<String> expectedValues = Arrays.asList("john", "joe", "bill");

assertTrue(people.stream().map(person -> person.getName())
                 .collect(Collectors.toList()).containsAll(expectedValues));

which lacks a test for the size of people, in other words allows duplicates. Further, using containsAll combining two Lists in very inefficient. It’s much better if you use a collection type which reflects you intention, i.e. has no duplicates, does not care about an order and has an efficient lookup:

Set<String> expectedNames=new HashSet<>(expectedValues);
assertTrue(people.stream().map(Person::getName)
                 .collect(Collectors.toSet()).equals(expectedNames));

with this solution you don’t need to test for the size manually, it is already implied that the sets have the same size if they match, only the order may be different.

There is a solution which does not require collecting the names of persons:

Set<String> expectedNames=new HashSet<>(expectedValues);
assertTrue(people.stream().allMatch(p->expectedNames.remove(p.getName()))
           && expectedNames.isEmpty());

but it only works if expectedNames is a temporary set created out of the static collection of expected names. As soon as you decide to replace your static collection by a Set, the first solution doesn’t require a temporary set and the latter has no advantage over it.

2 of 3
4

If the number of elements must be the same, then it would be better to compare sets:

List<Person> people = getPeopleFromDatabasePseudoMethod();
Set<String> expectedValues = new HashSet<>(Arrays.asList("john", "joe", "bill"));
assertEquals(expectedValues, 
    people.stream().map(Person::getName).collect(Collectors.toSet()));

The equals method for properly implemented sets should be able to compare different types of sets: it just checks whether the contents is the same (ignoring the order of course).

Using assertEquals is more convenient as in case of failure an error message will contain the string representation of your set.

🌐
Java Code Geeks
javacodegeeks.com › home › core java
Check If Two Lists Are Equal In Java - Java Code Geeks
March 20, 2019 - Note that we have created copies of the two lists to ensure that the elements in the original lists remain untouched. If the data in our lists are unique i.e. there isn’t a duplication, we can simply create TreeSets from the given lists and then compare them using equals():
Top answer
1 of 4
19

If I understand correctly, this is the example scenario:

  • listOne [datab] items: [A, B, C, D]
  • listTwo [front] items: [B, C, D, E, F]

and what you need to get as an effect is:

  • added: [E, F]
  • deleted: [A]

First thing first, I would use some type adapter or extend the different types from one common class and override the equals method so you can match them by id and name

Secondly, this is very easy operations on sets (you could use set's but list are fine too). I recommend using a library: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html

And now basically:

  • added is listTwo - listOne
  • deleted is listOne - listTwo

and using java code:

  • added: CollectionUtils.removeAll(listTwo, listOne)
  • deleted: CollectionUtils.removeAll(listOne, listTwo)

Otherwise, all collections implementing Collection (Java Docs) also has removeAll method, which you can use.

2 of 4
18

I propose solution using java 8 streams:

    ArrayList<ObjOne> list = new ArrayList<>(Arrays.asList(new ObjOne("1","1"),new ObjOne("3","3"),new ObjOne("2","2")));
    ArrayList<ObjTwo> list2 = new ArrayList<>(Arrays.asList(new ObjTwo("1","1"),new ObjTwo("3","3"),new ObjTwo("4","4")));

    List<ObjOne> removed = list.stream().filter(o1 -> list2.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
            .collect(Collectors.toList());
    System.out.print("added ");
    removed.forEach(System.out::println);

    List<ObjTwo> added = list2.stream().filter(o1 -> list.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
             .collect(Collectors.toList());

    System.out.print("removed ");
    added.forEach(System.out::println);

This is basically your solution but implemented using streams, which will make your code shorter and easer to read

🌐
Javatpoint
javatpoint.com › how-to-compare-two-arraylist-in-java
How to Compare Two ArrayList in Java - Javatpoint
How to Compare Two ArrayList in Java with oops, string, exceptions, multithreading, collections, jdbc, rmi, fundamentals, programs, swing, javafx, io streams, networking, sockets, classes, objects etc,
Top answer
1 of 12
182

EDIT

Here are two versions. One using ArrayList and other using HashSet

Compare them and create your own version from this, until you get what you need.

This should be enough to cover the:

P.S: It is not a school assignment :) So if you just guide me it will be enough

part of your question.

continuing with the original answer:

You may use a java.util.Collection and/or java.util.ArrayList for that.

The retainAll method does the following:

Retains only the elements in this collection that are contained in the specified collection

see this sample:

import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;

public class Repeated {
    public static void main( String  [] args ) {
        Collection listOne = new ArrayList(Arrays.asList("milan","dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta"));
        Collection listTwo = new ArrayList(Arrays.asList("hafil", "iga", "binga", "mike", "dingo"));

        listOne.retainAll( listTwo );
        System.out.println( listOne );
    }
}

EDIT

For the second part ( similar values ) you may use the removeAll method:

Removes all of this collection's elements that are also contained in the specified collection.

This second version gives you also the similar values and handles repeated ( by discarding them).

This time the Collection could be a Set instead of a List ( the difference is, the Set doesn't allow repeated values )

import java.util.Collection;
import java.util.HashSet;
import java.util.Arrays;

class Repeated {
      public static void main( String  [] args ) {

          Collection<String> listOne = Arrays.asList("milan","iga",
                                                    "dingo","iga",
                                                    "elpha","iga",
                                                    "hafil","iga",
                                                    "meat","iga", 
                                                    "neeta.peeta","iga");

          Collection<String> listTwo = Arrays.asList("hafil",
                                                     "iga",
                                                     "binga", 
                                                     "mike", 
                                                     "dingo","dingo","dingo");

          Collection<String> similar = new HashSet<String>( listOne );
          Collection<String> different = new HashSet<String>();
          different.addAll( listOne );
          different.addAll( listTwo );

          similar.retainAll( listTwo );
          different.removeAll( similar );

          System.out.printf("One:%s%nTwo:%s%nSimilar:%s%nDifferent:%s%n", listOne, listTwo, similar, different);
      }
}

Output:

$ java Repeated
One:[milan, iga, dingo, iga, elpha, iga, hafil, iga, meat, iga, neeta.peeta, iga]

Two:[hafil, iga, binga, mike, dingo, dingo, dingo]

Similar:[dingo, iga, hafil]

Different:[mike, binga, milan, meat, elpha, neeta.peeta]

If it doesn't do exactly what you need, it gives you a good start so you can handle from here.

Question for the reader: How would you include all the repeated values?

2 of 12
45

You can try intersection() and subtract() methods from CollectionUtils.

intersection() method gives you a collection containing common elements and the subtract() method gives you all the uncommon ones.

They should also take care of similar elements

🌐
Coderanch
coderanch.com › t › 638779 › java › Compare-Contrast-ArrayList-Object
Compare and Contrast Two ArrayList<Object> (Java in General forum at Coderanch)
August 29, 2014 - There are 3 pieces of information you eventually want: - Added objects (exist in List 1 but not in List 2). - Removed objects (exist in List 2 but not in List 1). - Changed objects (exist in both lists, but one or more of their fields have changed). The first two are solved with a utility method that can compare two lists and return the difference of them.
🌐
Medium
medium.com › @QA-initi › how-to-compare-two-array-list-in-java-using-comparator-cc05617175b5
How to compare two array list in Java using Comparator | by QA-init | Medium
November 14, 2023 - In order to compare two ArrayList in Java using a comparator, we can use the Collections.sort() method and pass in the ArrayList and a custom comparator. Here is an example: ArrayList<Integer> list1 = new ArrayList<Integer>(); list1.add(3); ...
🌐
GeeksforGeeks
geeksforgeeks.org › java › list-equals-method-in-java-with-examples
List equals() Method in Java with Examples - GeeksforGeeks
January 3, 2025 - It compares the lists as, both lists should have the same size, and all corresponding pairs of elements in the two lists are equal. ... // Java code to show the implementation of // addAll method in list interface import java.util.*; public class Geeks { public static void main(String[] args) { // Initializing a list of type ArrayList List<Integer> l = new ArrayList<>(); l.add(1); l.add(2); // Initializing another list List<Integer> l2 = new ArrayList<>(); l2.add(1); l2.add(2); if (l.equals(l2)) System.out.println("Equal"); else System.out.println("Not equal"); } }
🌐
javaspring
javaspring.net › blog › compare-2-lists-java
Comparing Two Lists in Java: A Comprehensive Guide — javaspring.net
This can be slow for large lists. Use Descriptive Variable Names: Use meaningful variable names to make your code easier to understand. Extract Logic into Methods: If your comparison logic is complex, extract it into separate methods to improve code readability and maintainability. import java.util.ArrayList; import java.util.List; public class ReadableListComparison { public static boolean areListsEqual(List<String> list1, List<String> list2) { if (list1 == null && list2 == null) { return true; } if (list1 == null || list2 == null) { return false; } return list1.equals(list2); } public static void main(String[] args) { List<String> list1 = new ArrayList<>(); list1.add("apple"); List<String> list2 = new ArrayList<>(); list2.add("apple"); boolean areEqual = areListsEqual(list1, list2); System.out.println("Are the lists equal?