我有这样的课:
class MultiDataPoint {
private DateTime timestamp;
private Map<String, Number> keyToData;
}
我想为每个MultiDataPoint生成
class DataSet {
public String key;
List<DataPoint> dataPoints;
}
class DataPoint{
DateTime timeStamp;
Number data;
}
当然,在多个MultiDataPoints中,“键”可以相同。
因此,给定a List<MultiDataPoint>
,如何使用Java 8流转换为List<DataSet>
?
这是我目前在没有流的情况下进行转换的方式:
Collection<DataSet> convertMultiDataPointToDataSet(List<MultiDataPoint> multiDataPoints)
{
Map<String, DataSet> setMap = new HashMap<>();
multiDataPoints.forEach(pt -> {
Map<String, Number> data = pt.getData();
data.entrySet().forEach(e -> {
String seriesKey = e.getKey();
DataSet dataSet = setMap.get(seriesKey);
if (dataSet == null)
{
dataSet = new DataSet(seriesKey);
setMap.put(seriesKey, dataSet);
}
dataSet.dataPoints.add(new DataPoint(pt.getTimestamp(), e.getValue()));
});
});
return setMap.values();
}
这是一个有趣的问题,因为它表明有很多不同的方法可以达到相同的结果。下面我展示了三种不同的实现。
集合框架中的默认方法: Java 8向集合类中添加了一些与 Stream API 没有直接关系的方法。使用这些方法,可以大大简化非流实现的实现:
Collection<DataSet> convert(List<MultiDataPoint> multiDataPoints) {
Map<String, DataSet> result = new HashMap<>();
multiDataPoints.forEach(pt ->
pt.keyToData.forEach((key, value) ->
result.computeIfAbsent(
key, k -> new DataSet(k, new ArrayList<>()))
.dataPoints.add(new DataPoint(pt.timestamp, value))));
return result.values();
}
具有扁平和中间数据结构的Stream API: 以下实现几乎与Stuart Marks提供的解决方案相同。与他的解决方案相比,以下实现使用
匿名内部类 作为中间数据结构。
Collection<DataSet> convert(List<MultiDataPoint> multiDataPoints) {
return multiDataPoints.stream()
.flatMap(mdp -> mdp.keyToData.entrySet().stream().map(e ->
new Object() {
String key = e.getKey();
DataPoint dataPoint = new DataPoint(mdp.timestamp, e.getValue());
}))
.collect(
collectingAndThen(
groupingBy(t -> t.key, mapping(t -> t.dataPoint, toList())),
m -> m.entrySet().stream().map(e -> new DataSet(e.getKey(), e.getValue())).collect(toList())));
}
带有地图合并功能的Stream API: 您也可以为每个 MultiDataPoint 创建一个 Map
,而不是将原始数据结构变平,然后通过reduce操作将所有地图合并为一个地图。该代码比上面的解决方案简单一些: __
Collection<DataSet> convert(List<MultiDataPoint> multiDataPoints) {
return multiDataPoints.stream()
.map(mdp -> mdp.keyToData.entrySet().stream()
.collect(toMap(e -> e.getKey(), e -> asList(new DataPoint(mdp.timestamp, e.getValue())))))
.reduce(new HashMap<>(), mapMerger())
.entrySet().stream()
.map(e -> new DataSet(e.getKey(), e.getValue()))
.collect(toList());
}
您可以在 Collectors 类中找到 地图合并 的实现。不幸的是,从外部访问它有点棘手。以下是 地图合并 的替代实现:
<K, V> BinaryOperator<Map<K, List<V>>> mapMerger() {
return (lhs, rhs) -> {
Map<K, List<V>> result = new HashMap<>();
lhs.forEach((key, value) -> result.computeIfAbsent(key, k -> new ArrayList<>()).addAll(value));
rhs.forEach((key, value) -> result.computeIfAbsent(key, k -> new ArrayList<>()).addAll(value));
return result;
};
}
我已经为这些列表创建了模型类,这些列表是我收到的对我的服务的响应 清单1 清单2 列表3是最后的列表,上面两个列表映射的结果,即我的服务的响应 清单3 这些列表与用户名和用户标签相连。我已将列表1的所有值映射到列表3。现在对于列表2,我需要检查每个userLabel是否在list3中存在一个userName等于userLabel的对象,如果为true,则totalUsers的值设置为list3的那
我需要将Java转换为的实例(包括映射内容) 我应该用什么来代替来使此代码可编译?
我有一个,另一个作为参数 我想创建一个按类型返回的方法 通常我会写 用java stream写的最佳做法是什么?
我知道如何变换
我正在寻找第一次到流API的Java8。我尝试创建一个筛选器来从映射中删除元素。
我正在从文件中读取值并获取列表。如下- 一旦我得到这个