Instead of using an auxiliary list to hold the indices, you can have them generated by an IntStream.

Map<Double, String> map = IntStream.range(0, list1.size())
            .boxed()
            .collect(Collectors.toMap(i -> list1.get(i), i -> list2.get(i)));
Answer from svarog on Stack Overflow
🌐
Baeldung
baeldung.com › home › java › java collections › java map › combining two lists into a map in java
Combining Two Lists Into a Map in Java | Baeldung
June 27, 2025 - As we see in the code above, the IntStream.range() method generates a stream of integers from 0 to the size of KEY_LIST. It’s worth mentioning that IntStream is a primitive stream. Therefore, we use the boxed() method to convert the IntStream to a Stream<Integer>, which allows us to use the collect() method to collect the elements into a Map. We’ve learned two approaches to associate two lists and get a Map as a result.
Discussions

Java 8 stream with two Lists - Stack Overflow
I have a method takes 2 lists as parameters and as you can see in the method body I want to do some filtering and returning the result to the caller. I wanted to convert this code to the Java 8 str... More on stackoverflow.com
🌐 stackoverflow.com
java - Set object properties in a list based on matching object in another list using the Stream API - Stack Overflow
Which is the best way to implement this with java.util.stream? ... Currently, your code has quadratic complexity. Do you actually want to check all combinations of elements, or only elements at the same index of their respective list? ... Does id mean a unique identifier for your objects? In that case a map ... More on stackoverflow.com
🌐 stackoverflow.com
April 25, 2017
java - Streaming two lists into a map - Stack Overflow
I'm trying to learn java 8 streams and i'm having trouble converting the following code into streams parents = new ArrayList () ... children = new ArrayList () ... Map More on stackoverflow.com
🌐 stackoverflow.com
collections - Java 8 Collect two Lists to Map by condition - Stack Overflow
I have an object: public class CurrencyItem { private CurrencyName name; private BigDecimal buy; private BigDecimal sale; private Date date; //... } where CurrencyName is one o... More on stackoverflow.com
🌐 stackoverflow.com
November 28, 2015
🌐
Javadeveloperzone
javadeveloperzone.com › java-basic › java-stream-of-multiple-lists
Java Stream of Multiple Lists – Java Developer Zone
List<Integer> odd = Arrays.asList(1, 3, 5, 7, 9); List<Integer> even = Arrays.asList(2, 4, 6, 8, 10); List<Integer> armstrongNo = Arrays.asList(0, 1, 153, 370, 371); List<List<Integer>> listOfList = new ArrayList<>(); lists.add(odd); lists.add(even); lists.add(armstrongNo); Stream<Integer> integerStream = listOfList.stream() .flatMap(Collection::stream); //Here, All current stream elements mapped to stream //OR: .flatMap(list -> list.stream()) integerStream.forEach(System.out::println); //Print all elements of sub lists: odd, even and armstrongNo · 1 //odd list elements 3 5 7 9 2 //even list elements 4 6 8 10 0 //multiplesOfTen list elements 1 153 370 371 · We have seen, how to get Java Stream of Multiple Lists using Java 8 Stream API (Stream interface) with an example.
🌐
Byte Padding
bytepadding.com › home › java › java core › java 8 – flatmap to find a pair of elements from two list
Java 8 – flatmap to find a pair of elements from two List | Byte Padding
March 25, 2017 - List list1 = Arrays.asList(1, 2, 3); List list2 = Arrays.asList(3, 4); List<Integer[]> pairs = list1.stream() .flatMap(i -> list2.stream() .map(j -> new Integer[]{i, j}) ).
🌐
Stack Overflow
stackoverflow.com › questions › 40980948 › streaming-two-lists-into-a-map
java - Streaming two lists into a map - Stack Overflow
I'm trying to learn java 8 streams and i'm having trouble converting the following code into streams · Copyparents = new ArrayList<Integer>() ... children = new ArrayList<Intger>() ... Map<Integer, List<Integer>> result = new HashMap<Integer, List<Integer>>(); for (Integer parentId : parents) { result.put(parentId, new ArrayList<Integer>(children)); } return result;
🌐
Davidvlijmincx
davidvlijmincx.com › home › java › java stream join lists
Java Stream join lists
March 10, 2022 - The easiest way to join two lists with Streams is by using the Stream.concat(Stream a, Stream b) method. The method takes two Stream instances as parameters and puts the second Stream behind the first Stream.
Find elsewhere
Top answer
1 of 2
7

This should be optimal. You first build a map from the currencies to their commercial banks. Then you run through your centrals building a map from commercial to central (looked up in the first map).

    List<CurrencyItem> currenciesByCommercialBank = new ArrayList<>();
    List<CurrencyItem> currenciesByCentralBank = new ArrayList<>();
    // Build my lookup from CurrencyName to CommercialBank.
    Map<CurrencyName, CurrencyItem> commercials = currenciesByCommercialBank
            .stream()
            .collect(
                    Collectors.toMap(
                            // Map from currency name.
                            ci -> ci.getName(),
                            // To the commercial bank itself.
                            ci -> ci));
    Map<CurrencyItem, CurrencyItem> commercialToCentral = currenciesByCentralBank
            .stream()
            .collect(
                    Collectors.toMap(
                            // Map from the equivalent commercial
                            ci -> commercials.get(ci.getName()),
                            // To this central.
                            ci -> ci
                    ));
2 of 2
4

The following code is O(n2), but it should be OK for small collections (which your lists probably are):

return currenciesByCommercialBank
    .stream()
    .map(c ->
        new AbstractMap.SimpleImmutableEntry<>(
            c, currenciesByCentralBank.stream()
                                      .filter(c2 -> c.currencyName == c2.currencyName)
                                      .findFirst()
                                      .get()))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  }

