我正在尝试使用 Stream 对列表中的项目进行分组。
public static void main(String[] args) {
List<String> l = Arrays.asList("A", "C", "B", "A", "B");
Map<String, List<String>> b = l.stream().collect(Collectors.groupingBy(Function.identity()));
System.out.println(b.toString());
}
这将返回
{A=[A, A], B=[B, B], C=[C]}
。
但是,我怎样才能获得每个元素的索引。 类似这样的,
{A=[(A,0), (A,3)], B=[(B,2), (B,4)], C=[(C,1)]}
您可以将
groupingBy
与 List::get(int index)
一起使用,如下所示:
Map<String, List<Integer>> result = IntStream.range(0, l.size())
.boxed()
.collect(Collectors.groupingBy(l::get));
输出
{A=[0, 3], B=[2, 4], C=[1]}
如您所见,响应与您的预期略有不同。我认为显示
(B,2)
是多余的。
编辑
由于OP坚持显示相同的输出,我建议创建一个包含字母和索引的自定义对象,如下所示:
@AllArgsConstructor
class MyOutput{
private String letter;
private Integer index;
@Override
public String toString() {
return "(" + letter + "," + index + ')';
}
}
您的信息流应如下所示:
Map<String, List<MyOutput>> response = IntStream.range(0, l.size())
.boxed()
.collect(groupingBy(l::get, mapping(i -> new MyOutput(l.get(i), i), toList())));
输出
{A=[(A,0), (A,3)], B=[(B,2), (B,4)], C=[(C,1)]}
这是如何做你想做的事。
record Pair(String letter, int index) {
@Override
public String toString() {
return "(%s, %d)".formatted(letter, index);
}
}
List<String> l = Arrays.asList("A", "C", "B", "A", "B");
Map<String, List<Pair>> result = IntStream.range(0, l.size())
.mapToObj(i -> new Pair(l.get(i), i))
.collect(Collectors.groupingBy(Pair::letter));
result.entrySet().forEach(System.out::println);
打印
A=[(A, 0), (A, 3)]
B=[(B, 2), (B, 4)]
C=[(C, 1)]