合并两个具有Java通用键的列表

时间:2019-01-04 15:40:04

标签: java json

我从AS400查询中获得一个列表,而从SQL Server查询中获得另一个列表。我需要将这两个列表合并为一个列表。第一个列表是我们库存中的每个资产,看起来像这样:

[
    {
        "assetId": 0,
        "type": "OV",
        "truckNumber": "L122",
        "longitude": 0,
        "latitude": 0,
        "id": 0
    },
    {
        "assetId": 0,
        "type": "PO",
        "truckNumber": "SQ46",
        "longitude": 0,
        "latitude": 0,
        "id": 0
    }
]

第二个列表更详细,看起来像这样,两个列表都有一个共同的字段,即truckNumber:

[
   {
        "trailerGroup": "C",
        "assetId": 308,
        "loaded": false,
        "dedicated": false,
        "intermodal": false,
        "sealed": false,
        "truckNumber": "L122",
        "companyOwned": true,
        "onSite": false,
        "customerId": "KTPH",
        "id": 308,
        "modified": {
            "when": 1546498401156
        },
        "created": {
            "when": 1546498401156
        }
    },
    {
        "trailerGroup": "C",
        "assetId": 309,
        "loaded": false,
        "dedicated": false,
        "intermodal": false,
        "sealed": false,
        "truckNumber": "SQ46",
        "companyOwned": true,
        "onSite": true,
        "customerId": "KTPH",
        "id": 309,
        "modified": {
            "when": 1546498401156
        },
        "created": {
            "when": 1546498401156
        }
    }
]

我需要更新所有现有值(例如经度),同时添加第一个查询中没有的值。

我尝试了一些合并示例,但是根本没有任何作用,或者只是将第一个列表追加到第二个列表中。


可能的解决方案:

有人看到这个问题吗?

List<Trailer> trailers = null;
List<Trailer> trailersAS400 = null;
List<Trailer> trailersSQLServer = null;

try {
    trailersAS400 = getTrailerAS400Proxy().getTrailers();
    trailersSQLServer = getTrailerSQLServerProxy().getTrailers();           

    Map<String, Trailer> map = new HashMap<>();
    for (Trailer t : trailersAS400) {
        map.put(t.getNumber(), t);
    }
    for (Trailer t : trailersSQLServer) {
        String key = t.getNumber();
        if (map.containsKey(key)) {
            map.get(key).setNumber(t.getNumber());
        } else {
            map.put(key, t);
        }
    }
    trailers = new ArrayList<>(map.values());

}

2 个答案:

答案 0 :(得分:0)

请尝试以下示例。我相信这可以满足您合并两个列表,更新任何现有值并最终添加第一个查询中未包含的任何值的要求。

