我有一个MoveTrack
个对象的列表,我想按月分组,并计算并将数据存储在Map<String, Double>
中。我正在尝试学习Lambda并试验它,以便尝试用Lambda完成这项任务。
class MoveTrack {
private Date time;
private Double movementAmount;
//getters and setters
}
// in my main method
List<MoveTrack> mveTracking = new ArrayList<>();
Map<String, Double> movMap = new HashMap<>();
所以我希望能够对moveTracking
列表进行分组并将值汇总到movMap
,每个Map Key = Month Name(1月,2月等)和相应的Value运动金额是该月双打的总和。
答案 0 :(得分:6)
如果您打开使用第三方库,Eclipse Collections会使用名为sumBy
的专用方法,这些方法适用于lambdas。
如果您使用Eclipse Collections中的MutableList
作为moveTracking列表,则代码如下所示:
MutableList<MoveTrack> moveTracking = Lists.mutable.empty();
ObjectDoubleMap<String> doubleMap =
moveTracking.sumByDouble(MoveTrack::getMonthName, MoveTrack::getMovementAmount);
由您决定要在何处以及如何实施getMonthName()
。您会注意到sumByDouble
返回ObjectDoubleMap
。这意味着您可以对double
使用movementAmount
,并且在求和期间不会将其装箱。
如果您想保留当前的List<MoveTrack>
类型,可以使用ListAdapter
或Iterate
实用程序类来完成相同的操作。
List<MoveTrack> list = ...;
ObjectDoubleMap<String> doubleMap =
Iterate.sumByDouble(list, MoveTrack::getMonthName, MoveTrack::getMovementAmount);
注意:我是Eclipse Collections的提交者
答案 1 :(得分:5)
Collectors.groupingBy
允许您将列表缩减为映射,其中键是对列表元素的某些操作,值是一些应用于元素操作的聚合函数。
在你的情况下,你可以使用这样的东西:
SimpleDateFormat monthFormatter = new SimpleDateFormat("MMM");
Map<String, Double> moveMap =
moveTracking.stream()
.collect(Collectors.groupingBy
(m -> monthFormatter.format(m.getTime()),
Collectors.summingDouble(MoveTrack::getMovementAmount)));
答案 2 :(得分:2)
使用Collectors.groupingBy,如下所示:
O(1)
代码适合您;)
mveTracking.stream().collect(Collectors.groupingBy(m -> {
final Calendar cal = Calendar.getInstance();
cal.setTime(m.getTime());
final int month = cal.get(Calendar.MONTH);
return new DateFormatSymbols().getMonths()[month];
}, Collectors.summingDouble(MoveTrack::getMovementAmount)));