添加到列表中是否有避免循环的方法?

问题描述 投票:28回答:7

我想知道这样的代码:

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

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

java list arraylist data-structures collections
7个回答
27
投票

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

List<String> list = objects.stream()
                           .map(CustomObject::getActualText)
                           .collect(Collectors.toList());

20
投票

如果您有Java 8,该怎么办:

objects.forEach(item -> list.add(item.getActualText()));

内部仍然是一个循环。

编辑一些非主题: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();
    }
}

9
投票

当然,Apache Commons和Guava还提供了无需使用Java 8即可避免循环的方法。

通用CollectionUtils.collect

CollectionUtils.collect(objects, Transformer.invokerTransformer("getActualText"), list);

番石榴Lists.transform

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

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);
  }
}

4
投票

如果使用Eclipse Collections,则可以从Java 8开始编写以下代码:

MutableList<CustomObject> objects = ...
MutableList<String> result = objects.collect(CustomObject::getActualText);

对于Java 5-7,您可以使用collect方法使用表示SAM类型Function的匿名内部类。

MutableList<CustomObject> objects = ...
MutableList<String> result = objects.collect(new Function<CustomObject, String>() {
    public String valueOf(CustomObject object){
        return object.getActualText();
    }
});

注意:我是Eclipse集合的提交者


3
投票

使用流在Java 8中会更惯用,但是如果您希望它更接近于传统的基于循环的方法,则可以使用forEach

objects.forEach(co -> list.add(co.getActualText()) );

0
投票

为了在两个互不相同的列表类型之间复制一定范围的数据时,要达到非常好的效率,必须有一种机制,通过这种机制,“受信任”类型可以要求每种类型公开与之关联的支持数组。一系列元素,然后使用批量复制操作将数据从一个移到另一个。通过将GetArraySource方法传递给受信任ArraySource类的构造函数,可以使用一个对象来请求与特定元素相关联的后备数组,从而完全用Java编写此类。 (包括底衬阵列和其中包含的元素范围)。想要复制的代码将调用GetArraySource,并将由此返回的ArraySource传递给目标列表的CopyFromArraySource方法,该方法然后可以要求ArraySource将一个或多个项目范围复制到其自己的后备数组中)。

[如果ArraySource是Java随附的类,并且Oracle确切记录了它将对接收到的数组执行的操作,则ArrayListString之类的类型可能会将其内容公开为[C0 ],或从ArraySource接受外部数据,而不会将其数组不当地暴露于可能滥用它的任何代码中。

[不幸的是,除非Oracle将此类内容合并到Java发行版中,否则支持可能太稀疏而无用。让源列表支持一个这样的类,目的地支持另一个这样的类以及希望复制操作的代码第三种是不好的。所有这三个类都需要支持相同的特定trusted-array-segment-copy-helper类。

© www.soinside.com 2019 - 2024. All rights reserved.