在Java中按多个值过滤和总结列表中的对象

我有一个 List<myobject> 并且此列表包含数千个对象。我想按 recordNoyear 过滤此列表。如果有任何对象具有相同的 recordNoyear 值,我想总结它们的 amountsum

过滤列表并汇总值后,我想创建一个新的 List<myobject> 并且此列表不会包含任何重复的对象(通过 recordNoyear)>

myobject 结构:

@Getter
@Setter
public class myobject{

    private Long recordNo;
    private Integer year;
    private BigDecimal amount;
    private BigDecimal sum;
}

当前示例列表输出:

[
    {
     "recordNo": 10,"year": 2021,"amount": 10,"sum": 100,},{
     "recordNo": 10,"amount": 20,"sum": 200,"year": 2020,"amount": 5,"sum": 20,{
     "recordNo": 11,}
]

所需的列表输出:

[
    {
     "recordNo": 10,"amount": 30,"sum": 300,"amount": 25,"sum": 120,}
]

创建所需列表输出的最佳方法是什么?

lshongbo 回答:在Java中按多个值过滤和总结列表中的对象

一个基于流 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

大家都在问