【问题标题】:AND/OR operations on lists in JavaJava中列表的AND/OR操作
【发布时间】:2015-03-27 09:43:00
【问题描述】:

让我们考虑两个数组列表。

ArrayList<Integer> list1 = new ArrayList<Integer>();
list1.add(1);
list1.add(2);
list1.add(3);

ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(3);
list2.add(4);
list2.add(5);

我想在这些列表之间执行 AND 和 OR 操作。 例如, 在这里,当我执行 AND 操作时 b/w list1 & list2 输出应该是一个仅包含 3 的列表 当我执行或操作 b/w list1 & list2 输出应该是一个包含 1,2,3,4,5 的列表(不是 3 重复两次)。

在 Java 中是否有可能实现这种情况?在这种情况下我们可以使用 Java 8 Streams 吗? 请给我最有效的方法来得到答案。

【问题讨论】:

  • 你的意思是一个设置交集和一个设置联合。尝试使用集合。
  • @khelwood 他要名单
  • @pivovarit 这并不意味着使用集合不能解决他的问题。

标签: java list java-8


【解决方案1】:

使用 Stream API:

List<Integer> union = Stream.concat(list1.stream(), list2.stream())
                            .distinct()
                            .collect(Collectors.toList());

List<Integer> intersection = list1.stream()
                                  .filter(list2::contains)
                                  .collect(Collectors.toList());

没有 Stream API:

List<Integer> intersection = new ArrayList<>(list1);
intersection.retainAll(list2);

List<Integer> union = new ArrayList<>(list1);
List<Integer> toAdd = new ArrayList<>(list2);
toAdd.removeAll(list1);  // avoid duplicates
union.addAll(toAdd);

【讨论】:

    【解决方案2】:

    您需要使用Sets 以避免重复。那么这只是使用addAll()removeAll()retainAll()操作的问题。

    【讨论】:

    • @DeepakShajan "Give me the code" 我想你不知道 SO 是如何工作的......试着自己思考一下,这个答案已经给了你解决方案。
    • @AlexisC.:我想知道他是怎么解决这个问题的,只能通过代码来理解。
    • @DeepakShajan 是什么阻止您编写此代码?他已经给了你所有你应该使用的方法。稍加反思和努力(阅读ex.的文档),你就可以毫无问题地做到这一点。您应该有一定程度的抽象,而不是询问解决问题的“特定”代码。
    【解决方案3】:

    如果您真的坚持使用 Streams,您可以这样做:

    对于AND,你可以这样做:

    List<Integer> AND = list1.stream()
                             .filter(list2:contains)
                             .collect(Collectors.toList());
    

    对于OR,你可以这样做:

    List<Integer> OR =  Arrays.asList(list1, list2)
                             .stream()
                             .flatMap(List::stream)
                             .distinct()
                             .collect(Collectors.toList());   
    

    甚至更好,正如@Alexis C. 所建议并受到@aioobe 启发:

    List<Integer> OR = Stream.concat(list1.stream(), list2.stream())
                             .distinct()
                             .collect(Collectors.toList());
    

    【讨论】:

    • 我可以将它添加到答案中吗? :)
    • [...] 输出应该是 一个列表 包含 1,2,3,4,5(不是 3 重复两次)[...]
    • @aioobe,AND 是一个列表。它只包含3。 :)
    • @aioobe 你可以随时使用.collect(collectingAndThen(toSet(), ArrayList::new))...如果你真的需要一份清单。或distinct() 后跟toList()(更好的国际海事组织)...
    • @Alexis C.: collectingAndThen(toSet(), ArrayList::new) 不维护订单。你可以改用collectingAndThen(toCollection(LinkedHashSet::new), ArrayList::new)
    【解决方案4】:

    可能有用:

    Set<Integer> orSet = new HashSet<Integer>();
        orSet.addAll(list);
        orSet.addAll(list1);
        List<Integer> orList = new ArrayList<Integer>(orSet);
        List<Integer> andList = new ArrayList<Integer>();
        int i=0;
        Iterator<Integer> itr = list.iterator();
        while(itr.hasNext()){
            int v = itr.next();
            if(list1.contains(v)){
                andList.add(v);
            }
        }
    
        System.out.println(orList);
        System.out.println(andList);
    

    【讨论】:

    • 不需要手动使用Iterator(从Java 5开始),只需使用for(Integer v: list) …进行迭代。此外,您不需要重复集合的类型:Set&lt;Integer&gt; orSet = new HashSet&lt;&gt;();List&lt;Integer&gt; orList = new ArrayList&lt;&gt;(orSet); 等(从 Java 7 开始)。在回答特定于 Java 8 的问题时,您应该考虑这一点。请注意HashSet 没有排序保证,可能不适合List 合并,请改用LinkedHashSet...
    猜你喜欢
    • 2015-02-26
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    相关资源
    最近更新 更多