static void assertStreamEquals(Stream<?> s1, Stream<?> s2) {
    Iterator<?> iter1 = s1.iterator(), iter2 = s2.iterator();
    while(iter1.hasNext() && iter2.hasNext())
        assertEquals(iter1.next(), iter2.next());
    assert !iter1.hasNext() && !iter2.hasNext();
}
Answer from ZhongYu on Stack Overflow
๐ŸŒ
Baeldung
baeldung.com โ€บ home โ€บ java โ€บ java โ€“ powerful comparison with lambdas
Java โ€“ Powerful Comparison with Lambdas | Baeldung
January 8, 2024 - We can sort the stream using natural ordering, as well as ordering provided by a Comparator. For this, we have two overloaded variants of the sorted() API: sorted() โ€“ sorts the elements of a Stream using natural ordering; the element class must implement the Comparable interface.
๐ŸŒ
Oracle
docs.oracle.com โ€บ javase โ€บ 8 โ€บ docs โ€บ api โ€บ java โ€บ util โ€บ stream โ€บ Stream.html
Stream (Java Platform SE 8 )
3 weeks ago - Returns a stream consisting of the elements of this stream, sorted according to natural order. If the elements of this stream are not Comparable, a java.lang.ClassCastException may be thrown when the terminal operation is executed.
Top answer
1 of 3
10

There cannot be a simpler solution:

  • To know the duplicated ids, you must iterate over the entire collection.
  • To print all the persons with duplicated ids, you must keep their full list.

As such, you will need to load the entire collection of persons in memory. There's no way around that. If you needed only the duplicate ids but not the Person objects, then you could keep just the ids with their counts, and throw away the Person objects as you go after use, that would be more efficient. (But that's not the case here.)

In any case, your solution can be more concise if you skip the intermediary map variable with the mapping of ids to lists of users:

people.stream()
        .collect(Collectors.groupingBy(Person::getId)).values().stream()
        .filter(peopleWithSameId -> peopleWithSameId.size() > 1)
        .forEach(peopleWithSameId -> System.out.println("People with identical IDs: " + peopleWithSameId));

Btw, in case you're wondering if the .stream() there could be .parallelStream(), it would be pointless, due to the synchronization in the println method of System.out (a PrintStream). (And without synchronization println wouldn't be thread safe anyway.)

2 of 3
10

Your code and Java 8 usage looks fine in general to me.

I do see an issue with the Person class, it looks like you are intending it to be an immutable class, if so, then you should also enforce it.

You need to ensure that the name and id fields can never be changed, you can do this by adding final to them. Your code currently seems to be safe, but it is not. I can extend Person and offer a method there to change the name and id fields, which violates the assumed variant of that those fields in Person are immutable.

Simply changing it to the following will do:

public class Person {
    private final String name;
    private final String id;
    ...
}

Onto the Java 8 usage now.

It is a good thing that you use the Collectors.groupingBy to provide a Map<String, List<Person>>, you cannot do it much faster either way if you want it to work with any kind of List<Person> as input and in this way you'll save yourself from nasty bugs and reimplementing what lots of people have already done, namely the grouping by operation.

Printing the offending values using Stream seems fine as well, except that you may rewrite it to look a little bit cleaner, something like this could work:

