如何在现有密钥的Hashmap中添加唯一值

时间:2015-02-18 23:04:40

标签: java linked-list hashmap

我正在尝试构建一个程序,我将运行时间添加到特定位置。然后我将位置和时间存储在hashmap中。当我得到运行时间时,我将它添加到LinkedList,然后尝试将新更新的LinkedList放在hashmap的Key值上。但是,一旦我搬到新的位置,运行时间就不会停留在他们设计的位置,所以所有位置最终都有相同的运行时间。我不太确定我做错了什么。谢谢你的帮助。

示例数据: 位置A:45秒,43秒,36秒 位置B:51秒,39秒

输出不正确: 位置A:39秒,51秒 位置B:39秒,51秒

正确输出: 位置A:36秒,43秒,45秒 位置B:39秒,51秒

    HashMap h = new HashMap();
    LinkedList times = new LinkedList();
    LinkedList newTimes = new LinkedList();


public static void addInformation(HashMap h, LinkedList times, LinkedList    
newTimes) {

   String location = scanner.next();
   Double time = scanner.nextDouble();

   if (h.containsKey(location)){
        for (int i = 0; i < newTimes.size(); i++){
            times.add(newTimes.get(i));
        }
        times.add(time);
        getFastTime(times);
        h.get(location).add(location, times); // cannot resolve add method 
    }else{
        newTimes.clear();
        newTimes.add(time);
        getFastTime(newTimes);
        h.put(location, newTimes);
    }
}
public static void printInformation(HashMap h) {
    Set keySet = h.keySet();  
    for ( Object locationName : keySet) {
        //Use the key to get each value. Repeat for each key.
        System.out.println("Location =" + locationName + " Time =" + 
    h.get(locationName));
    }
}

public static void getFastTime(LinkedList times){
   times.sort(null);
}

3 个答案:

答案 0 :(得分:4)

问题在于Java通过引用传递。您没有为不同的位置创建新列表,因此相同的列表将用于地图中的所有条目。您应该阅读这一点,因为它是Java的一个基本方面。

接下来,您的馆藏应该参数化。你不需要时间和newTimes列表。在地图中也使用List而不是LinkedList。像这样:

HashMap<String, List<Double>> map = new HashMap<>();

在方法定义中也这样做。还有许多其他问题,例如printInformation方法,它假定对象是字符串,甚至没有强制转换它们。输入未经过验证。如果输入格式不正确怎么办?应该考虑这一点。此外,应该更好地命名变量。

这样的东西应该可以使用(未​​经测试。你还需要查看print方法以使其与列表一起使用):

HashMap<String, List<Double>> map = new HashMap<>();

public static void addInformation(HashMap<String, List<Double>> map) {
    //input should be validated here
    String location = scanner.next();
    Double time = scanner.nextDouble();

    List<Double> timesInMap = map.get(location);
    if (timesInMap != null){
        timesInMap.add(time);
        timesInMap.sort(null);
    }else{
        timesInMap = new ArrayList<Double>();
        timesInMap.add(time);
        map.put(location, timesInMap);
    }
}
public static void printInformation(HashMap<String, List<Double>> map) {
    Set<String> keySet = map.keySet();  
    for (String locationName : keySet) {
        //Use the key to get each value. Repeat for each key.
        System.out.println("Location =" + locationName + " Time =" + 
                map.get(locationName));
    }
}

答案 1 :(得分:1)

在Java中,当您传递参数或获取对象时,实际上会在此对象上处理引用。大多数情况下,集合是 mutable (即使您也可以创建不可变的),这意味着您可以在适当的位置修改集合 。 最好使用Generics来支持强类型,这样可以解决add方法无法解决的问题。

E.G。,hashmap应声明为:

HashMap<String, List<Double>> h = new HashMap<>();

在左侧,它只声明了hashmap应包含的内容,但尚未实现List<Double>

我不确定您是否需要全局声明timesnewTimes列表。对于List<Double>中的每个条目,时间值将存储在不同的HashMap<>中。 addInformation函数可以具有以下逻辑:

// Add one (location, time) scanned from input
public static void addInformation(HashMap<String, List<Double> locations,
                                  Scanner scanner) {
   String location = scanner.next();
   Double time = scanner.nextDouble();

   List<Double> times = locations.get(location);
   if (times == null) {
      // this is a new location, create the linkedlist
      // and put it in the hashmap
      times = new LinkedList<Double>();
      locations.put(location, times);
   }
   // add the time to the linkedlist
   times.add(time);
}

在上面的实现中,通过插入来排序时间(首先插入第一个元素)。如果您希望将此时间值始终排序,则可以在每次添加新值(位置,时间)时对列表进行排序,即在times.add(time)之后添加以下行:

Collections.sort(times);

排序会修改列表 - 您可以在java doc Collections.sort中获得更多详细信息。

另一种选择是使用TreeSet<Double>代替LinkedList<Double>。元素将保持排序,但不允许重复时间。

如果您需要保留时间值和已排序集合的重复项,那么您可以使用TreeMultiset来实现此目的。

另请注意,Collection.sortTreeSet等排序集合的订单可以使用Comparator进行控制。例如,您可能希望按减少顺序排列时间(Double的自然顺序会增加)。

答案 2 :(得分:0)

尝试此代码,您的链接列表已全局定义并由所有位置键共享,

HashMap h = new HashMap();
public static void addInformation(HashMap h, LinkedList times, LinkedList    
newTimes) {

   String location = scanner.next();
   Double time = scanner.nextDouble();

   if (h.containsKey(location)){
        LinkedList times = h.get(location);
        times.add(time);
        getFastTime(times);

    }else{
        LinkedList newTimes = new LinkedList();
        newTimes.add(time);
        getFastTime(newTimes);
        h.put(location, newTimes);
    }
}