如何比较列表中的元素与Java中的地图元素?

时间:2016-03-28 09:54:56

标签: java list collections

我有以下代码(带有一些示例数据),并希望检查是否有更好或更高效的方法来比较地图列表中的每个元素与后续的元素:

import java.util.*;

public class CompareElements {

private static List<Map<String, String>> sample = new ArrayList<>(0);
private static int MIN = 0;
private static int MAX = 10;

static {
    populateListOfMaps();
}

/*
* This is the main part of the question, rest is just to generate test data..
*/
public static void main(String[] args){
    // Can we simplify this part using lambda's or any library?
    for (int i = 0; i < sample.size() -1; i++) {
        for (int j = i+1; j < sample.size(); j++) {
            Map<String, String> referenceMap = sample.get(i);
            Map<String, String> candideMap = sample.get(j);
            if(referenceMap.get("key").equalsIgnoreCase(candideMap.get("key"))){
                System.out.println("Equal : " + i + " || "  + referenceMap.get("key") + " and "+ j + " || " + candideMap.get("key") + " are pairs");
            } else {
                System.out.println("Not equal : " + i + " || "  + referenceMap.get("key") + " and "+ j + " || " + candideMap.get("key") + " are pairs");
            }
        }
    }   
}

private static void populateListOfMaps(){
    if(sample.size() <= 10){
        Map<String, String> someMap = new HashMap<>(0);
        someMap.put("key", "value" + randInt(MIN, MAX));
        sample.add(someMap);
        populateListOfMaps();
    } 
}

public static int randInt(int min, int max) {
    Random rand = new Random();
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}

}

我的要求是比较地图列表中的每个元素,然后检查相等性以删除重复,这是一个更简单的部分,但我的实时应用程序中的每个地图都有2个键值(但两者都是字符串..没有自定义POJO对象。)

上面的代码有效但我希望这个代码更加简洁和高效。

我们可以使用lambdas或溪流吗?

2 个答案:

答案 0 :(得分:0)

当您从MongoDB获取数据时,我假设您无法控制架构,因此使用POJO并不是一个简单的选择。 (它可以用生成的代码完成,但你可能不想去那里)

您可以做的是使用groupingBy将此O(n^2)循环更改为O(n)

public static void main(String... args) {
    List<Map<String, String>> sample = populateListOfMaps();
    sample.stream()
            .collect(Collectors.groupingBy(m -> m.get("key")))
            .forEach((key, list) -> System.out.println(key + " : " + list));
}

private static List<Map<String, String>> populateListOfMaps() {
    Random rand = new Random();
    return IntStream.range(0, 10)
            .mapToObj(i -> {
                Map<String, String> someMap = new HashMap<>(2);
                someMap.put("key", "value-" + rand.nextInt(10));
                return someMap;
            })
            .collect(Collectors.toList());
}

这将打印具有O(n)时间复杂度的相同“键”值的所有条目。 e.g。

value-9 : [{key=value-9}]
value-8 : [{key=value-8}, {key=value-8}, {key=value-8}]
value-5 : [{key=value-5}]
value-7 : [{key=value-7}, {key=value-7}]
value-1 : [{key=value-1}]
value-0 : [{key=value-0}]
value-2 : [{key=value-2}]

答案 1 :(得分:0)

我不确定您的具体要求是什么,以便一次解决您的问题:

  

检查是否有更好或更高效的方法将地图列表的每个元素与后续元素进行比较:

如何使用keySet?

Set<String> s1 = new HashSet< String >(referenceMap.values());
Set<String> s2 = new HashSet< String >(candideMap.values());

// Get intersection of values
s1.retainAll(s2);

// You can also get corresponding keys for each value later

这会降低您从O(n^2)O(n)

的复杂程度
  

我实时应用程序中的每个映射都有2个键值(但都是String ..没有自定义POJO对象)。

不确定你的实时意思。地图是否实时变化?你的解决方案和我的解决方案都不是线程安全的。

你的意思是每个条目有2个键值吗?如果您指的是每个键的2个值,则可能会覆盖hashcode()equals()并且您的代码应该有效。

如果我误解了你的问题,请告诉我