Java 8 流 - 通过比较两个列表进行过滤

我有 2 个彼此不同的列表


public class App1{

    private String name;

    private String city;


    // getter setter


    // constructors

}


public class App2{

    private String differentName;

    private String differentCity;

    private String someProperty1;

    private String someProperty2;


    // getter setter


    // constructors

}


List<App1> app1List = new ArrayList<>();

app1List.add(new App1("test1","city1"));

app1List.add(new App1("test2","city2"));

app1List.add(new App1("test3","city3"));

app1List.add(new App1("test4","city4"));


List<App2> app2List = new ArrayList<>();

app2List.add(new App2("test2","city2"));

app2List.add(new App2("test3","city3"));

如您所见,App1 和 App2 类是 2 个具有不同属性名称的不同 pojo,但是 name、city 和 differentName、 differentCity 属性分别持有的内容/值是相同的,即 test1、test2、test3 和 city1、city2 等


现在我需要过滤 app1List 比较其他列表中的名称和城市,即不存在的 app2List。


最终输出将是


app1List.add(new App1("test1","city1"));

app1List.add(new App1("test4","city4"));

最简单的方法是多次循环其他列表之一,这是我试图避免的。Java 8 流中有什么方法不必循环多次?


摇曳的蔷薇
浏览 116回答 3
3回答

慕婉清6462132

您可以使用noneMatch操作,例如:List<App1> result = app1List.stream()&nbsp; &nbsp; &nbsp; &nbsp; .filter(app1 -> app2List.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .noneMatch(app2 -> app2.getDifferentCity().equals(app1.getCity()) &&&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; app2.getDifferentName().equals(app1.getName())))&nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());这假设两者的组合name并且在 ingcity时匹配filter。

跃然一笑

您需要override equals在类中使用方法App2:public class App2{&nbsp; &nbsp; private String differentName;&nbsp; &nbsp; private String differentCity;&nbsp; &nbsp; private String someProperty1;&nbsp; &nbsp; private String someProperty2;&nbsp; &nbsp; // getter setter&nbsp; &nbsp; // constructors&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean equals(Object obj) {&nbsp; &nbsp; &nbsp; &nbsp;App2 app2 = (App2) obj;&nbsp; &nbsp; &nbsp; &nbsp;return this.differentName.equals(app2.getDifferentName()) && this.differentCity.equals(app2.getDifferentCity());&nbsp; &nbsp; }}然后您可以像这样在 list1 上使用 Streams:app1List = app1List.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(a-> !app2List.contains(new App2(a.getName(),a.getCity())))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());输出:[App1{name='test1', city='city1'}, App1{name='test4', city='city4'}]

吃鸡游戏

假设您想要匹配名称和城市,您可以创建一个将对象映射到key的函数,例如:public static Integer key(String name, String differentCity) {&nbsp; &nbsp; return Objects.hash(name, differentCity);}然后使用该键创建一组键,以便使用noneMatch进行过滤,例如:Set<Integer> sieve = app2List.stream()&nbsp; &nbsp; &nbsp; &nbsp; .map(app2 -> key(app2.differentName, app2.differentCity)).collect(Collectors.toSet());List<App1> result = app1List.stream().filter(app1 -> sieve.stream()&nbsp; &nbsp; &nbsp; &nbsp; .noneMatch(i -> i.equals(key(app1.name, app1.city))))&nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());System.out.println(result);输出[App1{name='test1', city='city1'}, App1{name='test4', city='city4'}]这种方法的复杂性在于O(n + m)其中n和m是列表的长度。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java