当前位置: 首页 > 知识库问答 >
问题:

如何结合2个或更多的对象在一个列表中基于这些对象的某些字段

和光启
2023-03-14

如果标题听起来很模糊,我很抱歉。

我有个目标-

    public class AccountInfo {
        private String accountId;
        private Double vat;
        private Double totalFee;
        private Date invoiceDate;
    }

还有这些物品的清单-

List<AccountInfo> AccountInfoLst;

我想通过合并具有相同帐户ID的对象来操作这个列表,方法是将vat字段和总计费用字段相加,前提是它们也具有相同的发票日期。

如果两个对象具有相同的帐户ID但不同的发票日期,则它们不应合并。

共有2个答案

谢哲瀚
2023-03-14

在重复的列表上迭代,将它们合并到一个AcCountInfo并删除所有重复的列表。

由于Date已被弃用,我们使用了java。时间LocalDate。

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class AccountInfo {
    private String accountId;

    private Double vat;
    private Double totalFee;
    private LocalDate invoiceDate;

    public Double getVat() {
        return vat;
    }

    public void setVat(Double vat) {
        this.vat = vat;
    }

    public Double getTotalFee() {
        return totalFee;
    }

    public void setTotalFee(Double totalFee) {
        this.totalFee = totalFee;
    }

    public LocalDate getInvoiceDate() {
        return invoiceDate;
    }

    public void setInvoiceDate(LocalDate invoiceDate) {
        this.invoiceDate = invoiceDate;
    }

    public AccountInfo(String accountId, Double vat, Double totalFee, LocalDate invoiceDate) {
        this.accountId = accountId;
        this.vat = vat;
        this.totalFee = totalFee;
        this.invoiceDate = invoiceDate;
    }

    public String getAccountId() {
        return accountId;
    }

    public void setAccountId(String accountId) {
        this.accountId = accountId;
    }

    public String toString() {
        return accountId + " " + vat + " " + totalFee + " " + invoiceDate;
    }

    public boolean areEquals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AccountInfo that = (AccountInfo) o;
        var thatInvoiceDate = that.getInvoiceDate();
        var thisInvoiceDate = getInvoiceDate();
        return that.getAccountId().equals(getAccountId()) && thatInvoiceDate.isEqual(thisInvoiceDate);
    }

    @Override
    public int hashCode() {
        return Objects.hash(accountId, vat, totalFee, invoiceDate);
    }
}

public class MainClass {
    public static void main(String... $) {
        var out = System.out;
        
        List<AccountInfo> accounts = Stream.of(new AccountInfo("A", 20.2, 200.4, LocalDate.of(2022, 11, 3))
                , new AccountInfo("A", 20.2, 200.4, LocalDate.of(2022, 11, 3)),
                new AccountInfo("B", 20.2, 200.4, LocalDate.of(2023, 11, 2)),
                new AccountInfo("B", 20.2, 200.4, LocalDate.of(2023, 11, 2))).collect(Collectors.toList());
        
        //Iterating over all the accounts
        for (int i = 0; i < accounts.size(); i++) {
            var account = accounts.get(i);
            ArrayList<AccountInfo> duplicates = new ArrayList<>();
            for (int j = i + 1; j < accounts.size(); j++) {
                var acc = accounts.get(j);
                if (acc.areEquals(account))
                    duplicates.add(acc);
            }
//            out.println(i + " " + indices);
            //Merging all duplicates to account
            for (AccountInfo acc : duplicates) {
                account.setTotalFee(acc.getTotalFee() + account.getTotalFee());
                account.setVat(acc.getVat() + account.getVat());
            }
            //Removing all duplicates
            accounts.removeAll(duplicates);
        }
        //printing accounts after removal of duplicates
        out.println(accounts);
    }
}
[A 40.4 400.8 2022-11-03, B 40.4 400.8 2023-11-02]
宓诚
2023-03-14

如果你想利用流来做这件事,其中一种可能的方法是收集数据到地图,使用一个组合了accountIdinvoiceDate的对象作为键。

将合并映射到同一密钥的所有帐户。

帐户ID发票日期中不同的帐户将保持不变。

    public static void main(String[] args) {
        List<AccountInfo> result = List.of(
                    new AccountInfo("123", 80., 180., LocalDate.now()),
                    new AccountInfo("123", 120., 590., LocalDate.now()),
                    new AccountInfo("123", 30., 120., LocalDate.now().minusDays(3))
                )
                .stream()
                .collect(Collectors.toMap(
                        AccountWrapper::new,
                        UnaryOperator.identity(),
                        (acc1, acc2) -> new AccountInfo(
                                acc1.getAccountId(),
                                acc1.getVat() + acc2.getVat(),
                                acc1.getTotalFee() + acc2.getTotalFee(),
                                acc1.getInvoiceDate())
                ))
                .values().stream()
                .collect(Collectors.toList());

        result.forEach(System.out::println);
    }



    public record AccountWrapper(String accountId, LocalDate invoiceDate) {
        public AccountWrapper(AccountInfo info) {
            this(info.getAccountId(), info.getInvoiceDate());
        }
    }

输出

AccountInfo{accountId='123', vat=200.0, totalFee=770.0, invoiceDate=2022-02-09}
AccountInfo{accountId='123', vat=30.0, totalFee=120.0, invoiceDate=2022-02-06}

 类似资料:
  • 我有一个对象的arraylist,其中有一个字段“name”,还有一个名称列表。我必须从列表中选择包含任何名称的所有对象。如何在java中最有效地实现这一点。任何代码片段都将受到高度赞赏。 例子: 让类名为 A由id、name、subject等字段组成。 那么让我们假设我有一个列表 所以假设我有第二个列表 因此,我只想从objectsA列表中选择那些名称字段由名称列表中的名称组成的对象,也就是说,

  • 我正在学习使用Java8和Stream做事情。我有一个问题,我正试图用java8流解决这个问题。 我有一个地图类型

  • 问题内容: 假设我们有一个对象类型,从而产生。 现在,我们要创建一个新的对象,这只是(即场和来自被修剪)。所以我们定义一个类如下: 然后我们初始化如下: 。 不幸的是,执行此操作时出现运行时错误。 问题: 我们如何如上所述定义? 问题答案: 假设你有三个字段中 创建一个新的字段 声明一个方法是这样 从A设置B的必填字段。 例如 设置f1并返回B对象 .B将成为一个成员,你可以简单地从A取得乙。 f

  • 我有两个具有一对多关系的实体,它们通过复合主键连接在一起。由于Spring Data为oracle数据库生成错误计数不同的查询,我SQL笛卡尔连接的输出,这导致每一行子对象都重复父对象的行。我需要找出基于复合键的不同的父对象,然后在列表中为父对象添加每个子对象,并将其设置为父对象的属性 我能够根据父对象的组合键找到不同的父对象。以下是相关代码 假设我有以下输入 我需要产生以下输出 这方面的任何帮助

  • 我在编写HQL查询时遇到困难,无法从我的案例实体中仅选择案例ID、标题和案例状态字段。返回的病例必须根据病例ID进行区分。我不希望包含名称和用户ID字段。我也不想对caseid、title和caseStatus字段使用延迟抓取。请注意,案例状态字段是一对多列表。以下是实体。为了节省空间,省略了getter/setter。 我的目标是检索一个不同的

  • 我有一个大的嵌套对象。我想在JSON字符串中序列化这个对象,但是我只需要包含某些字段。这里的问题是字段可能会非常频繁地更改,我希望以一种可以帮助我轻松包含或排除用于序列化的字段的方式来构建它。 我知道我可以编写很多代码来提取某些字段并“手动”构建JSON。但我想知道,除了指定一个必填字段列表之外,是否还有其他优雅的方法可以实现类似的结果? 例如,我希望在响应中只包含和以下对象结构: Json: