如何在现有键的哈希图中添加唯一值

How to add Unique Values to a Hashmap at an Existing Key

我正在尝试构建一个程序,我将 运行 次添加到特定位置。然后我将位置和时间存储在哈希图中。当我得到 运行 时间,我将它添加到一个 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);
}

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

的一个基本方面

接下来,应该对您的集合进行参数化。您不需要 times 和 newTimes 列表。在映射中也使用 List 而不是 LinkedList。像这样:

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

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

像这样的东西应该可以工作(未经测试。您还必须查看打印方法以使其与列表一起工作):

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));
    }
}

试试这个代码,你的链接列表定义为全局并由所有位置键共享,

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);
    }
}

在Java中,当你传递一个参数或者获取一个对象的时候,实际上是在这个对象上处理了一个reference。大多数情况下,集合是 可变的 (即使您也可以创建不可变的),这意味着您可以 就地 修改集合。 最好使用 Generics 来支持强类型,这应该可以解决 add 方法未解决的问题。

例如,hashmap 应声明为:

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

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

我不确定您是否需要全局声明 timesnewTimes 列表。对于 HashMap<> 中的每个条目,时间值将存储在不同的 List<Double> 中。 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);
}

在上面的实现中,时间是按插入顺序排列的(第一个元素先插入)。如果您希望这个时间值 always 排序,您可以在每次添加新的(位置,时间)时对列表进行排序,即在 times.add(time) 之后添加以下行:

Collections.sort(times);

排序会修改列表 - 您可以在 java 文档 Collections.sort.

中获得更多详细信息

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

如果您需要保留时间值的副本和排序的集合,那么 TreeMultiset 可以做到这一点。

此外,请注意 Collection.sort 或排序集合(如 TreeSet)的顺序可以用 Comparator 控制。例如,您可能希望时间按 递减 顺序排列(对于 Double,自然顺序将递增)。