web-dev-qa-db-ja.com

Mapの値を収集するためのJava 8ストリーム内のストリームを含むハッシュマップ

ハッシュマップを考えてみましょう

Map<Integer, List> id1 = new HashMap<Integer,List>();

両方のハッシュマップにいくつかの値を挿入しました。

例えば、

    List<String> list1 = new ArrayList<String>();

    list1.add("r1");
    list1.add("r4");

    List<String> list2 = new ArrayList<String>();
    list2.add("r2");
    list2.add("r5");

    List<String> list3 = new ArrayList<String>();
    list3.add("r3");
    list3.add("r6");

    id1.put(1,list1);
    id1.put(2,list2);
    id1.put(3,list3);
    id1.put(10,list2);
    id1.put(15,list3);

Q1)ハッシュマップのキーにフィルター条件を適用し、対応するvalue(List)を取得したい。

例:ここでは、クエリはkey = 1であり、出力は 'list1'である必要があります

私が書いた

id1.entrySet().stream().filter( e -> e.getKey() == 1);

しかし、このストリーム操作の出力としてリストとして取得する方法がわかりません。

Q2)再度、ハッシュマップのキーにフィルター条件を適用し、対応するリストのリストを取得したい。

例:ここで、私のクエリはkey = 1%(つまり、キーは1,10,15になります)で、出力は 'list1'、 'list2'、 'list3'(リストのリスト)になります。

45
Deepak Shajan

フィルターを通過した要素を1つだけ取得すると確信している場合(フィルターで保証されています)、findFirstを使用できます。

Optional<List> o = id1.entrySet()
                      .stream()
                      .filter( e -> e.getKey() == 1)
                      .map(Map.Entry::getValue)
                      .findFirst();

一般的な場合、フィルターが複数のリストに一致する可能性がある場合、それらをリストのリストに収集できます。

List<List> list = id1.entrySet()
                     .stream()
                     .filter(.. some predicate...)
                     .map(Map.Entry::getValue)
                     .collect(Collectors.toList());
65
Eran

必要なことは、Stream.entrySet()からMapを作成することです。

// Map<K, V> --> Set<Map.Entry<K, V>> --> Stream<Map.Entry<K, V>>
map.entrySet().stream()

以降、これらのエントリを.filter()できます。例えば:

// Stream<Map.Entry<K, V>> --> Stream<Map.Entry<K, V>>
.filter(entry -> entry.getKey() == 1)

そして、そこから値を取得するには、.map()

// Stream<Map.Entry<K, V>> --> Stream<V>
.map(Map.Entry::getValue)

最後に、Listに収集する必要があります。

// Stream<V> --> List<V>
.collect(Collectors.toList())

エントリが1つだけの場合は、代わりにこれを使用します(注:このコードは値があると想定しています。それ以外の場合は、.orElse()を使用します。詳細については、 javadoc of Optional を参照してください):

// Stream<V> --> Optional<V> --> V
.findFirst().get()
27
fge

Q2については、すでに質問に対する回答があります。 Q1では、より一般的には、キーのフィルタリングが一意の値を提供する必要があることがわかっている場合、Streamsを使用する必要はまったくありません。

getまたはgetOrDefaultを使用します。つまり:

List<String> list1 = id1.getOrDefault(1, Collections.emptyList());
4
user2336315

このようにすることもできます

public Map<Boolean, List<Student>> getpartitionMap(List<Student> studentsList) {

    List<Predicate<Student>> allPredicates = getAllPredicates();
    Predicate<Student> compositePredicate =  allPredicates.stream()
                             .reduce(w -> true, Predicate::and)
     Map<Boolean, List<Student>> studentsMap= studentsList
                .stream()
                .collect(Collectors.partitioningBy(compositePredicate));
    return studentsMap;
}

public List<Student> getValidStudentsList(Map<Boolean, List<Student>> studentsMap) throws Exception {

    List<Student> validStudentsList =  studentsMap.entrySet()
             .stream()
             .filter(p -> p.getKey() == Boolean.TRUE)
             .flatMap(p -> p.getValue().stream())
             .collect(Collectors.toList());

    return validStudentsList;
}

public List<Student> getInValidStudentsList(Map<Boolean, List<Student>> studentsMap) throws Exception {

    List<Student> invalidStudentsList = 
             partionedByPredicate.entrySet()
             .stream()
             .filter(p -> p.getKey() == Boolean.FALSE)
             .flatMap(p -> p.getValue().stream())
             .collect(Collectors.toList());

    return invalidStudentsList;

}

flatMapを使用すると、List<Student>ではなくList<List<Student>>のみを取得します。

ありがとう

2
Basit