web-dev-qa-db-ja.com

Java 8を使用して2つのリストを反復およびフィルタリングする

2つのリストを反復処理し、2番目のリストにない値を持つ新しいフィルターリストを取得します。誰でも助けることができますか?

2つのリストがあります。1つは文字列のリストで、もう1つはMyClassオブジェクトのリストです。

List<String> list1;
List<MyClass> list2;

MyClass {

    MyClass(String val)
    {
        this.str = val;
    }

     String str;
     ...
     ...
}

に基づいて文字列のフィルターされたリストが必要です->値がlist1にない要素(abc)の2番目のリストをチェック.

List<String> list1 = Arrays.asList("abc", "xyz", "lmn");

List<MyClass> list2 = new ArrayList<MyClass>();

MyClass obj = new MyClass("abc");
list2.add(obj);
obj = new MyClass("xyz");
list2.add(obj);

今、私は新しいフィルターされたリストが欲しい->これは値=> "lmn"を持つだろう。すなわち、要素がlist2にあるlist1に存在しない値。

12
Arun Khot

最終的に私はこの次の方法を達成する方法を得ました-

List<String> unavailable = list1.stream()
                .filter(e -> (list2.stream()
                        .filter(d -> d.getStr().equals(e))
                        .count())<1)
                        .collect(Collectors.toList());

しかし、これも期待どおりに機能しています。これがどれだけ効果的か教えてください。そして、誰かが同じことをする別の方法がある場合はどうなりますか?

5
Arun Khot
// produce the filter set by streaming the items from list 2
// assume list2 has elements of type MyClass where getStr gets the
// string that might appear in list1
Set<String> unavailableItems = list2.stream()
    .map(MyClass::getStr)
    .collect(Collectors.toSet());

// stream the list and use the set to filter it
List<String> unavailable = list1.stream()
            .filter(e -> unavailableItems.contains(e))
            .collect(Collectors.toList());
18
Ashley Frieze

ストリームでそれを行うことは簡単で読みやすいです:

Predicate<String> notIn2 = s -> ! list2.stream().anyMatch(mc -> s.equals(mc.str));
List<String> list3 = list1.stream().filter(notIn2).collect(Collectors.toList());
7
DSchmidt

最初のリストをストリーミングし、2番目のリストに含まれるに基づいてフィルターを使用する場合...

list1.stream()
    .filter(item -> !list2.contains(item))

次の質問は、結果をさらに処理するためにこのストリーミング操作の最後にどのコードを追加するかです...

また、list.containsは非常に遅いため、セットを使用する方が適切です。

ただし、セットを使用している場合は、removeAllなど、これを処理する簡単な操作が見つかる場合があります。

Set list1 = ...;
Set list2 = ...;
Set target = new Set();
target.addAll(list1);
target.removeAll(list2);

これをどのように使用するのかわからないので、どのアプローチをとるかをアドバイスすることは実際には不可能です。

4
Ashley Frieze

下記を参照してください。以下のコードに関するフィードバックを歓迎します。

2つの配列間では一般的ではありません。

List<String> l3 =list1.stream().filter(x -> !list2.contains(x)).collect(Collectors.toList());

2つの配列に共通:

List<String> l3 =list1.stream().filter(x -> list2.contains(x)).collect(Collectors.toList());
2
tosi

単純なアプローチは、list1のforeachで、list3に追加されていない場合、アイテムがlist2にあるかどうかを確認します。

outer:
for(String s : list1) {
    for(MyClass c : list2) 
        if(c.getStr().equals(s))
            continue outer;
    filteredList.add(c);
}

混乱を招くラベルが続く場合は、ブール値を返す関数で内部ループを抽出します。ラムダストリームイテレータの古典的なforeachを置き換えることもできます。

public static boolean isInList(ArrayList<MyClass> list, String s) {
    list2.stream().foreach((o)-> {
        if(o.getStr().equals(s)) {
            return true;
        }
    });
    return false;
}

