怎样遍历HashSet效率更高

时间:2022-04-01 16:46:29
怎样遍历HashSet效率更高
现在需要把一个HashSet复制一份再遍历,有2种方法:
1. clone出一个新的HashSet,再用iterator
2. toArray创建一个新数组,再用for循环

感觉上方法2可能会快些。

6 个解决方案

#1


直接clone吧。效率方面我觉得应该不是问题。

#3


看源代码是个好方法。我看了一下clone的实现,是用Iterator遍历源HashSet,把元素逐个插入到新复制的HashSet里。不过toArray的实现没找到,不知道在哪里。

实测了一下,还是方法2比较快,执行时间是N(2-20)倍的关系。可惜执行时间不太稳定,变化比较剧烈。不知道是因为数据太少,还是java执行环境有影响。
目前在HashSet里插入了20000条不重复的记录,执行时间是用函数"System.currentTimeMillis()"统计的。

#4



   public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
        Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
    if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
    r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
    }

hashset的toArray實現

#5



 /**
     * {@inheritDoc}
     *
     * <p>This implementation returns an array containing all the elements
     * returned by this collection's iterator, in the same order, stored in
     * consecutive elements of the array, starting with index {@code 0}.
     * The length of the returned array is equal to the number of elements
     * returned by the iterator, even if the size of this collection changes
     * during iteration, as might happen if the collection permits
     * concurrent modification during iteration.  The {@code size} method is
     * called only as an optimization hint; the correct result is returned
     * even if the iterator returns a different number of elements.
     *
     * <p>This method is equivalent to:
     *
     *  <pre> {@code
     * List<E> list = new ArrayList<E>(size());
     * for (E e : this)
     *     list.add(e);
     * return list.toArray();
     * }</pre>
     */

toArray
public <T> T[] toArray(T[] a)返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。如果指定的数组能容纳该 collection,则返回包含此 collection 元素的数组。否则,将分配一个具有指定数组的运行时类型和此 collection 大小的新数组。 
如果指定的数组能容纳 collection,并有剩余空间(即数组的元素比 collection 的元素多),那么会将数组中紧接 collection 尾部的元素设置为 null。(只有 在调用者知道此 collection 没有包含任何 null 元素时才能用此方法确定 collection 的长度。) 

如果此 collection 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。 

像 Collection.toArray() 方法一样,此方法充当基于数组的 API 与基于 collection 的 API 之间的桥梁。更进一步说,此方法允许对输出数组的运行时类型进行精确控制,并且在某些情况下,可以用来节省分配开销。 

假定 x 是只包含字符串的一个已知 collection。以下代码用来将 collection 转储到一个新分配的 String 数组: 

     String[] y = x.toArray(new String[0]); 注意,toArray(new Object[0]) 和 toArray() 在功能上是相同的。 
此实现返回一个数组,它包含此 collection 的迭代器返回的所有元素,这些元素的排列顺序与数组的连续元素存储顺序相同,都是从索引 0 开始。如果迭代器返回的元素数太大,不适合指定数组,则在新分配的数组中返回这些元素,该数组的长度等于迭代器返回的元素数,即使此 collection 的大小在进行迭代期间发生更改也是如此,这种情况可能发生在 collection 允许在迭代期间进行并发修改时。size 方法只是作为一个优化提示被调用;即使迭代器返回不同的元素数,也会返回正确的结果。 

此方法等效于: 

 List<E> list = new ArrayList<E>(size());
 for (E e : this)
     list.add(e);
 return list.toArray(a);
 
指定者:
接口 Collection<E> 中的 toArray
参数:
a - 存储此 collection 元素的数组(如果其足够大);否则,将为此分配一个具有相同运行时类型的新数组。 
返回:
包含此 collection 中所有元素的数组 
抛出: 
ArrayStoreException - 如果指定数组的运行时类型不是此 collection 每个元素运行时类型的超类型 
NullPointerException - 如果指定的数组为 null

#6


HashSet 不是用来遍历的,遍历一个 HashSet 的意义是什么呢?

#1


直接clone吧。效率方面我觉得应该不是问题。

#2


#3


看源代码是个好方法。我看了一下clone的实现,是用Iterator遍历源HashSet,把元素逐个插入到新复制的HashSet里。不过toArray的实现没找到,不知道在哪里。

实测了一下,还是方法2比较快,执行时间是N(2-20)倍的关系。可惜执行时间不太稳定,变化比较剧烈。不知道是因为数据太少,还是java执行环境有影响。
目前在HashSet里插入了20000条不重复的记录,执行时间是用函数"System.currentTimeMillis()"统计的。

#4



   public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
        Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
    if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
    r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
    }

hashset的toArray實現

#5



 /**
     * {@inheritDoc}
     *
     * <p>This implementation returns an array containing all the elements
     * returned by this collection's iterator, in the same order, stored in
     * consecutive elements of the array, starting with index {@code 0}.
     * The length of the returned array is equal to the number of elements
     * returned by the iterator, even if the size of this collection changes
     * during iteration, as might happen if the collection permits
     * concurrent modification during iteration.  The {@code size} method is
     * called only as an optimization hint; the correct result is returned
     * even if the iterator returns a different number of elements.
     *
     * <p>This method is equivalent to:
     *
     *  <pre> {@code
     * List<E> list = new ArrayList<E>(size());
     * for (E e : this)
     *     list.add(e);
     * return list.toArray();
     * }</pre>
     */

toArray
public <T> T[] toArray(T[] a)返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。如果指定的数组能容纳该 collection,则返回包含此 collection 元素的数组。否则,将分配一个具有指定数组的运行时类型和此 collection 大小的新数组。 
如果指定的数组能容纳 collection,并有剩余空间(即数组的元素比 collection 的元素多),那么会将数组中紧接 collection 尾部的元素设置为 null。(只有 在调用者知道此 collection 没有包含任何 null 元素时才能用此方法确定 collection 的长度。) 

如果此 collection 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。 

像 Collection.toArray() 方法一样,此方法充当基于数组的 API 与基于 collection 的 API 之间的桥梁。更进一步说,此方法允许对输出数组的运行时类型进行精确控制,并且在某些情况下,可以用来节省分配开销。 

假定 x 是只包含字符串的一个已知 collection。以下代码用来将 collection 转储到一个新分配的 String 数组: 

     String[] y = x.toArray(new String[0]); 注意,toArray(new Object[0]) 和 toArray() 在功能上是相同的。 
此实现返回一个数组,它包含此 collection 的迭代器返回的所有元素,这些元素的排列顺序与数组的连续元素存储顺序相同,都是从索引 0 开始。如果迭代器返回的元素数太大,不适合指定数组,则在新分配的数组中返回这些元素,该数组的长度等于迭代器返回的元素数,即使此 collection 的大小在进行迭代期间发生更改也是如此,这种情况可能发生在 collection 允许在迭代期间进行并发修改时。size 方法只是作为一个优化提示被调用;即使迭代器返回不同的元素数,也会返回正确的结果。 

此方法等效于: 

 List<E> list = new ArrayList<E>(size());
 for (E e : this)
     list.add(e);
 return list.toArray(a);
 
指定者:
接口 Collection<E> 中的 toArray
参数:
a - 存储此 collection 元素的数组(如果其足够大);否则,将为此分配一个具有相同运行时类型的新数组。 
返回:
包含此 collection 中所有元素的数组 
抛出: 
ArrayStoreException - 如果指定数组的运行时类型不是此 collection 每个元素运行时类型的超类型 
NullPointerException - 如果指定的数组为 null

#6


HashSet 不是用来遍历的,遍历一个 HashSet 的意义是什么呢?