Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intersecting List with keys of Map

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>>

like image 398
IUnknown Avatar asked Jan 01 '20 08:01

IUnknown


3 Answers

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));
like image 198
Andronicus Avatar answered Oct 17 '22 00:10

Andronicus


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));
like image 44
Eran Avatar answered Oct 16 '22 23:10

Eran


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)) 
like image 20
Hadi J Avatar answered Oct 17 '22 01:10

Hadi J