我正在尝试提出使用流解决此问题的解决方案,并且我查找是否有人遇到了此问题但找不到此问题。 因此,我有一个包含三个元素的列表,将其命名为list1,另一个列表称为list2,它可以具有不同的元素,并且还可以包含list1中的重复项。
我想实现的目标:-
对于2-我可以使用set,将list2转换为set,然后查看list1是否包含所有set。
但是我想知道我是否可以在这里使用流!
例如
list1(1,2,3)和list2(1,1,2,2)-返回true
list1(1,2,3)和list2(1,1,3,3)-返回true
list1(1,2,3)和list2(1,1,2,2,4)-返回false
我希望这不太清楚
答案 0 :(得分:2)
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;
}
但是建议您不要将流用于如此复杂的逻辑。
答案 1 :(得分:1)
流可能不是解决此问题的最有效方法。但是,这是另一种方法,一旦发现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;
}
尽管如此,我们还是要“作弊”:为了不经历完整的流程,我们必须借助计数器来限制元素。
检查&& count.get() == 2
确保list1
中包含2个元素。如果0或1元素也可以接受,请删除该检查。
答案 2 :(得分:0)
怎么样:
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();
不幸的是,您实际上执行了两次相同的流操作。或者,为避免这种情况,请收集流并重新转换:
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();
您实际上是在创建两个带有可选轨道的轨道:一个与您的需求匹配的轨道,另一个与您的需求不匹配。每当您发现不匹配的内容时,就会使用过滤器将其丢弃。 isPresent
仍在管道中的所有内容都符合您的条件。