6

We have a map of Student to record Map<Student, StudentRecord>.
Student class is as follows:

Student {
    String id;
    String grade;
    Int age; 
}

Additionally, we have a list of Student Id (List<String>) provided.
Using Java streams, what would be the most efficient way to filter out records of students whose Id exists in the provided list?
The expected outcome is the filtered list mapped against the Id(String) - <Map<Id, StudentRecord>>

4
  • 5
    If the input is a Map<Student,StudentRecord>, how come the output is a List<Map<Student,StudentRecord>>? Shouldn't the output be a Map<Student,StudentRecord> where some of the entries are filtered out? Commented Jan 1, 2020 at 8:39
  • 5
    And anyway, before finding "the most efficient way", you should first try to find "a way". Have you tried anything? What's the concrete problem you faced? Commented Jan 1, 2020 at 8:42
  • Edited the question as per Eran's observation.Have never tried intersection using java streams. Commented Jan 1, 2020 at 8:47
  • So now is the right moment. Hint: don't think about it as "an intersection". Think about it as: I have a map, which is a collection of entries, and I only want some of them. And once I know the ones I want, I want to store them in another map. Commented Jan 1, 2020 at 8:50

3 Answers 3

1

You can stream set of entries:

map.entrySet().stream()
    .filter(e -> list.contains(e.getKey()))
    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

If you also want to map keys to id field, then:

map.entrySet().stream()
    .filter(e -> list.contains(e.getKey()))
    .collect(toMap(e -> e.getKey().getId(), Map.Entry::getValue));
Sign up to request clarification or add additional context in comments.

Comments

1

First of all, I'd convert your List to a Set, to avoid linear search time:

List<String> ids = ...
Set<String> idsSet = new HashSet<>(ids);

Now, you can stream over the entries of the Map, filter out those having ids in the List/Set, and collect the remaining ones to an output Map:

Map<String,StudentRecord> filtered = 
    input.entrySet()
         .stream()
         .filter(e -> !idsSet.contains(e.getKey().getId()))
         .collect(Collectors.toMap(e -> e.getKey().getId(),Map.Entry::getValue));

Comments

1

Although other answers are correct but I think they are not more efficient since they use temporary memory or its complicity is not o(n).

the other answer is like this:

provided.stream()
        .map(id -> new AbstractMap.SimpleEntry<>(id, map.entrySet()
                    .stream().filter(st -> st.getKey().id == id)
                    .map(Map.Entry::getValue).findFirst()))
        .filter(simpleEntry ->simpleEntry.getValue().isPresent())
        .map(entry-> new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue().get()))
        .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue)) 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.