【发布时间】:2019-01-03 04:33:46
【问题描述】:
我有一个 LinkedHashSet 对象(每个对象有 3 个实例变量),我需要对每个对象进行操作并处理字段。我怎样才能遍历它?我的猜测是我需要使用 Iterator,但我不知道该怎么做。
【问题讨论】:
-
看看来自tutorial的“遍历集合”。
我有一个 LinkedHashSet 对象(每个对象有 3 个实例变量),我需要对每个对象进行操作并处理字段。我怎样才能遍历它?我的猜测是我需要使用 Iterator,但我不知道该怎么做。
【问题讨论】:
目前有 3 种主要方法可以遍历集合,但是该类必须实现 java.lan.Iterable 接口。如果是这样,我们可以这样做:
for-each循环:假设一组Set<Object> set = new LinkedHashSet<>(); 填充了随机对象并且我们想要打印,那么我们可以使用 for-each 循环:
for ( Object o : set )
{
// o is the reference to the currently selected object
System.out.println(o);
processObject( o );
}
此循环将依次选择集合中的每个对象并按照正文中的定义对其进行处理。这个特定的循环将它打印到标准输出流,然后将对象传递给processObject(Object o) 方法。由于这只是一个示例,该方法除了再次打印该值之外什么也不做。由于此循环按顺序执行,因此在“选择”下一个对象之前,每个对象都会被完全处理。
for-each 循环的一个主要缺点是我们无法在迭代期间安全地从集合中删除任何项目。
错误示例:
// Doing so will lead to a ConcurrentModificationException being thrown
for ( Object o : set )
{
set.remove( o );
}
但是 for-each 循环可以用另一种方式表示。
安静类似于Suryakant Bhartis 答案我们这次在此示例中使用java.util.Iterator:
// Utilizing the iterator provided by Set#iterator()
for ( Iterator<Object> iter = set.iterator(); iter.hasNext(); /* empty*/ )
{
// Iterator#next() returns the next object in line.
Object o = iter.next();
System.out.println( o );
processObject( o );
}
迭代器在 for 循环中直接声明和初始化,整体结构与“正常”循环 (for(int i = 0; i < n;i++){}) 非常相似,但在循环之后我们没有任何要增加的内容,因此第三部分保持为空。这是因为迭代器有一个内部计数器和指向下一个对象的指针,它通过调用iterator#next() 自动递增。但是,当多个操作需要同一个对象时,我们必须首先将其存储在局部变量中,因为随后对 Iterator#next() 的调用将导致不同的结果,或者如果集合中没有更多元素,则会导致 NoSuchElementException。
假设我们只是想将我们的集合对象传递给 processObject 方法,那么样板代码将归结为:
for ( Iterator<Object> iter = set.iterator(); iter.hasNext(); )
{
processObject( iter.next() );
}
迭代器的一个主要好处是,如果我们不再需要/不希望它们在我们的集合中,我们可以从集合中删除它们如果使用的迭代器支持它,否则抛出UnsupportedOperationException .
那么让我们来看看如何移除该项目。为此,我们假设我们的集合仅包含整数值,因此迭代器返回整数值:
for ( Iterator<Integer> iter = set.iterator(); iter.hasNext(); )
{
// if the returned vlaue equals 3...
if ( iter.next().intValue() == 3 )
{
// ... we remove it from the set
iter.remove();
}
}
请注意,此操作将删除迭代器的返回对象,而不是下一个。
从 Java 8(JDK 1.8 或更高版本)开始,我们能够在集合 API 的任何类上调用流,这些类遍历整个内容并能够评估所需的任何内容。让我们快速浏览一些可能的操作:
// Invoke the stream and then print every object to the standard output stream
set.stream().forEach( System.out::println );
// A 'shortcut' for the above
set.forEach( Test::processObject );
// Safely removing objects from the set. (Also a 'shortcut').
set.removeIf( i -> i.intValue() == 3 );
但是,由于大多数迭代都被混淆了,因此这些有点复杂。因此建议按照this 之类的教程来完全理解上述内容。 也不建议初学者使用。
【讨论】:
理解概念的简单示例解决方案。 希望对你有帮助...
LinkedHashSet<String> lhs = new LinkedHashSet<String>();
//Adding elements to HashSet
lhs.add("first");
lhs.add("second");
lhs.add("third");
Iterator<String> itr = lhs.iterator();
//Traversing or Iterating
while(itr.hasNext()){
System.out.println(itr.next());
}
【讨论】:
我肯定会开始引用这条评论https://stackoverflow.com/a/51534527/4149078。
但我也可以建议使用 Java8 流实现。
public static void main(String[] argv) {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("First");
set.add("Second");
set.add("Third");
set.stream().forEach(s -> {
// Do your staff here
System.out.println(s);
});
set.stream().map(s -> s.concat(" additional string")).forEach(s -> System.out.println(s));
// Etc.
}
阅读更多关于流点击的信息this link
【讨论】: