添加到列表时有没有办法避免循环?

Jim*_*Jim 28 java collections list arraylist data-structures

我想知道这样的代码:

List<String> list = new ArrayList<String>();
for(CustomObject co : objects) {
    list.add(co.getActualText());
}
Run Code Online (Sandbox Code Playgroud)

可以用不同的方式书写吗?我的意思是当然在某些时候会有一个循环,但我想知道是否有一个我忽略的API用法

Kon*_*kov 27

如果您使用Java 8,则可以利用Stream API:

List<String> list = objects.stream()
                           .map(CustomObject::getActualText)
                           .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

  • TBH恕我直言,这对于一项简单的任务实际上是不可读的.这不是关于你的答案,而是关于Java方法本身 (15认同)
  • 不是真的同意吉姆,这也是一个习惯于一个新概念的问题.虽然在Scala中,使用简单的val list = objects.map(_.getActualText)会更漂亮 (9认同)
  • .NET用户已经使用LINQ多年了,很明显,在几乎所有情况下,它都是比列表构建循环更好的方法.我认为Java人员只需要在这里改变心态.此代码本身并不可读.对于没有经验的人来说,这是难以理解的.这是一个临时状态. (7认同)

Fel*_*elk 20

如果你有Java 8,那么:

objects.forEach(item -> list.add(item.getActualText()));
Run Code Online (Sandbox Code Playgroud)

内部仍然是一个循环.

编辑一点偏离主题:IMO这是最可读和最好的解决方案.为什么不使用你可能会问的foreach.答案:因为这种方式集合选择了迭代项目的最佳方式.例如,ArrayList不使用迭代器,因为它比你更了解:

@Override
public void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    final int expectedModCount = modCount;
    @SuppressWarnings("unchecked")
    final E[] elementData = (E[]) this.elementData;
    final int size = this.size;
    for (int i=0; modCount == expectedModCount && i < size; i++) {
        action.accept(elementData[i]);
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}
Run Code Online (Sandbox Code Playgroud)


kap*_*pex 9

当然,Apache Commons和Guava也提供了在不使用Java 8的情况下避免循环的方法.

Commons CollectionUtils.collect:

CollectionUtils.collect(objects, Transformer.invokerTransformer("getActualText"), list);
Run Code Online (Sandbox Code Playgroud)

番石榴Lists.transform:

List<String> list = Lists.transform(objects, 
    new Function<CustomObject, String>() { 
        public String apply(CustomObject co) {
            return co.getActualText();
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

  • 在Java 8中,通过用lambda替换匿名类可以更简洁地编写Guava示例:`Lists.transform(objects,(co) - > co.getActualText())` (2认同)

And*_*ner 6

虽然显然有点荒谬的建议:你可以通过递归添加它们来避免循环.

void add(List<? super String> receiver, CustomObject[] objects) {
  addRec(receiver, toAdd, 0, objects.length());
}

void addRec(List<? super String> receiver, CustomObject[] objects, int start, int end) {
  if (start + 1 == end) {
    receiver.add(objects[start].getActualText());
  } else if (start != end) {
    int mid = (start + end) / 2;
    addRec(receiver, objects, start, mid);
    addRec(receiver, objects, mid, end);
  }
}
Run Code Online (Sandbox Code Playgroud)