The above is appropriate if you want to assert that currenciesByCentralBank contains a match for each item in currenciesByCommercialBank. If the two lists can have mismatches, then the following would be appropriate:

currenciesByCommercialBank
    .stream()
    .flatMap(c ->
        currenciesByCentralBank.stream()
                               .filter(c2 -> c.currencyName == c2.currencyName)
                               .map(c2 -> new AbstractMap.SimpleImmutableEntry<>(c, c2)))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

In this case the map will contain all the matches and won't complain about missing entries.

🌐
Stack Abuse
stackabuse.com › java-convert-map-to-list
Java 8: How to Convert a Map to List
October 10, 2023 - One of the Collectors that we can ... one-dimensional collections - the other approach would be to convert a Map to two Lists, one of which will contain the Map's keys, while the other would contain the Map's values....
Top answer
1 of 5
9

Can we collect two lists from Java 8 streams?

You cannot but if you have a way to group elements of the Lists according to a condition. In this case you could for example use Collectors.groupingBy() that will return Map<Foo, List<Bar>> where the values of the Map are the two List.

Note that in your case you don't need stream to do only filter.

Filter the invalid list with removeIf() and add all element of that in the first list :

invalidList.removeIf(o -> conditionToRemove);
goodList.addAll(invalidList);      

If you don't want to change the state of goodList you can do a shallow copy of that :

invalidList.removeIf(o -> conditionToRemove);
List<Foo> terminalList = new ArrayList<>(goodList);
terminalList.addAll(invalidList);
2 of 5
9

One way using Java 8 streams API is to use the Collectors.partitioningBy collector.

Consider I have a List of String elements: the input list has strings with various lengths; only strings with length 3 are valid.

List<String> input = Arrays.asList("one", "two", "three", "four", "five");
Map<Boolean, List<String>> map =
        input.collect(Collectors.partitioningBy(s -> s.length() == 3));
System.out.println(map); // {false=[three, four, five], true=[one, two]}

List<String> valid = map.get(true);    // [one, two]
List<String> invalid = map.get(false); // [three, four, five]

The resulting Map has only two records; one with valid and the other with not-valid input list elements. The map record with key=true has the valid string as a List: one, two. The other is a key=false and the not-valid strings: three, four, five.

Note that Collectors.partitioningBy produces always two records in the resulting map irrespective of the existence of valid or not-valid values.

🌐
Oracle
oracle.com › java › technical details
Part 2: Processing Data with Java SE 8 Streams
In other words, partitioning a stream of transactions organizes the transactions into a Map<Boolean, List<Transaction>>. For example, if you want to group the transactions into two lists—cheap and expensive—you could use the partitioningBy collector as shown in Listing 18, where the lambda t -> t.getValue() > 1000 is a predicate for classifying cheap and expensive transactions.
🌐
amitph
amitph.com › home › java › examples of converting list to map using streams
Examples of Converting List to Map using Streams | amitph
November 22, 2024 - Here, were are streaming through a List of User objects and creating a Map of their Id to the last names. Map<Long, String> map = users.stream() .collect (Collectors.toMap(User::getId, User::getLastName));Code language: Java (java)
Top answer
1 of 2
1

Ah now I understand what you want :) I don't know if there is a better way with streams but here is a solution which would work.

List<Map<String, String>> resultList = l1.stream()
        .map(m1 -> {
           Map<String, String> map = new HashMap<>();
           map.putAll(m1);
           l2.stream()
               .filter(m2 -> map.get("ID").equals(m2.get("ID")))
               .findFirst()
               .ifPresent(m2 -> map.put("director", m2.get("director")));
           return map;
        })
        .collect(Collectors.toList());

The above code generates a new List resultList and does not modify the other lists List1 and List2. If it does not matter if List1 gets modified or not you could do it in a cleaner, more readable way.

l1.forEach(m1 -> l2.stream()
    .filter(m2 -> m1.get("ID").equals(m2.get("ID")))
    .findFirst()
    .ifPresent(m2 -> m1.putIfAbsent("director", m2.get("director"))));

This way the entries of list1 get modified. So with the above example list1 is becomes the joined list. But it's actually good practice to have methods without any side effects. So I would not prefer the above example.

I would recommend a method getJoinedList which returns a new List and does not modify the other lists. And in this case I would not use streams but the old-fashioned for-loop.

private static List<Map<String, String>> getJoinedList(
    List<Map<String, String>> l1, List<Map<String, String>> l2) {

    List<Map<String, String>> result = new ArrayList<>();
    for (Map<String, String> m1 : l1) {
        Map<String, String> newMap = new HashMap<>();
        newMap.putAll(m1);
        for (Map<String, String> m2 : l2) {
            if (m1.get("ID").equals(m2.get("ID"))) {
                newMap.put("director", m2.get("director"));
                break;
            }
        }
        result.add(newMap);
    }

    return result;
}

Then you just can call the method like this.

List<Map<String, String>> joinedList = getJoinedList(l1, l2);
2 of 2
1

If performance matters, you should first build an index of directors:

Map<Object, Object> directors = list2.stream()
    .collect(Collectors.toMap(m -> m.get("ID"), m -> m.get("director")));

Then you can merge the directors to the list entries easily:

list1.stream().forEach(m -> m.put("director", directors.get(m.get("ID"))));

Accesing the director via a Map will be faster than searching the director for each list entry.