peopleById.values().stream()
    .filter(personList -> personList.size() > 1)
    .forEach(personList -> System.out.println("People with identical IDs: " + personList);

This is my personal preference on how to format it though, the only real change is to rename peopleWithSameId to personList, as it is simply a List<Person> and nothing more or less.

You've done a good job overall.

๐ŸŒ
SWTestAcademy
swtestacademy.com โ€บ home โ€บ java streams comparators with examples
Java Streams Comparators with Examples
October 10, 2021 - Hi all, in this article, we will ...ralOrder(), Comparator.reverseOrder(), etc. The Comparator Interface provides us comparison and sorting options that we can use with Java Streams....
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 70708207 โ€บ comparing-elements-within-stream
java - Comparing elements within Stream - Stack Overflow
Then, there is no way around doing one pass over the itemList to get the maximum price first, followed by the conversion loop which can compare the current itemโ€™s price with the maximum. This would also be the only solution supporting immutable objects, by the way. Of course, either pass could be implemented as loop or stream operation.
๐ŸŒ
Baeldung
baeldung.com โ€บ home โ€บ java โ€บ guide to java comparator.comparing()
Guide to Java Comparator.comparing() | Baeldung
January 8, 2024 - A practical guide to the static functions and instance methods of the Comparable interface that were introduced in Java 8.
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ java โ€บ stream-sorted-comparator-comparator-method-java
Stream sorted (Comparator comparator) method in Java - GeeksforGeeks
December 26, 2025 - In Java, the Stream.sorted(Comparator comparator) method sorts the elements of a stream based on a provided Comparator and returns a new sorted stream.
Find elsewhere
๐ŸŒ
Medium
medium.com โ€บ @coffeeandtips.tech โ€บ using-comparator-comparing-to-sort-java-stream-a6e0302dce1a
Using Comparator.comparing to sort Java Stream | by Coffee and Tips | Medium
December 2, 2023 - The Comparator.comparing interface is a powerful tool to perform the sorting of Streams in Java. Its flexibility, ascending and descending sorting capabilities, support for multiple criteria, and efficient execution make it a valuable choice ...
Top answer
1 of 3
12

Let listOne.size() is N and listTwo.size() is M. Then 2-for-loops solution has complexity of O(M*N).

We can reduce it to O(M+N) by indexing listTwo by ids.

Case 1 - assuming listTwo has no objects with the same id

// pair each id with its marks
Map<String, String> marksIndex = listTwo.stream().collect(Collectors.toMap(ObjectTwo::getId, ObjectTwo::getMarks));
// go through list of `ObjectOne`s and lookup marks in the index
listOne.forEach(o1 -> o1.setScore(marksIndex.get(o1.getId())));

Case 2 - assuming listTwo has objects with the same id

    final Map<String, List<ObjectTwo>> marksIndex = listTwo.stream()
            .collect(Collectors.groupingBy(ObjectTwo::getId, Collectors.toList()));

    final List<ObjectOne> result = listOne.stream()
            .flatMap(o1 -> marksIndex.get(o1.getId()).stream().map(o2 -> {
                // make a copy of ObjectOne instance to avoid overwriting scores
                ObjectOne copy = copy(o1);
                copy.setScore(o2.getMarks());
                return copy;
            }))
            .collect(Collectors.toList());

To implement copy method you either need to create a new object and copy fields one by one, but in such cases I prefer to follow the Builder pattern. It also results in more "functional" code.

2 of 3
3

Following code copies marks from ObjectTwo to score in ObjectOne, if both ids are equal, it doesn't have intermediate object List<ObjectOne> result

listOne.stream()
    .forEach(one -> {listTwo.stream()
        .filter(two -> {return two.getId().equals(one.getId());})
        .limit(1)
        .forEach(two -> {one.setScore(two.getMarks());});
    });
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ comparing-streams-to-loops-in-java
Comparing Streams to Loops in Java
Integer Stream Is Here: 12345678910111213141516171819 Integer Stream Values With The Value Skip : 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Integer Stream With Sum We Can Get: 10 Stream.of, sorted and Find The First : 2022 Stream from Array, sort, filter and print : Average of squares of an int array : 44.0 Stream from List, filter and print : ai Reduction - sum : Total = 13.600000000000001 Reduction - summary statistics : IntSummaryStatistics{count=7, sum=203, min=2, average=29.000000, max=88} In this particular Java approach, we are going to create a list first. By using that particular list we will compare the streams with some loops to get a new sorted data elements from that declared data set previously.
๐ŸŒ
CodePal
codepal.ai โ€บ code generator โ€บ java stream compare and filter
Java Stream Compare and Filter - CodePal
November 21, 2023 - public static void main(String[] args) { // Example: Filtering a list of integers List<Integer> numbers = new ArrayList<>(); numbers.add(1); numbers.add(2); numbers.add(3); numbers.add(4); numbers.add(5); Stream<Integer> numberStream = numbers.stream(); // Filter out even numbers List<Integer> filteredNumbers = StreamUtils.compareAndFilter(numberStream, n -> n % 2 == 0); System.out.println("Filtered Numbers: " + filteredNumbers); }
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ java โ€บ comparing-streams-to-loops-in-java
Comparing Streams to Loops in Java - GeeksforGeeks
October 20, 2022 - Integer Stream : 123456789 Integer Stream with skip : 6 7 8 9 Integer Stream with sum : 10 Stream.of, sorted and findFirst : Java Stream from Array, sort, filter and print : Scikit Average of squares of an int array : 44.0 Stream from List, filter and print : ai Reduction - sum : Total = 13.600000000000001 Reduction - summary statistics : IntSummaryStatistics{count=7, sum=203, min=2, average=29.000000, max=88}
Top answer
1 of 2
3

Your immediate problem is trivial to fix:

Optional<Integer> oi = nums.stream()
                           .filter(x -> x > nextNumber)
                           .findFirst();
System.out.println(oi.isPresent()? "Found: "+oi.get() : "Not found");

However, if you want to write code which optimally computes what you require it to, it is not the right approach. A far better option would be this:

OptionalInt oi = Stream.of(scn.nextLine().split(" "))
                       .mapToInt(Integer::parseInt)
                       .filter(i -> i > nextNumber)
                       .min();
System.out.println(oi.isPresent()? "Found: "+oi.getAsInt() : "Not found");

The advantage is that you never get an ArrayList involved and don't need to autobox the integers at any step, and you actually retrieve the smallest number satisfying the criterion, not the first one.

2 of 2
2

If you want to find the smallest number larger than some bound:

private int smallestLargerThan(int x, List<Integer> list) {
    return list.stream().filter(n -> n > x).mapToInt(n -> n).min();
}

.filter(n -> n > x) drops all values less than or equal to x.

.mapToInt(n -> n) transforms the Stream to an IntStream, which is required for the next operation:

.min() returns the smallest element in the IntStream. Since the stream at this point only contains values greater than x, the returned element is the number you are looking for.

The code you posted won't compile because .findFirst() returns an Optional<Integer>, not an Integer. It is also semantically wrong because the first element is not necessarily the smallest as your Stream is unsorted.

๐ŸŒ
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
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.
๐ŸŒ
Java67
java67.com โ€บ 2021 โ€บ 09 โ€บ java-comparator-multiple-fields-example.html
How to sort a List or Stream by Multiple Fields in Java? Comparator comparing() + thenComparing Example | Java67
You can use these two methods to easily compare a list or array of objects on multiple fields like you can compare a list of persons into firstName and if two persons have the same firstName you can compare their lastName to break ties. ... Thanks for reading this article so far. If you have any questions or feedback then please drop a comment. If you like this article then please share it with your friends and colleagues. P.S. - If you want to learn more about Core Java and Functional programming concepts like Lambda, Stream, and functional like map, flat map, and filter then please see these best Java Functional Programming courses.
๐ŸŒ
Medium
hudsonmendes.medium.com โ€บ comparator-vs-compartor-comparing-when-sorting-java-streams-8a98da021668
Comparator<> vs Compartor.comparing when sorting Java Streams
August 4, 2023 - Comparator vs Compartor.comparing when sorting Java Streams Reduce the amount of comparators you have using Comparator.comparing(). When implementing sorting logic, itโ€™s common to choose one out โ€ฆ