使用 Enumeration<E> 的 hasMoreElements() 和 nextElement() 方法打印列表,第一次成功,添加一些元素后第二次失败
using Enumeration<E> 's hasMoreElements() and nextElement() method to print a list, succeeded 1st time, failed 2nd time after adding some element
我是 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
这里有两点需要注意:
elements()
从属性创建枚举。一旦创建,它就与属性本身断开连接。那的意思就是后面再加一个属性就不会加到枚举中了
- 枚举是一个'one time'对象,类似于迭代器。这意味着您可以遍历元素一次,之后,每次调用时
hasMoreElements
都会 return false。
考虑到这两个事实,第二次打印什么也没打印是完全合理的
不要忘记在再次使用之前重置您的枚举。
eString1 = p1.elements();
while (eString1.hasMoreElements()) {
System.out.println(eString1.nextElement());
}
基本答案是,如果您修改要枚举的内容(在本例中为 Properties
),则不能依赖 Enumeration
工作。一旦这样做,您构建的 Enumeration
可能不再有效。
较新版本的 Enumeration
、Iterator
也是如此,除了 some Iterator
s 提供了 remove
方法允许您在不破坏迭代器的情况下从集合中删除 "current element"。 (但是你必须使用 Iterator
的 remove
方法;你不能使用任何其他机制来删除元素,否则你可能会破坏迭代器。)
基本原因是 Enumeration
或 Iterator
包含有关您正在枚举的实体的状态信息。如果您修改该实体,状态信息可能不再有效。例如,假设您正在遍历 ArrayList
。最有可能的是,迭代器将包含一个整数,它是数组的 "current" 索引。如果你随后在 ArrayList
的前面插入一些东西,那个索引指向的元素将变成一个不同的元素,下次你在迭代器上调用 next
时,它会查看该索引处的元素和 return 上次 return 编辑的相同元素。在你的情况下,我猜 Enumeration
中保存的一条状态信息是一个 boolean
实例变量,它说 "Have I reached the end yet?" 一旦你到达 Properties
,该变量将变为 true
。如果您随后添加更多属性,"end-of-the-enumeration" 变量仍然为真,即使此时它实际上是错误的。
尝试设置 Enumerators
和 Iterators
以便它们在底层实体发生变化时自行调整是不切实际的。 Properties
对象(或 ArrayList
或其他对象)需要跟踪从中创建的每个 Enumerator
或 Iterator
,然后找到所有对象并进行调整每当发生改变 Properties
的事情时,他们都会这样做;否则每个 Enumerator
或 Iterator
都需要一种方法来查询 Properties
来询问它,自从我上次检查以来发生了什么变化?其中任何一个都会非常复杂。还要考虑 Properties
是一个散列 table,这样当你添加一个新元素时,你可以将它添加到散列 table 中的任何桶中。如果 Enumerator
已经扫描过那个桶,它怎么知道在添加新元素后返回并再次扫描它?我相信 可以 写出这样的 Enumerator
,但效率会非常低,混乱且复杂。
我是 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
这里有两点需要注意:
elements()
从属性创建枚举。一旦创建,它就与属性本身断开连接。那的意思就是后面再加一个属性就不会加到枚举中了- 枚举是一个'one time'对象,类似于迭代器。这意味着您可以遍历元素一次,之后,每次调用时
hasMoreElements
都会 return false。
考虑到这两个事实,第二次打印什么也没打印是完全合理的
不要忘记在再次使用之前重置您的枚举。
eString1 = p1.elements();
while (eString1.hasMoreElements()) {
System.out.println(eString1.nextElement());
}
基本答案是,如果您修改要枚举的内容(在本例中为 Properties
),则不能依赖 Enumeration
工作。一旦这样做,您构建的 Enumeration
可能不再有效。
较新版本的 Enumeration
、Iterator
也是如此,除了 some Iterator
s 提供了 remove
方法允许您在不破坏迭代器的情况下从集合中删除 "current element"。 (但是你必须使用 Iterator
的 remove
方法;你不能使用任何其他机制来删除元素,否则你可能会破坏迭代器。)
基本原因是 Enumeration
或 Iterator
包含有关您正在枚举的实体的状态信息。如果您修改该实体,状态信息可能不再有效。例如,假设您正在遍历 ArrayList
。最有可能的是,迭代器将包含一个整数,它是数组的 "current" 索引。如果你随后在 ArrayList
的前面插入一些东西,那个索引指向的元素将变成一个不同的元素,下次你在迭代器上调用 next
时,它会查看该索引处的元素和 return 上次 return 编辑的相同元素。在你的情况下,我猜 Enumeration
中保存的一条状态信息是一个 boolean
实例变量,它说 "Have I reached the end yet?" 一旦你到达 Properties
,该变量将变为 true
。如果您随后添加更多属性,"end-of-the-enumeration" 变量仍然为真,即使此时它实际上是错误的。
尝试设置 Enumerators
和 Iterators
以便它们在底层实体发生变化时自行调整是不切实际的。 Properties
对象(或 ArrayList
或其他对象)需要跟踪从中创建的每个 Enumerator
或 Iterator
,然后找到所有对象并进行调整每当发生改变 Properties
的事情时,他们都会这样做;否则每个 Enumerator
或 Iterator
都需要一种方法来查询 Properties
来询问它,自从我上次检查以来发生了什么变化?其中任何一个都会非常复杂。还要考虑 Properties
是一个散列 table,这样当你添加一个新元素时,你可以将它添加到散列 table 中的任何桶中。如果 Enumerator
已经扫描过那个桶,它怎么知道在添加新元素后返回并再次扫描它?我相信 可以 写出这样的 Enumerator
,但效率会非常低,混乱且复杂。