简体   繁体   English

使用ArrayList而不是数组来避免使用普通的for循环

[英]Using ArrayList instead of an array to avoid using a normal for loop

I'm reviewing a piece of code that looks like this: 我正在审查一段看起来像这样的代码:

 public WrappedItem[] processItems(Item[] items) { List<WrappedItem> wrappedItems = new ArrayList<>(); for (Item item : items) { /* …do something with the item… */ wrappedItems.add(WrappedItem.wrap(item)); } return wrappedItems.toArray(new WrappedItem[0]); } 

A list is created so that the enhanced for loop can be used and then it is converted to an array to be returned. 创建一个列表,以便可以使用增强的for循环,然后将其转换为要返回的数组。

Would this be better from a performance and code style perspective? 从性能和代码风格的角度来看会更好吗?

public WrappedItem[] processItems(Item[] items)
{
    WrappedItem[] wrappedItems = WrappedItem[items.length];   
    for (int i = 0; i < items.length; i++)
    {
        Item item = items[i]
        /* …do something with the item… */
        wrappedItems[i] = WrappedItem.wrap(item);
    }
    return wrappedItems;
}

There is no reason you cannot simply directly construct an array and make use of the advanced for loop : 没有理由不能简单地直接构造一个数组使用高级的for循环:

public WrappedItem[] processItems(Item[] items)
{
    WrappedItem[] wrappedItems = WrappedItem[items.length];
    int i = 0;
    for (Item item : items)
    {
        /* …do something with the item… */
        wrappedItems[i++] = item;
    }
    return wrappedItems;
}

From code style perspective using enhanced loop increases readability, as it's more abstract than "standard" for loop. 从代码样式的角度来看,使用增强的循环可提高可读性,因为它比“标准”循环更抽象。

Standard for increases control, but introduces also a space for possible errors, as you're manipulating the indices and lengths, which everybody is familiar with, but still it's exposing some of the internal data's structure which is somehow against encapsulation... 增强控制的标准,但是当您操纵每个人都熟悉的索引和长度时,也引入了可能出现错误的空间,但是仍然暴露了某些内部数据的结构,这在某种程度上不利于封装...

Have a look also at this post What are the Advantages of Enhanced for loop and Iterator in Java? 也可以看看这篇文章Java中增强的for循环和迭代器的优点是什么?

As your code is written in the question you are not wrapping the item (despite the name) but just putting into a differently type array. 当您的代码写在问题中时,您不需要包装项目(尽管有名称),而只是放入不同类型的数组中。 This can be done even easier: 这可以更轻松地完成:

public WrappedItem[] processItems(Item[] items)
{
  WrappedItem[] wrappedItems
    = Arrays.copyOf(items, items.length, WrappedItem[].class);
  for (Item item : items)
  {
    /* …do something with the item… */
  }
  return wrappedItems;
}

If you need Java 5 compatibility you can use 如果需要Java 5兼容性,则可以使用

WrappedItem[] wrappedItems = Arrays.asList(items).toArray(new WrappedItem[0]);

instead of Arrays.copyOf . 而不是Arrays.copyOf


Now that you have updated your question it's clear that it's not that easy. 现在,您已经更新了问题,很显然这并不那么容易。 Then the answer is that the List based version creates some overhead but in most practical scenarios it will be negligible. 那么答案是基于List的版本会产生一些开销,但是在大多数实际情况下,它可以忽略不计。 As pointed out by others you can also combine a for-each loop with an additional index variable but to me it doesn't look convincing as the index variable has the wrong scope (you have to declare it outside the loop) and it's not really simpler than the traditional for loop. 正如其他人所指出的,您也可以将for-each循环与其他索引变量结合使用,但对我来说,这似乎没有说服力,因为index变量的作用域不正确(您必须在循环外声明它),并且它不是真的比传统的for循环更简单。

Maybe the final words come from the Java 8 solution: 最后的话也许来自Java 8解决方案:

public WrappedItem[] processItems(Item[] items) {
  return Arrays.stream(items)
      .map(item -> {
          /* …do something with the item… */
          return WrappedItem.wrap(item);
      }).toArray(WrappedItem[]::new);
}

or 要么

public WrappedItem[] processItems(Item[] items) {
  return Arrays.stream(items)
      .peek(item -> {
          /* …do something with the item… */
      }).map(WrappedItem::wrap).toArray(WrappedItem[]::new);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM