我有两份清单<代码>列表1包含一些城市。
列表2包含子列表。每个子列表包含一个人已经访问过的国家(一个子列表=一个人访问过的国家)。在这个例子中,Person1去了罗马、阿姆斯特丹和维也纳,Person2去了阿姆斯特丹、巴塞罗那和米兰。。。
我想知道有多少人已经去过第一个名单上的国家。不应重复计算。因此,如果人员1已经从列表1前往两个国家,则只应计算一次。
我想用JavaStreams实现这个。有人知道我怎么做吗?
list1 = ["Barcelona", "Milan", "Athens"];
list2 = [["Rom", "Amsterdam", "Vienna"], ["Amsterdam", "Barcelona", "Milan"], ["Prais", "Athens"], ["Istanbul", "Barcelona", "Milan", "Athens"]];
//The expected result for this example is: 3
//Both lists already result from a stream (Collectors.toList())
谢谢!
您可以尝试以下操作:
private static final List<String> CITIES = List.of("Barcelona", "Milan", "Athens");
private static final List<List<String>> VISITED_CITIES = List.of(
List.of("Rome", "Amsterdam", "Vienna"),
List.of("Amsterdam", "Barcelona", "Milan"),
List.of("Paris", "Athens"),
List.of("Instabul", "Barcelon", "Milan", "Athens")
);
public static void main(String... args) {
var count = VISITED_CITIES
.stream()
.flatMap(visited -> visited.stream().filter(CITIES::contains))
.distinct()
.count();
System.out.println(count);
}
通过此迭代,您将得到预期的结果3。但是,您可以修改代码,也可以将其收集到一个将显示频率的映射中(如果删除“distinct”中间步骤),如下所示:
var count = VISITED_CITIES
.stream()
.flatMap(visited -> visited.stream().filter(CITIES::contains))
.collect(Collectors.groupingBy(Function.identity()));
请看一下mapToInt()和sum()函数。
List<String> list1 = List.of("Barcelona", "Milan", "Athens");
List<List<String>> list2 = List.of(List.of("Rom", "Amsterdam", "Vienna"),
List.of("Amsterdam", "Barcelona", "Milan"),
List.of("Prais", "Athens"),
List.of("Istanbul", "Barcelona", "Milan", "Athens"));
int result = list2.stream().mapToInt(person -> person.stream().anyMatch(list1::contains) ? 1 : 0).sum();
我在这里要做的是创建一个所有人的流,然后根据列表1中是否包含他们访问过的国家,将每个人映射到1或0。
这与以下for循环示例相同:
int result = 0;
for (List<String> person : list2)
{
int i = 0;
for (String visited : person)
{
if (list1.contains(visited))
{
i = 1;
break;
}
}
result += i;
}