【问题标题】:Best way to iterate through a Set in Java在 Java 中遍历 Set 的最佳方法
【发布时间】:2018-03-09 17:38:39
【问题描述】:

情况是我必须迭代一个包含最多 5000 个元素的集合。目前,我正在使用带有迭代器的普通 for 循环。

for (Iterator iterator = allValues.iterator(); iterator.hasNext();) {

     ListMetadataElem element = (ListMetadataElem) iterator.next(); 
     NameValueObject value = new NameValueObject(); 
     value.setId(element.getListMetadataElemSeqId().toString());    
     value.setValue(element.getListMetadataElemNm());   
     abstractVO.getAllListMetadataElems().add(value);       
}

问题是它花费了太多时间来迭代,比如 6-7 秒,我必须多次调用同一个循环。

【问题讨论】:

  • 给机会Java 8 并行流
  • 您确定是迭代需要时间吗? 5000 个元素应该几乎没有
  • 我不经常使用 Java,但在 Python 中,我希望对一组仅 5000 元素的迭代非常快,并且只有 6-7 秒的一小部分。我只能假设它在 Java 中会同样快,而且可能快得多。我怀疑这是在你的循环中中发生的任何事情,那么abstractVO.getAllListMetadataElems()到底做了什么,例如?
  • 在我的慢速 PC 上,一组 5000 个字符串需要 324 毫秒

标签: java loops collections iterator set


【解决方案1】:

以下是比较:

public class IterateSet {

    public static void main(String[] args) {

        //example Set
        Set<String> set = new HashSet<>();

        set.add("Jack");
        set.add("John");
        set.add("Joe");
        set.add("Josh");

        long startTime = System.nanoTime();
        long endTime = System.nanoTime();

        //using iterator
        System.out.println("Using Iterator");
        startTime = System.nanoTime();
        Iterator<String> setIterator = set.iterator();
        while(setIterator.hasNext()){
            System.out.println(setIterator.next());
        }
        endTime = System.nanoTime();
        long durationIterator = (endTime - startTime);


        //using lambda
        System.out.println("Using Lambda");
        startTime = System.nanoTime();
        set.forEach((s) -> System.out.println(s));
        endTime = System.nanoTime();
        long durationLambda = (endTime - startTime);


        //using Stream API
        System.out.println("Using Stream API");
        startTime = System.nanoTime();
        set.stream().forEach((s) -> System.out.println(s));
        endTime = System.nanoTime();
        long durationStreamAPI = (endTime - startTime);


        //using Split Iterator (not recommended)
        System.out.println("Using Split Iterator");
        startTime = System.nanoTime();
        Spliterator<String> splitIterator = set.spliterator();
        splitIterator.forEachRemaining((s) -> System.out.println(s));
        endTime = System.nanoTime();
        long durationSplitIterator = (endTime - startTime);


        //time calculations
        System.out.println("Iterator Duration:" + durationIterator);
        System.out.println("Lamda Duration:" + durationLambda);
        System.out.println("Stream API:" + durationStreamAPI);
        System.out.println("Split Iterator:"+ durationSplitIterator);
    }
}

代码是不言自明的。 持续时间的结果是:

Iterator Duration:495287
Lamda Duration:50207470
Stream API:2427392
Split Iterator:567294

我们可以看到 Lambda 耗时最长,而 Iterator 最快。 除此之外,还有传统的古老的增强型 for 循环。

【讨论】:

  • 所以迭代器大约需要 0.5 秒,Lamba 大约需要 50 秒 - 似乎不太正确
  • 虽然没有投反对票,但仍然阅读有关基准测试的更多信息,或者只是尝试多次执行相同的代码,以了解这些值在设置基准方面可能有多不正确。
  • @Scary Wombat 在 1 毫秒内是 1000000 纳秒。所以 lambda 是 50 毫秒。转换器在这里 - convertunits.com/from/nanoseconds/to/milliseconds
  • @ScaryWombat 但这就是我得到的
  • @PritamBanerjee 学习基准测试您至少应该运行几次并进行一些热身
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-04
  • 2012-05-16
  • 1970-01-01
  • 2018-11-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多