我是Java的新手,正在尝试学习Enumeration的hasMoreElements()和nextElement()方法.我将一些元素添加到p1列表中,同时从p1列表中删除了其他元素后,我尝试打印所有内容,但是,它没有这样做?为什么会这样?
Properties p1 = new Properties();
try (OutputStream os1 = new FileOutputStream("xanadu123.properties")) {
//set the properties value
p1.setProperty("database", "localhost");
p1.setProperty("1", "one");
p1.setProperty("2", "two");
} catch (IOException e) {
e.printStackTrace();
}
Enumeration<Object> eString1 = p1.elements();
while (eString1.hasMoreElements()) {
System.out.println(eString1.nextElement());
}
System.out.println("after printing eString1");
p1.setProperty("3", "three");
p1.remove("2");
System.out.println("before printing eString1 again");
while (eString1.hasMoreElements()) {
System.out.println(eString1.nextElement());
}
输出:
two
one
localhost
after printing eString1
before printing eString1 again
解决方法:
基本答案是,如果修改了枚举的东西(在本例中为Properties),则不能依赖Enumeration.完成后,您构建的枚举可能不再有效.
较新版本的Enumeration,Iterator,是一样的,除了一些迭代器提供了一个remove方法,允许你从集合中删除“当前元素”而不破坏迭代器. (但是你必须使用Iterator的remove方法;你不能使用任何其他机制来删除元素,否则你可能会破坏迭代器.)
基本原因是Enumeration或Iterator包含有关您枚举的实体的状态信息.如果您修改该实体,则状态信息可能不再有效.例如,假设您正在迭代ArrayList.最有可能的是,迭代器将包含一个整数,它是数组的“当前”索引.如果然后在ArrayList的前面插入一些东西,那个索引指向的元素将成为一个不同的元素,下次在迭代器上调用next时,它将查看该索引处的元素并返回相同的元素它上次返回的元素.在你的情况下,我猜想Enumeration中保存的一条状态信息是一个布尔实例变量,上面写着“我到底还有吗?”到达属性的末尾后,该变量将变为true.如果然后添加更多属性,“枚举结束”变量仍然为真,即使此时它实际上是错误的.
尝试设置枚举器和迭代器是不切实际的,这样只要底层实体发生变化,它们就会自行调整.一个Properties对象(或一个ArrayList或其他)需要跟踪从它创建的每个Enumerator或Iterator,然后找到所有这些并在完成更改属性的任何操作时调整它们;或者每个枚举器或迭代器都需要一种方法来查询属性来询问它,自上次检查以来发生了哪些变化?其中任何一个都会非常复杂.还要考虑Properties是一个哈希表,因此当您添加新元素时,可以将其添加到哈希表中的任何桶中.如果枚举器已经扫描过该存储桶,那么在添加新元素后,如何知道返回并再次扫描它?我认为,可以编写以这种方式工作的枚举器,但这将是非常低效,混乱和复杂的.