🌐
Medium
medium.com › @kiarash.shamaii › list-map-vs-stream-map-in-java-44440284386
List.foreach() vs Stream().map() in Java
August 28, 2024 - List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> squaredNumbers = numbers.stream().map(x -> x * x).collect(Collectors.toList());
🌐
GeeksforGeeks
geeksforgeeks.org › java › program-to-convert-list-to-map-in-java
Program to Convert List to Map in Java - GeeksforGeeks
June 19, 2019 - import java.util.*; import java.util.stream.Collectors; class Student { private int id; private String name; Student(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public String getName() { return name; } } class ListToMapStream { public static void main(String[] args) { List<Student> students = new ArrayList<>(); students.add(new Student(101, "Aman")); students.add(new Student(102, "Riya")); students.add(new Student(103, "Rahul")); Map<Integer, String> map = students.stream().collect(Collectors.toMap( Student::getId, Student::getName)); System.out.println("List converted to Map: " + map); } } ... Explanation: Student::getId is used to create the Map keys, while Student::getName provides the corresponding values. Note: Collectors.toMap() throws IllegalStateException if two elements produce the same key.
Top answer
1 of 3
2

Using Collectors.groupingBy, you can generate a Map from your Key to a List of Values, provided you can compute the Key from the Value. Alternatively, you can use Collectors.toMap, provided you can compute both the Key and the Value from an upstream element. You probably want the version of toMap with a merge function, because that will allow you to handle multiple keys with the same value (by putting them in a list together).

Edit:
If you want ordering, there are overloads for toMap and groupingBy that allow you to provide a mapFactory (Supplier<Map>) , such as TreeMap::new.

2 of 3
0

To invert a map, so that its distinct values become keys, and its keys are added to a collection under the corresponding value, use groupingBy() on the map entries. It's important that the values from the original map implement equals() and hashCode() correctly to be used as a key in the new hash table .

static <K, V> Map<V, Set<K>> invert(Map<? extends K, ? extends V> original) {
  return original.entrySet().stream()
    .collect(Collectors.groupingBy(
      Map.Entry::getValue, 
      Collectors.mapping(Map.Entry::getKey, Collectors.toSet())
    ));
}

If you want to groups to be sorted, you can create a specialized "downstream" collector:

static <K, V> Map<V, SortedSet<K>> invert(
    Map<? extends K, ? extends V> original, 
    Comparator<? super K> order) {

  Collector<K, ?, SortedSet<K>> toSortedSet = 
     Collectors.toCollection(() -> new TreeSet<>(order));
  return original.entrySet().stream()
    .collect(Collectors.groupingBy(
      Map.Entry::getValue, 
      Collectors.mapping(Map.Entry::getKey, toSortedSet)
    ));
}
🌐
Reddit
reddit.com › r/javahelp › compare two list to pull out matching records
r/javahelp on Reddit: Compare two List<Map<String, Object>> to pull out matching records
August 16, 2022 -

I have two lists containing maps, the four keys are instrument, party, quantity, and entity.

If the values match between query1 and query2 results I want to add the matching maps into a list. So we can tell map1 in query1 matches map3 in query2. This is for reconciliation of data where there will be a plethora of records so essentially we want to go through each map in query1 results and compare to all maps in query2 results until there is a match. Once there is a match, we want to create a unique identifier or some sort of a pair to show that the two maps are equal and thus can be deemed a match. If we go through a full iteration and map1 in query1 does not equal any maps in query 2 we can then mark map1 in query1 a break, which would be adding the key to a break list.

Please let me know if you need more information. I've added the 3 different attempts I have tried, however none seem to make a match.

 public void reconcile(LocalDate date) {
    List<Map<String, Object>> query1Records;
    List<Map<String, Object>> query2Records;
    try (Stream<Map<String, Object>> stream = executeQuery1(date)) {
      query1Records = stream.collect(Collectors.toList());
    }
    try (Stream<Map<String, Object>> stream = executeQuery2(date)) {
      query2Records = stream.collect(Collectors.toList());
    }

//  ATTEMPT #1
    List<Map<String,Object>> unMatchedRecords = query1Records.parallelStream().filter(searchData ->
            query2Records.parallelStream().noneMatch( inputMap ->
                    searchData.entrySet().stream().noneMatch(value ->
                            inputMap.entrySet().stream().noneMatch(value1 ->
                                    (value1.getKey().equals(value.getKey()) &&
                                            value1.getValue().equals(value.getValue()))))
            )).collect(Collectors.toList());

//  ATTEMPT #2
    List<Map<String, Object>> matching = query1Records.parallelStream().filter(searchData ->
                    query2Records.parallelStream().anyMatch(inputMap ->
                            String.valueOf(searchData.get("quantity")).equals(inputMap.get("quantity"))
                                    && searchData.get("instrument").equals(inputMap.get("instrument"))
                    && searchData.get("entity").equals(inputMap.get("entity"))
                    && searchData.get("party").equals(inputMap.get("party"))))
            .collect(Collectors.toList());


//    ATTEMPT #3
    List<String> keysToReconcile = Arrays.asList("quantity", "instrument", "entity", "party");

    Function<Map<String,Object>,List<?>> getKey
            = m -> keysToReconcile.stream().map(m::get).collect(Collectors.toList());

    Map<List<?>,Map<String, Object>> inputKeys = query1Records.stream()
            .collect(Collectors.toMap(
                    getKey,
                    m -> m,
                    (a,b) -> { throw new IllegalStateException("duplicate "+a+" and "+b); },
                    LinkedHashMap::new));

    List<Map<String,Object>> matchingRecords = query2Records.stream()
            .filter(m -> inputKeys.containsKey(getKey.apply(m)))
            .collect(Collectors.toList());

    matchingRecords.forEach(m -> inputKeys.remove(getKey.apply(m)));
    List<Map<String,Object>> notMatchinRecords = new ArrayList<>(inputKeys.values());
  }
}

Top answer
1 of 2
2
Have you considered using a record to hold the information instead of a map? Would be much easier to do item-per-item comparison.
2 of 2
1
Please ensure that: Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions You include any and all error messages in full You ask clear questions You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions. Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar If any of the above points is not met, your post can and will be removed without further warning. Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://imgur.com/a/fgoFFis ) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc. Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit. Code blocks look like this: public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above. If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures. To potential helpers Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice. I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
🌐
Baeldung
baeldung.com › home › java › java list › intersection of two lists in java
Intersection of Two Lists in Java | Baeldung
April 4, 2025 - Well, as long as we follow Java’s conventions, the solution with stream methods will work fine for our custom class. How does the contains method decide whether a specific object appears in a list? Based on the equals method. Thus, we have to override the equals method and make sure that it compares two objects based on the values of the relevant properties.