哪个Java集合类更适合对对象列表进行分组?
我有一个用户消息列表,如下所示:
aaa hi
bbb hello
ccc Gm
aaa Can?
CCC yes
ddd No
我想从这个消息对象列表中计算并显示 aaa(2)+bbb(1)+ccc(2)+ddd(1)
。有任何的代码帮助吗?
哪个Java集合类更适合对对象列表进行分组?
我有一个用户消息列表,如下所示:
aaa hi
bbb hello
ccc Gm
aaa Can?
CCC yes
ddd No
我想从这个消息对象列表中计算并显示 aaa(2)+bbb(1)+ccc(2)+ddd(1)
。有任何的代码帮助吗?
Map<String, Integer>
来表示字符串的集合,其中键表示每个单独的字符串,而映射值为每个字符串的计数器。
例如,您可以这样做:// where ever your input comes from: turn it into lower case,
// so that "ccc" and "CCC" go for the same counter
String item = userinput.toLowerCase();
// as you want a sorted list of keys, you should use a TreeMap
Map<String, Integer> stringsWithCount = new TreeMap<>();
for (String item : str) {
if (stringsWithCount.contains(item)) {
stringsWithCount.put(item, stringsWithCount.get(item)+1));
} else {
stringsWithCount.put(item, 0);
}
}
然后在完成操作后,您可以迭代Map:
for (Entry<String, Integer> entry : stringsWithCount.entrySet()) {
并构建您的结果字符串。
那就像老式实现一样;如果你想要花哨并惊喜你的老师,你可以选择Java8/lambda/stream解决方案。 (我不建议除非你真的投入时间完全理解以下解决方案;因为这是未经我的测试的)
Arrays.stream(someListOrArrayContainingItems)
.collect(Collectors
.groupingBy(s -> s, TreeMap::new, Collectors.counting()))
.entrySet()
.stream()
.flatMap(e -> Stream.of(e.getKey(), String.valueOf(e.getValue())))
.collect(Collectors.joining())
MultiSet<String> multiSet = new MultiSet<>();
for (String line : lines) { // somehow you read the lines
multiSet.add(line.split(" ")[0].toLowerCase());
}
boolean first = true;
for (Multiset.Entry<String> entry : multiset.entrySet()) {
if (!first) {
System.out.println("+");
}
first = false;
System.out.print(entry.getElement() + "(" + entry.getCount() + ")");
}
List<Message> messages = ...;
// Convert your list as a Stream
// Extract only the login from the Message Object
// Lowercase the login to be able to group ccc and CCC together
// Group by login using TreeMap::new as supplier to sort the result alphabetically
// Convert each entry into login(count)
// Join with a +
String result =
messages.stream()
.map(Message::getLogin)
.map(String::toLowerCase)
.collect(
Collectors.groupingBy(
Function.identity(), TreeMap::new, Collectors.counting()
)
)
.entrySet()
.stream()
.map(entry -> entry.getKey() + '(' + entry.getValue() + ')')
.collect(Collectors.joining("+"))
System.out.println(result);
输出:
aaa(2)+bbb(1)+ccc(2)+ddd(1)
Map<String, List<Message>> groupedMessages =
messages.stream()
.collect(
Collectors.groupingBy(
message -> message.getLogin().toLowerCase(),
TreeMap::new,
Collectors.toList()
)
);
// as you want a sorted list of keys, you should use a TreeMap
Map<String, Integer> stringsWithCount = new TreeMap<>();
for (Message msg : convinfo.messages) {
// where ever your input comes from: turn it into lower case,
// so that "ccc" and "CCC" go for the same counter
String item = msg.userName.toLowerCase();
if (stringsWithCount.containsKey(item)) {
stringsWithCount.put(item, stringsWithCount.get(item) + 1);
} else {
stringsWithCount.put(item, 1);
}
}
String result = stringsWithCount
.entrySet()
.stream()
.map(entry -> entry.getKey() + '(' + entry.getValue() + ')')
.collect(Collectors.joining("+"));
System.out.println(result);
这将打印:
aaa(2)+bbb(1)+ccc(2)+ddd(1)
stringsWithCount
声明了一个 TreeMap
。TreeMap
是 SortedMap
接口的一个实现(这就是为什么 @GhostCar 和 @NicolasFilotto 建议使用它)。在 SortedMap
的 API 文档中,您会发现其中九个方法之一是 lastKey()
。所以 stringsWithCount.lastKey()
将返回 "WVU"
。如果您将其传递到 stringsWithCount.get()
中,则还将获得数量(在本例中为 1)。 - Ole V.V.
HashMap<String, Integer>
来实现类似的功能(假设您将aaa
存储为字符串对象;否则,您需要使用另一种类型作为键,但请确保该类型实现了hashCode()
和equals()
方法)。 - Ole V.V.