一个基于流 API Collectors::toMap
的简单解决方案,带有合并函数和 Supplier<Map>
以维护初始流中元素的顺序如下——计算映射的值被包装到新的 { {1}}:
ArrayList
对于像这样创建以匹配输入 JSON 的 List<MyObject> totals = new ArrayList<>(
data // initial List<MyObject> read from JSON
.stream() // Stream<MyObject>
.collect(Collectors.toMap(
obj -> Arrays.asList(obj.getRecordNo(),obj.getYear()),// group by recordNo and year
obj -> obj,// a copy may be created if needed
(o1,o2) -> { // merge function
o1.setAmount(o1.getAmount().add(o2.getAmount())); // total amount
o1.setSum(o1.getSum().add(o2.getSum())); // total sum
return o1;
},LinkedHashMap::new // maintain order of initial data
))
.values() // get Collection<MyObject> with totals grouped by key
);
:
data
结果如下(在List<MyObject> data = Arrays.asList(
new MyObject(10L,2021,new BigDecimal(10),new BigDecimal(100)),new MyObject(10L,new BigDecimal(20),new BigDecimal(200)),2020,new BigDecimal(5),new BigDecimal(20)),new MyObject(11L,new BigDecimal(200))
);
类中使用自定义toString
):
MyObject
,
使用流的解决方案:
public static void main(String[] args) {
// create some test data
List<MyObject> objects = new ArrayList<>();
for (int i = 0; i < 3; i++) {
MyObject obj = new MyObject();
obj.setSum(BigDecimal.TEN);
obj.setAmount(new BigDecimal(i));
obj.setYear(2020);
obj.setRecordNo(1L);
objects.add(obj);
}
for (int i = 0; i < 3; i++) {
MyObject obj = new MyObject();
obj.setSum(BigDecimal.TEN);
obj.setAmount(new BigDecimal(i));
obj.setYear(2021);
obj.setRecordNo(2L);
objects.add(obj);
}
for (int i = 0; i < 3; i++) {
MyObject obj = new MyObject();
obj.setSum(BigDecimal.TEN);
obj.setAmount(new BigDecimal(i));
obj.setYear(2021);
obj.setRecordNo(3L);
objects.add(obj);
}
// groupingBy collector produces a key for object grouping
// we group by 'recordNo' and 'year' fields
Map<String,List<MyObject>> grouped = objects.stream()
.collect(Collectors.groupingBy(obj -> obj.getRecordNo() + " " + obj.getYear()));
// groupingBy colletor returned a map,but we need only
// its values
List<MyObject> groupedAndSummedUp = grouped.values()
.stream()
.map(group -> {
return group.stream()
.reduce((obj1,obj2) -> {
// actual 'merging' of objects is happening here
BigDecimal newAmount = obj1.getAmount().add(obj2.getAmount());
BigDecimal newSum = obj1.getSum().add(obj2.getSum());
obj1.setAmount(newAmount);
obj1.setSum(newSum);
return obj1;
})
.get();
})
.collect(Collectors.toList());
,
您可以使用 Comparator
对列表进行排序。创建一个实现比较器的类(MyComparator
),添加根据您的条件进行排序的逻辑,例如首先基于 recordNo
然后基于 year
(您可以决定是升序还是降序)。
然后您可以调用 Collections.sort(<yourList>,new MyComparator());
它将对当前列表进行排序。
现在您可以根据需要创建一个新列表,并继续检查是否需要将先前对象的值与当前对象相加。如果为真,您可以使用汇总值创建一个新对象并将其放入新列表中。
附言由于您没有提供任何工作逻辑,所以没有自己提供代码。
,
不完全确定你最后想做什么,但你可以查看 Java8 流,这将过滤掉你不想要的对象,只留下你想要的项目
Stream.of(list or array).filter(obj->condition);
ref
,
让我们从迭代(非流)方法开始
public static void main(String[] args) {
List<MyObject> objects = List.of(
new MyObject(10L,new BigDecimal(200))
);
Map<Long,Map<Integer,MyObject>> mapped = new HashMap<>();
for (MyObject object : objects) {
var recordNo = object.getRecordNo();
if (mapped.containsKey(recordNo)) {
var objectMap = mapped.get(recordNo);
var year = object.getYear();
if (objectMap.containsKey(year)) {
var objectFromMap = objectMap.get(year);
var myObject = new MyObject(recordNo,year,object.getAmount().add(objectFromMap.getAmount()),object.getSum().add(objectFromMap.getSum()));
objectMap.put(year,myObject);
} else {
objectMap.put(year,object);
}
mapped.put(recordNo,objectMap);
} else {
Map<Integer,MyObject> value = new HashMap<>();
value.put(object.getYear(),object);
mapped.put(recordNo,value);
}
}
// convert map to lists
var newList = mapped.values()
.stream()
.map(a -> new ArrayList<>(a.values()))
.collect(Collectors.toList());
System.out.println(newList);
}
还有一种流方法
var collect = objects.stream()
.collect(Collectors.groupingBy(
MyObject::getRecordNo,Collectors.groupingBy(MyObject::getYear)))
.values()
.stream()
.map(a -> a.values()
.stream()
.map(values -> values.stream()
.reduce((myObject1,myObject2) -> {
Long recordNo = myObject1.getRecordNo();
Integer year = myObject1.getYear();
var newAmount = myObject1.getAmount().add(myObject2.getAmount());
var newSum = myObject1.getSum().add(myObject2.getSum());
return new MyObject(recordNo,newAmount,newSum);
})
.get())
.collect(Collectors.toList()))
.collect(Collectors.toList());
System.out.println(collect);
本文链接:https://www.f2er.com/17455.html