有没有更好的方法来编写这个循环?也许有溪流?

时间:2018-04-23 23:06:41

标签: java java-stream

我正在努力学习如何更好地使用流,我认为使用流可能会有更好的代码。

List<Integer> origList = Arrays.asList(1,2,3,4,5,6);
List<Integer> newList = new ArrayList<>();

//Need at least a first and a last
if(origList.size < 2) {
    return newList;
}

//Add First
newList.add(origList.get(0));

//Play leap frog and only add ever other item in the middle
for(int i = 1; i < origList.size() - 1; i++) {
    if(i%2 == 1) {
        newList.add(origList.get(i));
    }
}

//Add Last
newList.add(origList.get(origList.size-1));

System.out.println(newList); // expect: [1,2,4,6]

3 个答案:

答案 0 :(得分:1)

我会留在循环中。但是,不是迭代所有数字,只是通过模数测试跳过每一秒,首先迭代每个第二个数字:

newList.add(origList.get(0));
int last = origList.size() - 1;
for(int i = 1; i < last; i += 2) newList.add(origList.get(i));
newList.add(origList.get(last));

您可以使用流

List<Integer> newList = IntStream.concat(IntStream.of(0),
    IntStream.concat(IntStream.range(0, last / 2).map(i -> i * 2 + 1), IntStream.of(last)))
        .mapToObj(origList::get)
        .collect(Collectors.toList());

但它不一定是对循环版本的改进......

答案 1 :(得分:0)

好的,您可以使用自定义收集器来完成此操作。但收藏家并不是很好。无论如何,你走了:

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

public class MyCollector<T> implements Collector<T, MyCollector.DataHolder<T>, List<T>> {

    static class DataHolder<T> {
        T first;
        T last;
        List<T> evens = new LinkedList<>();
        List<T> odds = new LinkedList<>();
        boolean hasFirst = false;
        boolean hasLast = false;
        boolean even = true;

        void accummulate(T next) {
            if (!hasFirst) {
                hasFirst = true;
                first = next;
                return;
            }
            if (!hasLast) {
                hasLast = true;
                last = next;
                return;
            }
            T cur = last;
            last = next;
            if (even) {
                evens.add(cur);
            } else {
                odds.add(cur);
            }
            even = !even;
        }

        DataHolder<T> combine(DataHolder<T> other) {
            if (!hasFirst)
                return other;
            if (hasLast) {
                if (even) {
                    evens.add(last);
                    odds.add(other.first);
                    evens.addAll(other.evens);
                    odds.addAll(other.odds);
                    last = other.last;
                    even = other.even;
                } else {
                    odds.add(last);
                    evens.add(other.first);
                    odds.addAll(other.evens);
                    evens.addAll(other.odds);
                    last = other.last;
                    even = !other.even;
                }
            } else {
                if (even) {
                    evens.add(other.first);
                    odds.addAll(other.evens);
                    evens.addAll(other.odds);
                    last = other.last;
                    even = !other.even;
                } else {
                    odds.add(other.first);
                    evens.addAll(other.evens);
                    odds.addAll(other.odds);
                    last = other.last;
                    even = other.even;
                }
            }
            return this;
        }

        List<T> finish() {
            if (hasFirst)
                evens.add(0, first);
            if (hasLast)
                evens.add(last);
            return evens;
        }
    }

    @Override
    public Supplier<DataHolder<T>> supplier() {
        return DataHolder::new;
    }

    @Override
    public BiConsumer<DataHolder<T>, T> accumulator() {
        return DataHolder::accummulate;
    }

    @Override
    public BinaryOperator<DataHolder<T>> combiner() {
        return DataHolder::combine;
    }

    @Override
    public Function<DataHolder<T>, List<T>> finisher() {
        return DataHolder::finish;
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Collections.emptySet();
    }

    // Test main, just to show off.
    public static void main(String[] args) {
        System.out.println(Arrays.asList(1, 2, 3, 4, 5, 6).stream().collect(new MyCollector<>()));
    }

}

答案 2 :(得分:0)

引用有效最终(常量引用)计数器:

AtomicInteger count = new AtomicInteger();
List<Integer> newList = origList.stream()
        .filter(x -> count.getAndIncrement() % 2 == 1)
        .collect(Collectors.toList());
newList.add(0, origList.get(0));
Optional.of(origList.size()).filter(n -> n % 2 == 1).ifPresent(n -> newList.add(origList.get(n - 1)));

此代码根据样本输入生成所需的输出。