简体   繁体   English

使用流检查Java中列表是否仅具有特定元素排列

[英]Using stream to check if list has only specific elements permutations in Java

I am trying to come up a solution using streams to solve this problem and I looked up if someone has came across this but couldn't find this. 我试图提出一种使用流来解决此问题的解决方案,并且我查找是否有人遇到了此问题但找不到此问题。 So I have a list of three elements, let call it list1 and another list say list2 which can have different elements and can also contain duplicate items from list1. 因此,我有一个包含三个元素的列表,将其命名为list1,另一个列表称为list2,它可以具有不同的元素,并且还可以包含list1中的重复项。

What I want to achieve :- 我想实现的目标:

  1. Check if the list2 has any element which isn't in list1. 检查list2是否具有list1中没有的任何元素。
  2. Check if list2 has only 2 item from list1 at a time. 检查list2一次是否只有2个项目。

For 2 - I could use set, convert list2 to set and see if list1 containsAll the set. 对于2-我可以使用set,将list2转换为set,然后查看list1是否包含所有set。

But I wanted to know if I can use stream here! 但是我想知道是否可以在这里使用流!

Eg 例如

list1 (1,2,3) and list2 (1,1,2,2) - returns true list1(1,2,3)和list2(1,1,2,2)-返回true

list1 (1,2,3) and list2 (1,1,3,3) - returns true list1(1,2,3)和list2(1,1,3,3)-返回true

list1 (1,2,3) and list2 (1,1,2,2,4) -return false list1(1,2,3)和list2(1,1,2,2,4)-返回false

I hope this makes it little clear 我希望这一点不太清楚

  public static <T> boolean func(List<T> list1, List<T> list2) {
    return list2.stream()
        .distinct()
        .map(list1::contains)
        .reduce(0,
            (result, current) -> result < 0 ? -1 : (current ? result + 1 : -1),
            (a, b) -> a < 0 || b < 0 ? -1 : a + b) == 2;
  }

But suggest you don't use stream for such complex logic. 但是建议您不要将流用于如此复杂的逻辑。

Streams are probably not the most efficient way to tackle this problem. 流可能不是解决此问题的最有效方法。 Nonetheless, here is another approach that has the advantage of short-circuting as soon as we find the third element contained or the first element not contained in list1 : 但是,这是另一种方法,它具有一旦发现list1包含的第三个元素或第一个元素不包含的第一个元素,便可以进行短循环的优点:

public static <T> boolean func(List<T> list1, List<T> list2)
{
    AtomicLong count = new AtomicLong(0);
    return list2.stream()
                .distinct()
                .allMatch(element -> list1.contains(element) &&
                                     count.incrementAndGet() < 3)
           && count.get() == 2;
}

We have to "cheat" a bit, though: In order to not go through the complete stream, we have to limit the elements with the help of a counter. 但是,我们必须“作弊”:为了不进行完整的处理,我们必须借助计数器来限制元素。

The check && count.get() == 2 makes sure that you have exactly 2 elements that are contained in list1 . check && count.get() == 2确保list1中包含2个元素。 If 0 or 1 element are also acceptable, remove that check. 如果0或1元素也是可接受的,则删除该检查。

How about: 怎么样:

return Optional.of(list2)
        .filter(list -> list.stream().allMatch(list1::contains))
        .map(list -> list.stream().distinct().map(list1::contains))
        .map(stream -> stream.mapToInt(x -> x ? 1 : 0))
        .map(IntStream::sum)
        .filter(sum -> sum == 2)
        .isPresent();

Unfortunately, you're essentially performing the same stream operation twice. 不幸的是,您实际上要执行两次相同的流操作。 Alternatively, to avoid this, collect the stream and reconvert it: 或者,为避免这种情况,请收集流并对其进行转换:

List<Boolean> containedInFirst = list2.stream()
        .distinct()
        .map(list1::contains)
        .collect(Collectors.toList());
return Optional.of(containedInFirst)
        .filter(list -> list.stream().allMatch(x -> x))
        .map(list -> list.stream().mapToInt(x -> x ? 1 :0))
        .map(IntStream::sum)
        .map(sum -> sum == 2)
        .filter(sum -> sum == 2)
        .isPresent();

You're essentially creating two tracks with the optional: the one which matches your requirements and those that don't. 本质上,您正在创建带有可选轨道的两个轨道:一个与您的需求匹配的轨道,另一个与您的需求不匹配。 Any time you find something that doesn't match up, you throw it out with a filter. 每当您发现不匹配的内容时,就会使用过滤器将其丢弃。 Anything that is still in the pipeline by the isPresent matches your criteria. isPresent仍在管道中的任何内容都符合您的条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM