如何通过比较Java中给定对象中的字段值来合并两个对象列表

use*_*486 3 java merge arraylist

我有两个对象列表,我想将它们合并为一个。这些对象有两个字段,“名称”和“值”。对于list2中的给定obj2,如果在list1中找到obj1的“名称”字段(list1中的obj1和list2中的obj2)匹配,则我们使用obj2的“值”覆盖obj1。如果找不到匹配项,则将obj2添加到list1。最终输出将更新list1。

有什么快速的方法可以做到这一点吗?我能想到的就是使用两个for循环比较两个列表中的所有对象

class NameValueObj{
String name;
String value;
}

List<NameValueObj> merge(List<NameValueObj> list1, List<NameValueObj> list2){
// I want to merge two list here
}
Run Code Online (Sandbox Code Playgroud)

NameValueObj是给定的,因此我不能修改对象源。

这是我的方法。

private List<Header> mergeHeaders(List<Header> defHeaders, List<Header> ovrdHeaders) {
        List<Header> lFinal = defHeaders;
        boolean foundMatch = false;
        for (Header ovrdHeader : ovrdHeaders) {
            foundMatch = false;
            for (Header defHeader : defHeaders) {
                if (defHeader.getName().equalsIgnoreCase(ovrdHeader.getName())) {
                    defHeader.setValue(ovrdHeader.getValue());
                    foundMatch = true;
                    break;
                }
            }
            if(!foundMatch) {
                lFinal.add(ovrdHeader);
            }

        }

        return lFinal;
    }
Run Code Online (Sandbox Code Playgroud)

标头具有名称和值字段。标头在给定列表中具有唯一的名称。

Ale*_*rov 7

您的算法是O(n*n)(二次)。

您可以O(n)使用(临时)临时方式LinkedHashMap

private List<Header> mergeHeaders(final List<Header> defHeaders, final List<Header> ovrdHeaders) {
    final Map<String, Header> headersMap = new LinkedHashMap<String, Header>();

    for (final Header defHeader : defHeaders) {
        headersMap.put(defHeader.getName().toLowerCase(), defHeader);
    }

    for (final Header ovrdHeader : ovrdHeaders) {
        headersMap.put(ovrdHeader.getName().toLowerCase(), ovrdHeader);
    }

    return new ArrayList<Header>(headersMap.values());
}
Run Code Online (Sandbox Code Playgroud)

请注意,行为与实现的行为并不完全相同。不同之处在于:

  • 此实现返回一个新的列表实例,而不是修改第一个列表。海事组织,这是有好处的,但可能要视情况而定。如果需要,您可以按如下方式修改第一个列表(尽管我建议这样做):

    defHeaders.clear();
    defHeaders.addAll(headersMap.values());
    return defHeaders;
    
    Run Code Online (Sandbox Code Playgroud)
  • 此实现假定标题名称在两个列表中已经是唯一的(不区分大小写),而您的名字没有做此假设。
    如果标头名称不是唯一的,则此实现将保留列表1或列表2中的最后一个标头。