如何使用Java8进行分组和收集?
我有一个元素列表,我们称之为关键字,如下所示:如何使用Java8进行分组和收集?,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个元素列表,我们称之为关键字,如下所示: public class Keyword { Long id; String name; String owner; Date createdTime; Double price; Date metricDay; Long position; } public class KeywordMetric { Double price; Date metricDay; Lo
public class Keyword {
Long id;
String name;
String owner;
Date createdTime;
Double price;
Date metricDay;
Long position;
}
public class KeywordMetric {
Double price;
Date metricDay;
Long position;
}
public class KeywordMeged {
Long id;
String name;
String owner;
List<KeywordMetric> metricList;
}
public class KeywordMerged {
public static KeywordMerged from(Keyword k) {
KeywordMetric metric = new KeywordMetric();
metric.setPrice(k.getPrice());
metric.setMetricDay(k.getMetricDay());
metric.setPosition(k.getPosition());
KeywordMerged merged = new KeywordMerged();
merged.setId(k.getId());
merged.setName(k.getName());
merged.setOwner(k.getOwner());
merged.setMetricList(new ArrayList<>(Arrays.asList(metric)));
return merged;
}
}
问题是每一天都有一个关键词。例如:
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.1", metricDay="11/11/1999", position=109}
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.3", metricDay="12/11/1999", position=108}
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.2", metricDay="13/11/1999", position=99}
Keyword{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", price="0.6", metricDay="13/11/1999", position=5}
Keyword{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", price="0.1", metricDay="14/11/1999", position=4}
Keyword{id=3, name="kw3", owner="Josh", createdTime="13/12/1992", price="0.1", metricDay="13/11/1999", position=8}
然后,从这个列表中,我想创建一个新的列表,在一个列表中包含所有这些不同日期的所有指标。首先,我创建了这样一个类:
public class Keyword {
Long id;
String name;
String owner;
Date createdTime;
Double price;
Date metricDay;
Long position;
}
public class KeywordMetric {
Double price;
Date metricDay;
Long position;
}
public class KeywordMeged {
Long id;
String name;
String owner;
List<KeywordMetric> metricList;
}
public class KeywordMerged {
public static KeywordMerged from(Keyword k) {
KeywordMetric metric = new KeywordMetric();
metric.setPrice(k.getPrice());
metric.setMetricDay(k.getMetricDay());
metric.setPosition(k.getPosition());
KeywordMerged merged = new KeywordMerged();
merged.setId(k.getId());
merged.setName(k.getName());
merged.setOwner(k.getOwner());
merged.setMetricList(new ArrayList<>(Arrays.asList(metric)));
return merged;
}
}
我想归档的是从第一个列表到如下结构:
public class Keyword {
Long id;
String name;
String owner;
Date createdTime;
Double price;
Date metricDay;
Long position;
}
public class KeywordMetric {
Double price;
Date metricDay;
Long position;
}
public class KeywordMeged {
Long id;
String name;
String owner;
List<KeywordMetric> metricList;
}
public class KeywordMerged {
public static KeywordMerged from(Keyword k) {
KeywordMetric metric = new KeywordMetric();
metric.setPrice(k.getPrice());
metric.setMetricDay(k.getMetricDay());
metric.setPosition(k.getPosition());
KeywordMerged merged = new KeywordMerged();
merged.setId(k.getId());
merged.setName(k.getName());
merged.setOwner(k.getOwner());
merged.setMetricList(new ArrayList<>(Arrays.asList(metric)));
return merged;
}
}
我知道如何处理大量循环和可变变量,但我不知道如何处理流和lambda操作。我能够通过Id对所有相关关键字进行分组:
Map<Long, List<Keyword>> kwL = kwList.stream()
.collect(groupingBy(Keyword::getId))
我知道使用.forEach我可以迭代该映射,但不知道如何使流的collect方法从List传递到KeywordMerged 您可以尝试改用。其中:
关键字::getId是一个键映射器函数
关键字合并。从。。。执行转换:关键字=>KeywordMerged
{}对于左->实体,使用相同的ID组合
Collection<KeywordMerged> result = keywords.stream()
.collect(Collectors.toMap(
Keyword::getId,
k -> KeywordMerged.from(k), // you can replace this lambda with a method reference
(left, right) -> {
left.getMetricList().addAll(right.getMetricList());
return left;
}))
.values();
转换方法可能如下所示:
public class Keyword {
Long id;
String name;
String owner;
Date createdTime;
Double price;
Date metricDay;
Long position;
}
public class KeywordMetric {
Double price;
Date metricDay;
Long position;
}
public class KeywordMeged {
Long id;
String name;
String owner;
List<KeywordMetric> metricList;
}
public class KeywordMerged {
public static KeywordMerged from(Keyword k) {
KeywordMetric metric = new KeywordMetric();
metric.setPrice(k.getPrice());
metric.setMetricDay(k.getMetricDay());
metric.setPosition(k.getPosition());
KeywordMerged merged = new KeywordMerged();
merged.setId(k.getId());
merged.setName(k.getName());
merged.setOwner(k.getOwner());
merged.setMetricList(new ArrayList<>(Arrays.asList(metric)));
return merged;
}
}
我想你已经有了基本的想法。因此,根据您的需要进行重构…您可以尝试使用。其中:
关键字::getId是一个键映射器函数
关键字合并。从。。。执行转换:关键字=>KeywordMerged
左、右->{..}组合具有相同ID的实体的度量
Collection<KeywordMerged> result = keywords.stream()
.collect(Collectors.toMap(
Keyword::getId,
k -> KeywordMerged.from(k), // you can replace this lambda with a method reference
(left, right) -> {
left.getMetricList().addAll(right.getMetricList());
return left;
}))
.values();
转换方法可能如下所示:
public class Keyword {
Long id;
String name;
String owner;
Date createdTime;
Double price;
Date metricDay;
Long position;
}
public class KeywordMetric {
Double price;
Date metricDay;
Long position;
}
public class KeywordMeged {
Long id;
String name;
String owner;
List<KeywordMetric> metricList;
}
public class KeywordMerged {
public static KeywordMerged from(Keyword k) {
KeywordMetric metric = new KeywordMetric();
metric.setPrice(k.getPrice());
metric.setMetricDay(k.getMetricDay());
metric.setPosition(k.getPosition());
KeywordMerged merged = new KeywordMerged();
merged.setId(k.getId());
merged.setName(k.getName());
merged.setOwner(k.getOwner());
merged.setMetricList(new ArrayList<>(Arrays.asList(metric)));
return merged;
}
}
我想你已经有了基本的想法。因此,根据您的需要进行重构…这是一种稍微不同的方法。首先,收集按id分组的关键字图:
Map<Integer, List<Keyword>> groupedData = keywords.stream()
.collect(Collectors.groupingBy(k -> k.getId()));
进一步将地图转换为所需格式的列表:
List<KeywordMerged> finalData = groupedData.entrySet().stream()
.map(k -> new KeywordMerged(k.getValue().get(0).getId(),
k.getValue().stream()
.map(v -> new KeywordMetric(v.getMetricDay(), v.getPrice(), getPosition()))
.collect(Collectors.toList())))
.collect(Collectors.toList());
这将对分组数据起作用,但转换映射将创建KeywordMerged对象,该对象作为参数将接收id,您可以自己进一步扩展它,并转换为以前按id分组的列表数据
编辑:我相信通过一些提取方法,你可以使它看起来更漂亮:一个稍微不同的方法。首先,收集按id分组的关键字图:
Map<Integer, List<Keyword>> groupedData = keywords.stream()
.collect(Collectors.groupingBy(k -> k.getId()));
进一步将地图转换为所需格式的列表:
List<KeywordMerged> finalData = groupedData.entrySet().stream()
.map(k -> new KeywordMerged(k.getValue().get(0).getId(),
k.getValue().stream()
.map(v -> new KeywordMetric(v.getMetricDay(), v.getPrice(), getPosition()))
.collect(Collectors.toList())))
.collect(Collectors.toList());
这将对分组数据起作用,但转换映射将创建KeywordMerged对象,该对象作为参数将接收id,您可以自己进一步扩展它,并转换为以前按id分组的列表数据
编辑:我相信通过一些提取方法,你可以让它看起来更好:有什么想法吗?是的,但是你试过什么?看起来你想让我们为你写一些代码。虽然许多用户愿意为陷入困境的程序员编写代码,但他们通常只在海报已经试图自己解决问题时才提供帮助。演示这项工作的一个好方法是包括您迄今为止编写的代码、示例输入(如果有)、预期输出以及您实际获得的控制台输出、回溯等。。你提供的细节越多,你可能得到的答案就越多。检查并更新我的问题,我没有走得太远,这就是为什么我没有把我的代码。谢谢你的建议,有什么想法吗?是的,但是你试过什么?看起来你想让我们为你写一些代码。虽然许多用户愿意为陷入困境的程序员编写代码,但他们通常只在海报已经试图自己解决问题时才提供帮助。演示这项工作的一个好方法是包括您迄今为止编写的代码、示例输入(如果有)、预期输出以及您实际获得的控制台输出、回溯等。。你提供的细节越多,你可能得到的答案就越多。检查并更新我的问题,我没有走得太远,这就是为什么我没有把我的代码。谢谢你的建议。