簡體   English   中英

如何根據java 8中的值合並對象的ArrayList?

[英]How to merge ArrayList of Objects based on value in java 8?

我想在來自各種來源的列表中建立數據庫連接。 某些來源可能/可能不提供 URL。

我想保留具有完整信息的記錄(即 dbName、connUrl、isActive)+ 如果任何數據庫沒有任何來源的完整記錄。

記錄.java,

String dbName;
String connUrl;
String isActiveYN;

主應用程序.java,

List <Record> connRecords = new ArrayList<>();
connRecords = someFunc(sourceName) // some func takes source as param and returns connection List
connRecords.addAll(someFunc(sourceName));
connRecords.addAll(someFunc(sourceName));
//logic for getting all unique DBs

例如:來自源 Alpha 的列表 1:[{A,Y},{B,Y},{C, Y},{D,Y}]

源 Beta 中的列表 2:[{A, abc-url, Y}, {B, xyz-url, Y}]

源 Gamma 中的列表 3:[{A,Y},{C,Y}]

合並所有列表后,我們得到:

I/P 列表:[{A,Y}, {B,Y}, {C, Y}, {D,Y}, {A, abc-url, Y}, {B, xyz-url, Y}, {A,Y}, {C,Y}]

對於 dbName A,源 Beta 具有完整的記錄信息,因此我們將采用

對於 dbName B,源 Beta 具有完整的記錄信息,因此我們將采用

對於 dbName C,即使沒有一個來源有完整的信息,我們仍然會保留它,因為它是一個可用的數據庫,並且某些來源可能在未來的某個時候具有 url 連接。 對於 dbName D,即使沒有一個來源有完整的信息,我們仍然會保留它,因為它是一個可用的數據庫,並且某些來源可能在未來的某個時候具有 url 連接。

所需的 O/P 列表:[{A,abc-url,Y}, {B,xyz-url,Y}, {C,Y},{D,Y}]

任何人都可以建議使用 java 8 方式(使用流)來執行此操作嗎?

這樣做的老派方式:

Map<String, Record> map = new HashMap<>();

        for (Record record: recordList) {
            String dbName = record.getDBName();
            String isActiveYN = record.getIsActiveYN();
            if (map.containsKey(dbName)) {
                if(record.getConnURL() != null)
                  map.replace(dbName, record);
            } else {
                map.put(dbName, record);
            }
        }

List<Record> merged = new ArrayList<>(map.values());

它可以通過實現幾個merge函數來實現:

  1. 將兩個Record實例合並為一個
  2. 將兩個String實例合並為一個
  3. 覆蓋toString方法以提供所需的輸出
  4. 修復isActiveN設置:如果需要合並,則設置為Y
// using Lombok annotations for brevity
@Data
@AllArgsConstructor
@EqualsAndHashCode
class Record {
    String dbName;
    String connUrl;
    String isActiveYN;

    Record merge(Record other) {
        if (this.dbName.equals(other.dbName)) {
            this.connUrl = merge(this.connUrl, other.connUrl);
            this.isActiveYN = "Y"; // if merge called, there are at least two entries
        }
        return this;
    }

    static String merge(String thiss, String thats) {
        return thiss == null ^ thats == null ? (thiss == null ? thats : thiss) : thiss;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        String sep = "";
        if (null != dbName) {
            sb.append(dbName);
            sep = ", ";
        }
        if (null != connUrl) {
            sb.append(sep).append(connUrl);
            sep = ", ";
        }
        if (null != isActiveYN) {
            sb.append(sep).append(isActiveYN);
        }
        sb.insert(0, '{');
        sb.append('}');
        return sb.toString();
    }
}

然后可以像使用Collectors.toMap器一樣簡單地合並記錄,並將對Record::merge引用作為第三個參數傳遞:

// Source Alpha
List<Record> connRecords = new ArrayList<>(Arrays.asList(
        new Record("A", null, "N"),
        new Record("B", null, "Y"),
        new Record("C", null, null),
        new Record("D", null, "N")
));

// Source Beta
connRecords.addAll(Arrays.asList(
        new Record("A", "abc-url", null),
        new Record("B", "xyz-url", "N")
));

// Source Gamma
connRecords.addAll(Arrays.asList(
        new Record("A", null, "N"),
        new Record("C", null, "N")
));

List<Record> merged = new ArrayList<>(
        connRecords.stream()
                   .collect(Collectors.toMap(Record::getDbName, rec -> rec, Record::merge))
                   .values()
);
System.out.println(merged);

輸出:

[{A, abc-url, Y}, {B, xyz-url, Y}, {C, Y}, {D, N}]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM