如何将两个地图合并为一个并保持重复值

时间:2015-06-24 12:21:34

标签: java list arraylist merge hashmap

我有两个哈希映射“map0 and map1”,它们都包含Point类型的键和类型Double的值,如下所示。

我确信该密钥永远不会重复,但值可能是,我想将“map0 and map1”同时添加到一个Hashmap中,以便 我没有丢失重复的值“我想保留重复的值”。在我在本网站上查看了一些问题之后,我在代码中使用了putAll()方法,如下所示,但问题是,当我将两个地图“map0,map1”合并为一个组合地图时,我丢失了重复的值如下图所示,map0的值为20,map1的值为20!

请让我知道如何将两张地图合并为一张而不会丢失重复值

代码

public static void main(String[] args) {

    HashMap<Point, Double> map0 = new HashMap<Point, Double>();
    HashMap<Point, Double> map1 = new HashMap<Point, Double>();

    map0.put(new Point(32,59), (double) 56);
    map0.put(new Point(398,3), (double) 20);
    map0.put(new Point(3,3), (double) 209);

    map1.put(new Point(32,596), (double) 561);
    map1.put(new Point(396,311), (double) 20);
    map1.put(new Point(35,34), (double) 2099);

    System.out.println("map0.size:"+map0.size());
    System.out.println("map1.size:"+map1.size());

    HashMap<Point, Double> combine = new HashMap<Point, Double>();

    combine.putAll(map0);
    combine.putAll(map1);
    ValueComparator vc = new ValueComparator(combine);
    TreeMap<Point, Double> tree= new TreeMap<Point, Double>(vc);

    tree.putAll(combine);
    System.out.println("tree.size:"+tree.size());
    System.out.println("tree_sorted:"+tree);

}

static class ValueComparator implements Comparator<Point> {

    private HashMap<Point, Double> map = null;

    public ValueComparator(HashMap<Point, Double> map) {
        // TODO Auto-generated constructor stub
        this.map = map;
    }

    public int compare(Point arg0, Point arg1) {
        // TODO Auto-generated method stub

        return Double.compare(this.map.get(arg0), this.map.get(arg1));
        /*
        if (this.map.get(arg0) >= this.map.get(arg1)) {
            return 1;
        } else {
            return -1;
        }
        */
    }
}

输出

map0.size:3
map1.size:3
tree.size:5
tree_sorted:{{398.0, 3.0}=20.0, {32.0, 59.0}=56.0, {3.0, 3.0}=209.0, {32.0, 596.0}=561.0, {35.0, 34.0}=2099.0}

2 个答案:

答案 0 :(得分:1)

您定义键的比较条件(Point)是相关值(Double),因此值为20的两个点与您的比较器相同。

如果要保留重复项,请更改比较器(即您的相等定义)或使用不同的数据结构,因为地图不允许重复键。

答案 1 :(得分:1)

从给定比较器的角度来看,TreeMap中不能有两个“相等”的对象。它在javadoc中明确说明:

  

这是因为Map接口是根据equals操作定义的,但是有序映射使用compareTo(或compare)方法执行所有键比较,因此通过此方法认为相同的两个键是有序地图的立场,相等。

问题中未说明您对排序集合的进一步使用,因此我认为排序List对您来说已经足够了。我还建议扩展Point类以将值与其关联。它更适合这种用途。

你的比较器也没有以正确的方式实施。它不应该有外部地图参考。

请考虑以下代码:

public class Example {

public static class ValuedPoint extends Point {
  private double value;

  public ValuedPoint(double x, double y, double value) {
    super(x, y);
    this.value = value;
  }

  public double getValue() {
    return value;
  }

  public String toString() {
    return "{" + x + ", " + y + ", " + value + "}";
  }
}

private static class ValueComparator implements Comparator<ValuedPoint> {

  public int compare(ValuedPoint arg0, ValuedPoint arg1) {
    return Double.compare(arg0.getValue(), arg1.getValue());
   }
 }

public static void main(String[] args) {

  Set<ValuedPoint> set0 = new HashSet<ValuedPoint>();
  Set<ValuedPoint> set1 = new HashSet<ValuedPoint>();

  set0.add(new ValuedPoint(32, 59, 56));
  set0.add(new ValuedPoint(398, 3, 20));
  set0.add(new ValuedPoint(3, 3, 209));

  set1.add(new ValuedPoint(32, 596, 561));
  set1.add(new ValuedPoint(396, 311, 20));
  set1.add(new ValuedPoint(35, 34, 2099));

  System.out.println("set0.size:" + set0.size());
  System.out.println("set1.size:" + set1.size());

  Set<ValuedPoint> combined = new HashSet<ValuedPoint>();

  combined.addAll(set0);
  combined.addAll(set1);
  System.out.println("combined size:" + combined.size());

  ValueComparator comparator = new ValueComparator();

  List<ValuedPoint> sortedList = new ArrayList<ValuedPoint>(combined);
  Collections.sort(sortedList, comparator);

  System.out.println("list size:" + sortedList.size());
  System.out.println("sortedList:" + sortedList);
  }
}

输出结果为:

set0.size:3
set1.size:3
combined size:6
list size:6
sortedList:[{398.0, 3.0, 20.0}, {396.0, 311.0, 20.0}, {32.0, 59.0,56.0}, {3.0, 3.0, 209.0}, {32.0, 596.0, 561.0}, {35.0, 34.0, 2099.0}]