-1

I have 2 distinct lists: List1 and List2, and I want to perform an action for each index where the elements have the same getName() value:

for (int i = 0; i < 5; i++) { 
    if (list1.get(i).getName().equals(list2.get(i).getName())) {
        // TODO
    }
}

Is there a way to do this using Java streams? I have tried the logic:

if (List1().stream().anymatch(x -> List2().stream().anymatch(y -> x.getName().equals(y.getName))))) {
    // TODO
}

This works, but first object(index) of List1 is compared with every object(index) of List2.

What I need is first object(index) of List1 to be compared with first of List2, second index to second and so on. How to write this if logic using stream instead of for loop.

M. Justin
  • 14,487
  • 7
  • 91
  • 130
  • 1
    Please dont post code as images – Saatvik Ramani Aug 02 '21 at 13:54
  • Use an `IntStream` to generate the indices e.g. `IntStream.range(0, 5)`, then use `map`, `mapToObj` or `forEach` as appropriate and access `obj1.get(i)` and `obj2.get(i)`. – Andy Turner Aug 02 '21 at 13:56
  • `IntStream.range(0, a.length).mapToObj(i -> a[i].getName() == b[i].getName()).collect(Collectors.toList()); ` something like this? – Saatvik Ramani Aug 02 '21 at 14:01
  • What do you want after condition check. Are you going to store data in another list. please be specific toward your question and go to this link. Your question is explained here https://stackoverflow.com/questions/57252497/java-8-streams-compare-two-lists-object-values-and-add-value-to-new-list – Sheshanath Kumar Aug 02 '21 at 14:05
  • Hi sorry for the inconvenience, now added additional information to the question. kindly help me with this. – sathya moorthy Aug 02 '21 at 14:41
  • @SheshanathKumar i am not going to store values using it, just need to compare values from two different list, based on the constraint i have mentioned in the question. – sathya moorthy Aug 02 '21 at 14:45
  • One approach would be to zip the two streams and filter on any where they match. There's nothing built-in for this, but there are ways to do it, including third-party libraries. I would take a look at this: https://stackoverflow.com/questions/17640754/zipping-streams-using-jdk8-with-lambda-java-util-stream-streams-zip. – M. Justin Aug 02 '21 at 17:35
  • Does the operation you want to perform need the matching element from the first list, the matching element from the second list, the name, or the index? – M. Justin Aug 04 '21 at 19:37

2 Answers2

0

One solution is to use a third-party library that has the ability to zip pairs of streams into a single stream of pairs. Using this approach, the two streams would be zipped into a single stream containing the pairs of elements, the pairs with equal names would be retained via a call to Stream.filter(), and then finally the remaining filtered pairs of elements will have the action applied to them.

The Stack Overflow answer Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip) contains various solutions for zipping two streams in this manner.

Guava

Google's Guava library provides the Streams.zip method:

Streams.zip(list1.stream(), list2.stream(), Map::entry)
        .filter(e -> e.getKey().getName().equals(e.getValue().getName()))
        .forEachOrdered(e ->
                System.out.println("Match: " + e.getKey() + ", " + e.getValue()));

StreamEx

The StreamEx library provides multiple zip methods, including StreamEx.zip and EntryStream.zip:

EntryStream.zip(list1, list2)
        .filterKeyValue((k, v) -> k.getName().equals(v.getName()))
        .forKeyValue((k, v) -> System.out.println("Match: " + k + ", " + v));
M. Justin
  • 14,487
  • 7
  • 91
  • 130
0

One approach would be to stream over the indexes rather than the lists, and use List.get(i) to retrieve elements from each List.

IntStream.range(0, list1.size())
        .mapToObj(i -> Map.entry(list1.get(i), list2.get(i)))
        .filter(e -> e.getKey().getName().equals(e.getValue().getName()))
        .forEachOrdered(e ->
                System.out.println("Match: " + e.getKey() + ", " + e.getValue()));

or

IntStream.range(0, list1.size())
        .filter(i -> list1.get(i).getName().equals(list2.get(i).getName()))
        .forEachOrdered(i ->
                System.out.printf("Match at index %s: %s, %s\n", i, list1.get(i), list2.get(i)));

Note for this approach to be efficient, the lists must support fast (e.g. constant-time) random access. This would generally mean any list which implements the RandomAccess interface, such as ArrayList and Arrays.asList().

M. Justin
  • 14,487
  • 7
  • 91
  • 130