2017-01-12 10 views
5

によってオブジェクトを含む二つのリストをマージ:のJava 8:私は二つのリストを持っているキー

List<Server> servers1 = new ArrayList<>(); 
Server s1 = new Server("MyServer"); 
s1.setAttribute1("Attribute1"); 
servers1.add(s1); 

List<Server> servers2 = new ArrayList<>(); 
Server s2 = new Server("MyServer"); 
s2.setAttribute2("Attribute2"); 
servers2.add(s2); 

servers1nameattribute1(ただしattribute2)とサーバーが含まれます。
servers2には、nameattribute2(ただし、attribute1はありません)のサーバーが含まれています。

public class Server { 
    private String name; 
    private String attribute1; 
    private String attribute2; 

    public Server(String name) { 
     this.name = name; 
     this.attribute1 = ""; 
     this.attribute2 = ""; 
    } 

    //Getters & Setters 

} 

誰もが、私は(nameによる)一度だけ 各Serverを含む1つのリストにはなく、両方の属性を持つこれら二つのリストをマージすることができます方法を知っていますか?

1つまたは他のリストにのみ存在するサーバーがあります。 最終的なリストにはすべてのサーバーが含まれている必要があります。

サーバ[名前= myServer2を、attribute1の= Attribute1.2、attribute2の=]、

[サーバー[名前= MyServerを、attribute1の= ATTRIBUTE1、attribute2の= attribute2の]:

List<Server> servers1 = new ArrayList<>(); 
    Server s1 = new Server("MyServer"); 
    s1.setAttribute1("Attribute1"); 

    Server s2 = new Server("MyServer2"); 
    s2.setAttribute1("Attribute1.2"); 

    servers1.add(s1); 
    servers1.add(s2); 

    List<Server> servers2 = new ArrayList<>(); 
    Server s3 = new Server("MyServer"); 
    s3.setAttribute2("Attribute2"); 

    Server s4 = new Server("MyServer3"); 
    s4.setAttribute2("Attribute2.2"); 

    servers2.add(s3); 
    servers2.add(s4); 

をもたらすはずです]

サーバー[名前= MyServer3、attribute1の=、attribute2の= Attribute2.2]]

// SOLUTION(THX助けを皆)

Map<String, Server> serverMap1 = Stream.concat(servers1.stream(), servers2.stream()) 
      .collect(Collectors.toMap(Server::getName, Function.identity(), 
      (server1, server2) -> { 
       server1.setAttribute2(server2.getAttribute2()); 
       return server1; 
      })); 
+0

はservers1' 'からServer''へ 'name'のマップを作成し、名前でマップ内のサーバーを検索' servers2'から欠落している 'attribute2'を埋めます。あなた自身でいくつかのコードを書くようにしてください。 – lexicore

+0

これが 'Server'クラスの全体である場合、' List'のエンティティは 'name'、' attribute1'または 'attribute2'の値をどのように持っていますか?これがクラス全体でない場合は、コンストラクタを含めてください – CraigR8806

+0

2つのリストには常にマージされない同じサーバまたは存在するサーバが含まれていますか? –

答えて

2

それをマッピングし、マージする各リストを変換する(私は定型的なコードを記述しないためにロンボクを使用):!

@Data 
@NoArgsConstructor 
@AllArgsConstructor 
class Server { 
    private String name; 
    private String attribute1; 
    private String attribute2; 
} 

public class ServerMain { 

    public static void main(String[] args) { 

     List<Server> servers1 = Arrays.asList(
       new Server("name1", "attr1.1", null), 
       new Server("name2", "attr1.2", null)); 

     List<Server> servers2 = Arrays.asList(
       new Server("name1", null, "attr2.1"), 
       new Server("name2", null, "attr2.2")); 

     Map<String, Server> serverMap1 = servers1.stream().collect(Collectors.toMap(Server::getName, Function.identity())); 
     Map<String, Server> serverMap2 = servers2.stream().collect(Collectors.toMap(Server::getName, Function.identity())); 

     serverMap1.keySet().forEach(key -> serverMap1.merge(key, 
       serverMap2.get(key), 
       (server1, server2) -> { 
        server1.setAttribute2(server2.getAttribute2()); 
        return server1; 
       })); 


     System.out.println(serverMap1); 
    } 
} 
+0

これはLombokが行っていることだと思います。 – CraigR8806

+1

あなたはあまりにも多くの作業を行い、2つのマップを収集して、各サーバーに対して2つのマップ参照を行います。あなたは 'serverMap2'を完全に削除して' servers2.forEach(s - > serverMap1.merge(s。前のものと同じマージ関数* /)); – Holger

+4

キーが一意であると確信しているならば、単一のストリーム操作でもそれを行うことができます: 'serverMap1 = Stream.concat(servers1 (サーバ:: getName、Function.identity()、/ *以前と同じマージ関数* /)); ' – Holger

0

各サーバーに対してサーバー1ではservers2に一致するSERVER2を見つけます名前で一致するサーバがない場合はnullを返すだけで、属性を訂正するために最初の属性の欠落した属性を設定します。また、この実装では、servers1に含まれるサーバ名のリストだけが返されることにも注意してください。

@AllArgsConstructor 
@Data 
private class Server { 
    private String name; 
    private String attribute1; 
    private String attribute2; 
} 

List<Server> completServersInfo = servers1.stream() 
    .map((server1 -> { 
     Server matchingServer = servers2.stream() 
      .filter(server2 -> server2.name.equals(server1.name)) 
      .findFirst() 
      .orElse(null); 
     server1.setAttribute2(matchingServer.attribute2); 
     return server1; 
    })) 
    .collect(Collectors.toList()); 
+0

両方のリストに同じキーがあると確信している場合 Map serverMap1 = servers1.stream()。collect(Collectors.toMap(Server :: getName、Function.identity())); servers2 .forEach(key-> serverMap1.get(key.getName())。setAttribute2(key.getAttribute2())); System.out.println(serverMap1); –

+0

両方のリストに同じキーが存在する必要はありません。 もしそうでなければ、サーバは最後のリストにそのまま現れなければなりません。 – Nibor

0

多分あなたは地図を使ってそれを行うことができますか?マップのキーはサーバーの名前で、マップの値はオブジェクトServerです。

Map<String, Server> map = new HashMap<>(); 
for (Server s : servers1) { 
    map.put(s.getName(), s); 
} 
for (Server s : servers2) { 
    String key = s.getName(); 
    if (map.containsKey(key)) { 
     map.get(key).setAttribute2(s.getAttribute2()); 
    } else { 
     map.put(key, s); 
    } 
} 
List<Server> servers = new ArrayList<>(map.values()); // or other impl. 
関連する問題