我有一个有序的字符串列表,比如说“aaa”,“aaa”,“aaa”,“bbb”,“bbb”,“aaa”
。我想将相邻的相等字符串分组在一起并对它们进行计数,因此操作的结果应该是一个 List
,如下所示: {"aaa":3}, {"bbb": 2},{“aaa”,1}
。请注意,任务不仅仅是按相同的值进行分组并对它们进行计数(否则我可以简单地将 groupingBy
与 counting
一起使用),而是仅按具有相同值的相邻字符串进行分组值,如果相同的字符串稍后出现在列表中,则应将其视为单独的。基本上,我需要这段代码来从现有数据结构中创建一个具有适当列跨度的表头。
我想知道是否有一种相当好的方法可以使用 Java 8 流来完成此任务。我知道如何使用老式循环来做到这一点,只是认为流可能提供了更好的方法。
最佳答案
据我所知,您可以创建一个自定义收集器,但它与循环没有太大区别(将应用相同的逻辑)。另请注意,我使用 SimpleEntry
而不是 Pair
来保存列表中的每个元素。
private static Collector<String, ?, List<AbstractMap.SimpleEntry<String, Integer>>> adiacentCollector() {
class Acc {
private String previous;
private List<AbstractMap.SimpleEntry<String, Integer>> result = new ArrayList<>();
void accumulate(String elem) {
if (previous == null) {
previous = elem;
result.add(new AbstractMap.SimpleEntry<String, Integer>(elem, 1));
return;
}
if (previous.equals(elem)) {
SimpleEntry<String, Integer> current = result.get(result.size() - 1);
current.setValue(current.getValue() + 1);
previous = elem;
} else {
SimpleEntry<String, Integer> oneMore = new SimpleEntry<String, Integer>(elem, 1);
result.add(oneMore);
previous = elem;
}
}
Acc combine(Acc other) {
SimpleEntry<String, Integer> lastEntry = result.get(result.size() - 1);
SimpleEntry<String, Integer> firstEntry = other.result.get(0);
if (lastEntry.getKey().equals(firstEntry.getKey())) {
lastEntry.setValue(lastEntry.getValue() + firstEntry.getValue());
other.result.remove(0);
}
result.addAll(other.result);
return this;
}
List<AbstractMap.SimpleEntry<String, Integer>> finisher() {
return result;
}
}
return Collector.of(Acc::new, Acc::accumulate, Acc::combine, Acc::finisher);
}
并使用它:
System.out.println(Stream.of("aaa", "aaa", "aaa", "bbb", "bbb", "aaa")
.collect(adiacentCollector()));
关于java - 是否可以使用流将字符串分组并在有序的 Java 列表中对组成员进行计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45998611/