此外,我考虑到您正在使用Java Runtime Environment 7(JRE 1.7)。

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class App {

    private static String path1 = "C:\\path\\to\\AS400.json";
    private static String path2 = "C:\\path\\to\\SQL_Server_query.json";

    public static void main( String[] args ) {
        JSONArray trailersAS400 = null;
        JSONArray trailersSQLServer = null;
        try {
            FileReader fr = new FileReader(path1);
            FileReader fr2 = new FileReader(path2);
            // utilize simple json parser to parse json objects
            trailersAS400 = (JSONArray) new JSONParser().parse(fr);
            trailersSQLServer = (JSONArray) new JSONParser().parse(fr2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }

        List<Object> list = new ArrayList<Object>(); // store parsed JSON's data in a list
        for (Object trSQL : trailersAS400) {
            list.add(trSQL);
        }
        for (Object tr400 : trailersSQLServer) {
            list.add(tr400);
        }

        HashMap<String, Object> map1 = new HashMap<String, Object>(); // maps truck L122 key value pairs
        HashMap<String, Object> map2 = new HashMap<String, Object>(); // maps truck SQ46 key value pairs
        for (Iterator iter = list.iterator(); iter.hasNext();) { // iterate through list and update map1 with key value pair.
            HashMap<String, Object> truck = (HashMap<String, Object>) iter.next();
            if (truck.containsValue("L122")) {
                Set<Entry<String, Object>> s = truck.entrySet();
                for (Entry<String, Object> entry : s) {
                    map1.put(entry.getKey(), entry.getValue());
                }
            } else if (truck.containsValue("SQ46")) { // iterate through list and update map2 with key value pair.
                Set<Entry<String, Object>> s = truck.entrySet();
                for (Entry<String, Object> entry : s) {
                    map2.put(entry.getKey(), entry.getValue());
                }
            }
        }
        // Update map with map1 & map2. Note the key is represented as the truck number.
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("L122", map1);
        map.put("SQ46", map2);
        Gson pp = new GsonBuilder().setPrettyPrinting().create();
        String p = pp.toJson(map);
        System.out.println(p);
    }
}

输出:

{
  "L122": {
    "truckNumber": "L122",
    "dedicated": false,
    "sealed": false,
    "created": {
      "when": 1546498401156
    },
    "latitude": 0,
    "type": "OV",
    "loaded": false,
    "intermodal": false,
    "companyOwned": true,
    "assetId": 308,
    "customerId": "KTPH",
    "onSite": false,
    "modified": {
      "when": 1546498401156
    },
    "trailerGroup": "C",
    "id": 308,
    "longitude": 0
  },
  "SQ46": {
    "truckNumber": "SQ46",
    "dedicated": false,
    "sealed": false,
    "created": {
      "when": 1546498401156
    },
    "latitude": 0,
    "type": "PO",
    "loaded": false,
    "intermodal": false,
    "companyOwned": true,
    "assetId": 309,
    "customerId": "KTPH",
    "onSite": true,
    "modified": {
      "when": 1546498401156
    },
    "trailerGroup": "C",
    "id": 309,
    "longitude": 0
  }
}

出于性能目的。您可以考虑使用LinkedHashMap与HashMap,就像上面的示例一样。使用LinkedHashMap时,迭代效率更高。下面的示例使用这种方法。

public class App {

private static String path1 = "C:\\path\\to\\AS400.json";
private static String path2 = "C:\\path\\to\\SQL_Server_query.json";


    public static void main( String[] args ) {
        JSONArray trailersAS400 = null;
        JSONArray trailersSQLServer = null;
        try {
            FileReader fr = new FileReader(path1);
            FileReader fr2 = new FileReader(path2);
            // utilize simple json parser to parse json objects
            trailersAS400 = (JSONArray) new JSONParser().parse(fr);
            trailersSQLServer = (JSONArray) new JSONParser().parse(fr2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }

        List<Object> list = new ArrayList<Object>(); // store parsed JSON's data in a list
        for (Object trSQL : trailersAS400) {
            list.add(trSQL);
        }
        for (Object tr400 : trailersSQLServer) {
            list.add(tr400);
        }

        HashMap<String, Object> map1 = new HashMap<String, Object>(); // maps truck L122 key value pairs
        HashMap<String, Object> map2 = new HashMap<String, Object>(); // maps truck SQ46 key value pairs
        Iterator<Object> iter = list.iterator();
        while (iter.hasNext()) { // iterate through list and update map1 with key value pair.
            LinkedHashMap<String, Object> truck = new LinkedHashMap<String, Object>(); 
            truck.putAll((Map<? extends String, ? extends Object>) iter.next());
            if (truck.containsValue("L122")) {
                Set<Entry<String, Object>> s = truck.entrySet();
                for (Entry<String, Object> entry : s) {
                    map1.put(entry.getKey(), entry.getValue());
                }
            } else if (truck.containsValue("SQ46")) { // iterate through list and update map2 with key value pair.
                Set<Entry<String, Object>> s = truck.entrySet();
                for (Entry<String, Object> entry : s) {
                    map2.put(entry.getKey(), entry.getValue());
                }
            }
        }
        // Update map with map1 & map2. Note the key is represented as the truck number.
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("L122", map1);
        map.put("SQ46", map2);
        Gson pp = new GsonBuilder().setPrettyPrinting().create();
        String p = pp.toJson(map);
        System.out.println(p);
    }
}

两个示例代码都将产生上述输出中指示的所需结果。

答案 1 :(得分:0)

如果您使用的是Jackson(最受欢迎的JSON库之一),则可以按照以下步骤简单地实现此目标:

代码段

ObjectMapper mepper = new ObjectMapper();
List<Map<String, Object>> listAs400 = mepper.readValue(jsonStrAs400, List.class);
List<Map<String, Object>> listSqlServer = mepper.readValue(jsonStrSqlServer, List.class);
listAs400.forEach(e1 -> {
    listSqlServer.forEach(e2 -> {
        if (e1.get("truckNumber").toString().equals(e2.get("truckNumber").toString())) {
            e2.forEach((k, v) -> {
                e1.put(k, v);
            });
        }
    });
});
System.out.println(mapper.writeValueAsString(listAs400));

控制台输出

[ 
  { 
    "assetId":308,
    "type":"OV",
    "truckNumber":"L122",
    "longitude":0,
    "latitude":0,
    "id":308,
    "trailerGroup":"C",
    "loaded":false,
    "dedicated":false,
    "intermodal":false,
    "sealed":false,
    "companyOwned":true,
    "onSite":false,
    "customerId":"KTPH",
    "modified":{ 
      "when":1546498401156
    },
    "created":{ 
      "when":1546498401156
    }
  },
  { 
    "assetId":309,
    "type":"PO",
    "truckNumber":"SQ46",
    "longitude":0,
    "latitude":0,
    "id":309,
    "trailerGroup":"C",
    "loaded":false,
    "dedicated":false,
    "intermodal":false,
    "sealed":false,
    "companyOwned":true,
    "onSite":true,
    "customerId":"KTPH",
    "modified":{ 
      "when":1546498401156
    },
    "created":{ 
      "when":1546498401156
    }
  }
]