在java中对字符串集合中的数据进行分组
我有一组字符串和一些数据。例如:在java中对字符串集合中的数据进行分组,java,string,collections,Java,String,Collections,我有一组字符串和一些数据。例如: List<String> list = new ArrayList<>(); list.add("10/10/2012 [user2] some message1"); list.add("10/10/2012 [user1] some message2"); list.add("10/10/2012 [qwwww] some message3"); list.add("11/10/2012 [user3] some message4")
List<String> list = new ArrayList<>();
list.add("10/10/2012 [user2] some message1");
list.add("10/10/2012 [user1] some message2");
list.add("10/10/2012 [qwwww] some message3");
list.add("11/10/2012 [user3] some message4");
list.add("11/10/2012 [user3] some message5");
list.add("12/10/2012 [user2] some message6");
list.add("12/10/2012 [user3] some message7");
list.add("12/10/2012 [user2] some message8");
list.add("12/10/2012 [sdsds] some message9");
list.add("12/10/2012 [user2] some message10");
用户
对象
或者进行某种排序,使其具有名称
、日期
和消息
属性,然后您的列表将成为列表
User
对象进行分组,您可以使用Streams API,尤其是对groupingBy
方法感兴趣李>
您可以在站点中找到许多关于如何根据给定属性对元素进行分组的示例,如下所示:
完成上面的步骤1后,这是一个如何按
名称
属性分组的快速示例,它同样可以轻松地扩展到按其他属性分组:
Map<String, Long> resultSet = userList.stream().collect(
Collectors.groupingBy(User::getName, Collectors.counting()));
System.out.println(resultSet);
Map resultSet=userList.stream().collect(
Collectors.groupingBy(User::getName,Collectors.counting());
系统输出打印项次(结果集);
以下输出:{user1=1,qwww=1,user2=4,sdsds=1,user3=3}
public class Main {
final static Pattern pattern = Pattern.compile("\\[(.*)\\]");
public static Optional<String> parseValue(String raw) {
Matcher m = pattern.matcher(raw);
if (m.find()) {
return Optional.of(m.group(1));
} else {
return Optional.empty();
}
}
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("10/10/2012 [user2] some message1");
list.add("10/10/2012 [user1] some message2");
list.add("10/10/2012 [qwwww] some message3");
list.add("11/10/2012 [user3] some message4");
list.add("11/10/2012 [user3] some message5");
list.add("12/10/2012 [user2] some message6");
list.add("12/10/2012 [user3] some message7");
list.add("12/10/2012 [user2] some message8");
list.add("12/10/2012 [sdsds] some message9");
list.add("12/10/2012 [user2] some message10");
Map<String, Long> counts = list.stream().map(s -> parseValue(s).orElse("missing")).collect(Collectors.groupingBy(
Function.identity(), Collectors.counting()
));
System.out.println(counts);
}
}
公共类主{
最终静态模式=Pattern.compile(“\\[(.*)\\]”);
公共静态可选值(字符串原始){
匹配器m=模式匹配器(原始);
if(m.find()){
返回可选的。of(m.group(1));
}否则{
返回可选的.empty();
}
}
公共静态void main(字符串[]args){
列表=新的ArrayList();
列表。添加(“2012年10月10日[user2]一些消息1”);
列表。添加(“2012年10月10日[user1]一些消息2”);
列表。添加(“2012年10月10日[QWW]一些消息3”);
列表。添加(“2012年10月11日[user3]一些消息4”);
列表。添加(“2012年10月11日[user3]一些消息5”);
列表。添加(“2012年10月12日[user2]一些消息6”);
列表。添加(“2012年10月12日[user3]一些消息7”);
列表。添加(“2012年10月12日[user2]一些消息8”);
列表。添加(“2012年10月12日[sdsds]一些消息9”);
列表。添加(“2012年10月12日[user2]一些消息10”);
Map counts=list.stream().Map->parseValue.orElse(“缺失”).collect(Collectors.groupingBy(
Function.identity(),collector.counting()
));
系统输出打印项次(计数);
}
}
正如建议的那样,您可以使用流和正则表达式来高效地对数据进行排序和分组,但是对于较小的数据集,这可能不是最有效的方法
我使用Streams和Matchers与使用简单字符串方法的示例进行了速度比较:
- 流和匹配器:72毫秒
- 简单字符串方法(如下):1毫秒
以下示例使用简单的substr和indexOf方法实现相同的结果:
基于我们讨论的假设
速度比较
删除lambdas使简单测试更快:
public class SpeedComparison
{
private static String extractUser(String aS)
{
int start = aS.indexOf('[') + 1;
int end = aS.indexOf(']');
return aS.substring(start, end);
}
static Map<String, Integer> group(List<String> aList)
{
Map<String, Integer> results = new HashMap<>();
for (String s : aList)
{
String extract = extractUser(s);
int count = results.getOrDefault(extract, 0) + 1;
results.put(extract, count);
}
return results;
}
final static Pattern pattern = Pattern.compile("\\[(.*)\\]");
static Optional<String> parseValue(String raw) {
Matcher m = pattern.matcher(raw);
if (m.find()) {
return Optional.of(m.group(1));
} else {
return Optional.empty();
}
}
public static void main(String[] args)
{
List<String> list = new ArrayList<>();
for (int i = 0; i< 100000 ; ++i)
{
list.add("10/10/2012 [user2] some message1");
list.add("10/10/2012 [user1] some message2");
list.add("10/10/2012 [qwwww] some message3");
list.add("11/10/2012 [user3] some message4");
list.add("11/10/2012 [user3] some message5");
list.add("12/10/2012 [user2] some message6");
list.add("12/10/2012 [user3] some message7");
list.add("12/10/2012 [user2] some message8");
list.add("12/10/2012 [sdsds] some message9");
list.add("12/10/2012 [user2] some message10");
}
//Test basic
final long start1 = System.currentTimeMillis();
group(list);
final long dur1 = System.currentTimeMillis() - start1;
//Test streams
final long start2 = System.currentTimeMillis();
list.stream().map(s -> parseValue(s).orElse("missing")).collect(Collectors.groupingBy(
Function.identity(), Collectors.counting()
));
final long dur2 = System.currentTimeMillis() - start2;
System.out.println("Speed Comparison");
//prints ~100, ~1000 milliseconds (10x slower with streams)
System.out.printf("Test 1: %s%nTest 2: %s",dur1,dur2);
}
}
公共类速度比较
{
私有静态字符串提取器用户(字符串为)
{
int start=aS.indexOf('[')+1;
int end=aS.indexOf(']');
返回为子字符串(开始、结束);
}
静态映射组(列表列表列表)
{
映射结果=新的HashMap();
for(字符串s:aList)
{
字符串提取=提取用户;
int count=results.getOrDefault(extract,0)+1;
结果:put(提取、计数);
}
返回结果;
}
最终静态模式=Pattern.compile(“\\[(.*)\\]”);
静态可选parseValue(字符串原始){
匹配器m=模式匹配器(原始);
if(m.find()){
返回可选的。of(m.group(1));
}否则{
返回可选的.empty();
}
}
公共静态void main(字符串[]args)
{
列表=新的ArrayList();
对于(int i=0;i<100000;++i)
{
列表。添加(“2012年10月10日[user2]一些消息1”);
列表。添加(“2012年10月10日[user1]一些消息2”);
列表。添加(“2012年10月10日[QWW]一些消息3”);
列表。添加(“2012年10月11日[user3]一些消息4”);
列表。添加(“2012年10月11日[user3]一些消息5”);
列表。添加(“2012年10月12日[user2]一些消息6”);
列表。添加(“2012年10月12日[user3]一些消息7”);
列表。添加(“2012年10月12日[user2]一些消息8”);
列表。添加(“2012年10月12日[sdsds]一些消息9”);
列表。添加(“2012年10月12日[user2]一些消息10”);
}
//基本测试
最终长启动t1=System.currentTimeMillis();
小组(名单);
final long dur1=System.currentTimeMillis()-start1;
//测试流
最终长启动t2=System.currentTimeMillis();
list.stream().map->parseValue.orElse(“缺失”).collect(Collectors.groupingBy(
Function.identity(),collector.counting()
));
最终长dur2=System.currentTimeMillis()-start2;
System.out.println(“速度比较”);
//打印约100,~1000毫秒(流速度慢10倍)
System.out.printf(“测试1:%s%n测试2:%s”,dur1,dur2);
}
}
Streams可能在更大的列表上表现更好(stream().parallel()可能利用多线程),但并行性并不总是得到保证
大小问题
在我的机器上,我发现当列表大小超过10000000左右时,使用并行流开始迎头赶上
结论
蒸汽可以非常强大,但你应该总是考虑它们是否是解决手头问题的最佳方案。如果有疑问,请运行一些比较测试。如果您愿意使用第三方库,您可以使用countBy
方法,从中返回包
@Test
public void countingSubstrings()
{
MutableList<String> list = Lists.mutable.with(
"10/10/2012 [user2] some message1",
"10/10/2012 [user1] some message2",
"10/10/2012 [qwwww] some message3",
"11/10/2012 [user3] some message4",
"11/10/2012 [user3] some message5",
"12/10/2012 [user2] some message6",
"12/10/2012 [user3] some message7",
"12/10/2012 [user2] some message8",
"12/10/2012 [sdsds] some message9",
"12/10/2012 [user2] some message10");
Bag<String> countsByUser =
list.countBy(this::findUser);
Bag<String> countsByMessage =
list.countBy(this::findMessage);
Bag<String> countsByDate =
list.countBy(this::findDate);
}
private String findUser(String string)
{
return string.substring(string.indexOf('[') + 1, string.indexOf(']'));
}
private String findMessage(String string)
{
return string.substring(string.indexOf(']') + 2, string.length());
}
private String findDate(String string)
{
return string.substring(0, string.indexOf('[') - 1);
}
@测试
public void countingSubstrings()
{
MutableList=Lists.mutable.with(
“2012年10月10日[user2]一些消息1”,
“2012年10月10日[user1]一些消息2”,
“2012年10月10日[QWW]一些消息3”,
“2012年10月11日[user3]一些消息4”,
“2012年10月11日[user3]一些消息5”,
“2012年10月12日[user2]一些消息6”,
“2012年10月12日[user3]一些消息7”,
“2012年10月12日[user2
user1: 1
user2: 4
qwwww: 1
sdsds: 1
user3: 3
11/10/2012: 2
12/10/2012: 5
10/10/2012: 3
some message9: 1
some message8: 1
some message10: 1
some message7: 1
some message6: 1
some message5: 1
some message4: 1
some message3: 1
some message2: 1
some message1: 1
public class SpeedComparison
{
private static String extractUser(String aS)
{
int start = aS.indexOf('[') + 1;
int end = aS.indexOf(']');
return aS.substring(start, end);
}
static Map<String, Integer> group(List<String> aList)
{
Map<String, Integer> results = new HashMap<>();
for (String s : aList)
{
String extract = extractUser(s);
int count = results.getOrDefault(extract, 0) + 1;
results.put(extract, count);
}
return results;
}
final static Pattern pattern = Pattern.compile("\\[(.*)\\]");
static Optional<String> parseValue(String raw) {
Matcher m = pattern.matcher(raw);
if (m.find()) {
return Optional.of(m.group(1));
} else {
return Optional.empty();
}
}
public static void main(String[] args)
{
List<String> list = new ArrayList<>();
for (int i = 0; i< 100000 ; ++i)
{
list.add("10/10/2012 [user2] some message1");
list.add("10/10/2012 [user1] some message2");
list.add("10/10/2012 [qwwww] some message3");
list.add("11/10/2012 [user3] some message4");
list.add("11/10/2012 [user3] some message5");
list.add("12/10/2012 [user2] some message6");
list.add("12/10/2012 [user3] some message7");
list.add("12/10/2012 [user2] some message8");
list.add("12/10/2012 [sdsds] some message9");
list.add("12/10/2012 [user2] some message10");
}
//Test basic
final long start1 = System.currentTimeMillis();
group(list);
final long dur1 = System.currentTimeMillis() - start1;
//Test streams
final long start2 = System.currentTimeMillis();
list.stream().map(s -> parseValue(s).orElse("missing")).collect(Collectors.groupingBy(
Function.identity(), Collectors.counting()
));
final long dur2 = System.currentTimeMillis() - start2;
System.out.println("Speed Comparison");
//prints ~100, ~1000 milliseconds (10x slower with streams)
System.out.printf("Test 1: %s%nTest 2: %s",dur1,dur2);
}
}
@Test
public void countingSubstrings()
{
MutableList<String> list = Lists.mutable.with(
"10/10/2012 [user2] some message1",
"10/10/2012 [user1] some message2",
"10/10/2012 [qwwww] some message3",
"11/10/2012 [user3] some message4",
"11/10/2012 [user3] some message5",
"12/10/2012 [user2] some message6",
"12/10/2012 [user3] some message7",
"12/10/2012 [user2] some message8",
"12/10/2012 [sdsds] some message9",
"12/10/2012 [user2] some message10");
Bag<String> countsByUser =
list.countBy(this::findUser);
Bag<String> countsByMessage =
list.countBy(this::findMessage);
Bag<String> countsByDate =
list.countBy(this::findDate);
}
private String findUser(String string)
{
return string.substring(string.indexOf('[') + 1, string.indexOf(']'));
}
private String findMessage(String string)
{
return string.substring(string.indexOf(']') + 2, string.length());
}
private String findDate(String string)
{
return string.substring(0, string.indexOf('[') - 1);
}