哪个Java Collection类更适合对象列表进行分组?
我有来自以下用户的消息列表:
aaa hi
bbb hello
ccc Gm
aaa Can?
CCC yes
ddd No
从我想要计算的消息对象列表中显示aaa(2)+bbb(1)+ccc(2)+ddd(1)
。任何代码帮助?
答案 0 :(得分:4)
您可以使用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);
}
}
然后你可以在完成时迭代地图:
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())
答案 1 :(得分:1)
你需要番石榴MultiSet。该集合类型是为此类任务量身定制的:
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() + ")");
}
答案 2 :(得分:1)
假设你使用Java 8,它可能是这样的,使用Stream API:
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()
)
);
答案 3 :(得分:1)
从其他几个答案中将各个部分放在一起,从另一个问题调整代码并修复一些琐碎的错误:
// 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)