list1.stream().foreach((s) -> {
    if(!isInList(list2, s)) {
        list3.add(s);
    }
});

しかし、それは本当にもっとジャンキー/汚染されており、私の目には不要です。

また、String strはクラスのパブリック定義を持たないため、クラスがJava Beanモデルに従い、getStr( ) 方法。

2
Felype
list1 = list1.stream().filter(str1-> 
        list2.stream().map(x->x.getStr()).collect(Collectors.toSet())
        .contains(str1)).collect(Collectors.toList());

これはより効率的に機能する場合があります。

1
YiFu.Zhou

iDを持つクラスがあり、IDでフィルタリングする場合

line1:すべてのIDをマッピングします

line2:マップに存在しないものをフィルタリングします

Set<String> mapId = entityResponse.getEntities().stream().map(Entity::getId).collect(Collectors.toSet());

List<String> entityNotExist = entityValues.stream().filter(n -> !mapId.contains(n.getId())).map(DTOEntity::getId).collect(Collectors.toList());
0
Ran Adler

@DSchmditの答えは私のために働いた。付け加えたいと思います。したがって、私の要件は、テーブルに保存されているいくつかの構成に基づいてファイルをフィルター処理することでした。ファイルは最初に取得され、dtoのリストとして収集されます。 dbから構成を受け取り、別のリストとして保存します。これは、ストリームでフィルタリングを機能させる方法です

    List<FPRSDeferralModel> modelList = Files
            .lines(Paths.get("src/main/resources/rootFiles/XXXXX.txt")).parallel().parallel()
            .map(line -> {
                FileModel fileModel= new FileModel();
                line = line.trim();
                if (line != null && !line.isEmpty()) {
                    System.out.println("line" + line);
                    fileModel.setPlanId(Long.parseLong(line.substring(0, 5)));
                    fileModel.setDivisionList(line.substring(15, 30));
                    fileModel.setRegionList(line.substring(31, 50));
                    Map<String, String> newMap = new HashedMap<>();
                    newMap.put("other", line.substring(51, 80));
                    fileModel.setOtherDetailsMap(newMap);

                }
                return fileModel;
            }).collect(Collectors.toList());

    for (FileModel model : modelList) {
        System.out.println("model:" + model);
    }

    DbConfigModelList respList = populate();
    System.out.println("after populate");
    List<DbConfig> respModelList = respList.getFeedbackResponseList();


    Predicate<FileModel> somePre = s -> respModelList.stream().anyMatch(respitem -> {

        System.out.println("sinde respitem:"+respitem.getPrimaryConfig().getPlanId());
        System.out.println("s.getPlanid()"+s.getPlanId());
        System.out.println("s.getPlanId() == respitem.getPrimaryConfig().getPlanId():"+
        (s.getPlanId().compareTo(respitem.getPrimaryConfig().getPlanId())));
        return s.getPlanId().compareTo(respitem.getPrimaryConfig().getPlanId()) == 0
                && (s.getSsnId() != null);
    });



 final List<FileModel> finalList =  modelList.stream().parallel().filter(somePre).collect(Collectors.toList());

 finalList.stream().forEach(item -> {
     System.out.println("filtered item is:"+item);
 });

詳細は、フィルター述語の実装にあります。これは、ループを繰り返し処理してフィルター処理するよりもはるかに性能が高いことを証明しています

0
Joey587
`List<String> unavailable = list1.stream()
                .filter(e -> (list2.stream()
                        .filter(d -> d.getStr().equals(e))
                        .count())<1)
                        .collect(Collectors.toList());`
for this if i change to 
`List<String> unavailable = list1.stream()
                .filter(e -> (list2.stream()
                        .filter(d -> d.getStr().equals(e))
                        .count())>0)
                        .collect(Collectors.toList());`
will it give me list1 matched with list2 right? 
0
Vignesh