使用Java集合对对象列表进行分组和计数
哪个Java集合类更适合对对象列表进行分组 我有一个来自以下用户的消息列表:使用Java集合对对象列表进行分组和计数,java,collections,count,grouping,Java,Collections,Count,Grouping,哪个Java集合类更适合对对象列表进行分组 我有一个来自以下用户的消息列表: aaa hi bbb hello ccc Gm aaa Can? CCC yes ddd No 从这个消息对象列表中,我想计数并显示aaa(2)+bbb(1)+ccc(2)+ddd(1)。任何代码帮助?您可以使用Map,其中键表示单个字符串,Map值是每个字符串的计数器 因此,您可以执行以下操作: // where ever your input comes from: turn it into lower
aaa hi
bbb hello
ccc Gm
aaa Can?
CCC yes
ddd No
从这个消息对象列表中,我想计数并显示aaa(2)+bbb(1)+ccc(2)+ddd(1)
。任何代码帮助?您可以使用Map
,其中键表示单个字符串,Map值是每个字符串的计数器
因此,您可以执行以下操作:
// 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);
}
}
你需要番石榴汁。该集合类型是为此类任务量身定制的:
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() + ")");
}
MultiSet MultiSet=new MultiSet();
对于(stringline:lines){//您以某种方式阅读了这些行
multiSet.add(line.split(“”[0].toLowerCase());
}
布尔值优先=真;
for(Multiset.Entry:Multiset.entrySet()){
如果(!第一个){
System.out.println(“+”);
}
第一个=假;
System.out.print(entry.getElement()+“(“+entry.getCount()+”));
}
假设您使用Java 8,那么使用流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);
如果您想按登录名对邮件进行分组,并将结果作为一个集合,则可以执行下一步:
Map<String, List<Message>> groupedMessages =
messages.stream()
.collect(
Collectors.groupingBy(
message -> message.getLogin().toLowerCase(),
TreeMap::new,
Collectors.toList()
)
);
映射分组消息=
messages.stream()
.收集(
收集者分组(
message->message.getLogin().toLowerCase(),
树映射::新的,
收集者
)
);
将其他两个答案中的部分组合在一起,根据其他问题中的代码进行调整,并修复一些小错误:
// 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);
HashMap
以前曾多次用于类似目的(假设您将aaa
存储为字符串对象;否则您将希望使用字符串以外的其他类型作为键,只需确保该类型实现了hashCode()
和equals()
)。您好,谢谢您的回答,但没有解决我的问题。。。我有一个类似Hashset messages=newhashset()的列表;消息包含如上所述的用户nd消息列列表。所以我必须提取和显示用户的计数。您必须向我们展示一些代码,这将是描述您的设计的最精确的方式。最好为我们制作i。代码在这个链接中,那里有很多代码……提示:您应该更明确地说明,您的解决方案需要使用第三方库。我还想知道multiset是否会将“ccc”视为“ccc”——正如他在示例输入中给出的那样。也许他可以;但是这个问题不需要求助于第三方库就可以解决。很抱歉风格不一致。根据您的喜好和Java版本,您可以使用循环或流来完成所有操作。。。。但是我不能用流(Java7/8)特性来实现它。。。不知道为什么在eclipse中仍然会出现错误。。所以我用了老办法,像地图输入和遍历它的工作!如何从中得出最后的结果?呃,我相信这是个很难回答的问题。幸运的是,它非常简单,您可能很容易找到自己:stringsWithCount
被声明为一个TreeMap
TreeMap
是SortedMap
接口的实现(这就是@GhostCar和@NicolasFilotto建议的原因)。在SortedMap
的API文档中,您注意到九种方法之一是lastKey()
。因此stringsWithCount.lastKey()
将返回“WVU”
。如果您将其传递到stringsWithCount.get()
,您也将获得计数(即,在本例中为1)。我尝试了stringWithCount.lastKey()打印我,就像G_LO G_LO WVU WVU WVU WVU WVU WVU WVU WVU WVU
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)