Java 无法使用提取到字符串的映射键
在应用程序“我有公交车”中,每辆公交车都与多个车站关联,并且在一天的时间内,每辆公交车都有几次到达每个车站的时间Java 无法使用提取到字符串的映射键,java,list,for-loop,hashmap,key,Java,List,For Loop,Hashmap,Key,在应用程序“我有公交车”中,每辆公交车都与多个车站关联,并且在一天的时间内,每辆公交车都有几次到达每个车站的时间 Map<String, Station> stationMap = new HashMap<>(); Map<String, String[]> busTimesForSingleStation = new HashMap<>(); // key is station's name and value would be an arr
Map<String, Station> stationMap = new HashMap<>();
Map<String, String[]> busTimesForSingleStation = new HashMap<>(); // key is station's name and value would be an array of times in string.
List<Station> stationsOfBus = new ArrayList<>();
Map<List<Station>, String[]> allArriveTimes = new HashMap<>();
for (int i = 10; i <= 400; i += 10) {
busTimesForSingleStation = generateTimeForStation(i);
String key;
for (Map.Entry<String, String[]> e : busTimesForSingleStation.entrySet()){
key = e.getKey();
}
allArriveTimes.put(stationsOfBus.add(stationMap.get(key)),
busTimesForSingleStation.get(Integer.toString(i)));
}
Map stationMap=newhashmap();
Map-busTimesForSingleStation=新建HashMap();//键是站点的名称,值是字符串中的时间数组。
List stationsOfBus=new ArrayList();
Map allArriveTimes=newhashmap();
对于(int i=10;i问题是,编译器不知道第二个for循环是否至少运行一次(因为它不可能知道busTimesForSingleStation是否为空)
要解决此问题,只需将String key;
更改为String key=“”;
,这样编译器就知道,即使busTimesForSingleStation为空,也不会有空引用。我同意SimMac对问题的描述,但不同意他建议的解决方法
简单地说String key=“”;
的问题是,然后使用这个值。也许这是可以的,stationMap.get(key)
返回一个安全的“not found”值,但更可能的是它没有返回。比如说它返回null
:现在您正在将null
添加到stationsOfBus
,这可能会在运行时失败(最好的情况——但它可能会在很长一段时间内失败),或者在程序中继续无意义地传播(最坏的情况)
修复编译器捕获的实际问题(映射可能是空的)要比修复隐藏该问题的修复好得多
如果bastimesforsinglestation
不能为空,则断言该事实:
if (!busTimesForSingleStation.isEmpty()) {
String key = ""; // Now you know it will be overwritten.
for (String maybeKey : busTimesForSingleStation.keySet()) {
key = maybeKey;
}
} else {
throw new AssertionError("Should never happen!");
}
或者,如果可以为空,则显式处理:
if (!busTimesForSingleStation.isEmpty()) {
String key = ""; // Now you know it will be overwritten.
for (String maybeKey : busTimesForSingleStation.keySet()) {
key = maybeKey;
}
} else {
// Some logic to handle it correctly.
}
此问题的深层原因是您选择的generateMesforStation
返回类型没有准确地编码您的意图:
- 您的问题是,您希望返回的映射包含一个键/值对
- 您的返回类型表示该方法的调用方应该期望返回零、一个或多个键/值对
显然,“一个k/v对”可以在包含“零个或多个k/v对”的数据结构中表示,但选择这样表示意味着调用代码也必须能够处理“零个”和“多个”情况
例如,如果返回的数据结构确实包含2个或更多的k/v对,并且您想要选择“最后一个”键,那么您就必须担心这些对的迭代顺序。如果类型系统能够保证永远不会发生这种情况,那么处理这种情况的需求将被完全删除
如果您希望只返回一个k/v对,有两个选项要突出显示:
- 代码中最简单的更改是使用而不是
Map
。Map.Entry
只是循环中迭代的结构元素之一
Map.Entry<String, String[]> entry = generateTimesForStation(i);
String key = entry.getKey();
// Do whatever with the key.
无论您选择哪一个,现在都可以避免未初始化的变量和循环,因为再也没有什么可循环的了
如果您想返回零或一个k/v对,上面的两个选项都是有效的,但是您应该将结果包装成一个类似于Optional
的类型,以便强烈指出不存在这样的k/v对的可能性。您可以返回null
来表明这一点,但我不鼓励这样做-请参阅为什么Optional
应该d应该优先于null
(他说的是番石榴Optional
,但Java8Optional
的论点是相同的)
Optional entry=generateTimesForStation(i);
if(entry.isPresent()){
String key=entry.get().getKey();
//用钥匙干什么都行。
}否则{
//处理“未找到”的情况。
}
使用更具体的返回类型的方法也可能有助于实现generateTimesForStation
:一(或零或一)的约束必须返回的值可以帮助您捕获可能导致返回值不满足这些约束的控制流路径。最好显式处理空的大小写。很可能,stationMap.get(“”)
将返回null,因此您只需将易于发现的编译时故障转换为运行时故障(这实际上可能与此代码相去甚远)。谢谢。在更改为String key=“”;
后,我得到了与设置String key=null
时相同的错误。错误是错误的第一个参数类型。发现:'boolean',必需:java.util.List
我不知道编译器为什么将空字符串计算为布尔值。[null]谢谢你的提示。至于选择busTimesForSingleStation
的最后一个键,问题是每次地图中肯定只有一个条目,而我使用作为提取键的原因是我不知道如何以任何其他方式进行。(问题中提到)。无论如何,循环中的key=maybeKey;
使得逻辑仅使用最后一个键?(即,如果bastimesforsinglestation
map中有多个条目,则在数组中保存键将解决此问题?)///尽管应用了您建议的更改,但我仍然收到错误:@Dummy初学者好吧,我没有足够仔细地阅读问题:)由于您选择了类型,我已经发布了整个问题的详细解释。@MohamedBathaoui谢谢。但即使指定了初始值,我仍然有问题:
BusTime entry = generateTimesForStation(i);
String key = entry.getStationName();
// Do whatever with the key - or maybe just refer to
// `entry.getStationName()` directly.
Optional<Map.Entry<String, String[]>> entry = generateTimesForStation(i);
if (entry.isPresent()) {
String key = entry.get().getKey();
// Do whatever with the key.
} else {
// Handle the "not found" case.
}