如何在现有键的哈希图中添加唯一值
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>
。
我不确定您是否需要全局声明 times
和 newTimes
列表。对于 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
,自然顺序将递增)。
我正在尝试构建一个程序,我将 运行 次添加到特定位置。然后我将位置和时间存储在哈希图中。当我得到 运行 时间,我将它添加到一个 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>
。
我不确定您是否需要全局声明 times
和 newTimes
列表。对于 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
,自然顺序将递增)。