我正在尝试构建一个程序,我将运行时间添加到特定位置。然后我将位置和时间存储在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);
}
答案 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>
。
我不确定您是否需要全局声明times
和newTimes
列表。对于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.sort
或TreeSet
等排序集合的订单可以使用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);
}
}