Java流修剪列表

Java流修剪列表,java,java-stream,trim,Java,Java Stream,Trim,我有以下实现,用于根据给定谓词(即-删除前导和尾随的空元素)修剪元素列表 我希望使实现更具可读性,最好使用Java的流API /** * Trim a List based on a given predicate, that is, remove leading * and trailing elements that match the predicate (but not in-between * non-matching elements). * * @param list t

我有以下实现,用于根据给定谓词(即-删除前导和尾随的空元素)修剪元素列表

我希望使实现更具可读性,最好使用Java的流API

/**
 * Trim a List based on a given predicate, that is, remove leading
 * and trailing elements that match the predicate (but not in-between
 * non-matching elements).
 *
 * @param list the list to trim
 * @param trimPredicate the predicate for trimming
 * @param <T> type of the list
 * @return the same list minus the trimmed elements.
 * @throws NullPointerException if the list is {@code null}
 * @throws UnsupportedOperationException if the {@code remove}
 *      operation is not supported by the list iterator
 */
public static <T> List<T> trim(List<T> list, Predicate<T> trimPredicate)
        throws NullPointerException, UnsupportedOperationException {
    if (list == null) throw new NullPointerException("list is null");
    ListIterator<T> it = list.listIterator();
    while (it.hasNext() && trimPredicate.test(it.next())) it.remove();
    it = list.listIterator(list.size());
    while (it.hasPrevious() && trimPredicate.test(it.previous())) it.remove();

    return list;
}
将被修剪为:

[3, 5, 0, 4, 0, -3]

(事实上,这里至少有两个不同的读者弄错了,这证明了我关于代码可读性的观点:)

一点黑客技术使之成为可能,但我不确定它是否更清晰

/**
 * Stateful predicate to only match until matching fails.
 * It seems this is not necessary in Java 9.
 */
static class MatchWhile<T> implements Predicate<T> {
    final Predicate<T> matcher;
    boolean match = true;

    MatchWhile(Predicate<T> matcher) {
        this.matcher = matcher;
    }

    @Override
    public boolean test(T t) {
        return match && (match = matcher.test(t));
    }
}

// Hides the horrible stuff.
static <T> Stream<T> asStream(Iterator<T> it) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,Spliterator.ORDERED), false);
}

<T> List<T> trim2(List<T> list, Predicate<T> isEmpty) {
    // Trim right using a Deque to reverse it.
    Deque<T> reversedAndTrimmedAtEnd = asStream(new ArrayDeque<>(list).descendingIterator())
            .filter(new MatchWhile<>(isEmpty).negate())
            .collect(Collectors.toCollection(ArrayDeque::new));
    // Reverse it again to trim left.
    List<T> leftTrimmed = asStream(reversedAndTrimmedAtEnd.descendingIterator())
            .filter(new MatchWhile<>(isEmpty).negate())
            .collect(Collectors.toList());

    return leftTrimmed;
}
/**
*只有在匹配失败之前才匹配的有状态谓词。
*这在Java9中似乎不是必需的。
*/
静态类MatchWhile实现谓词{
最终谓词匹配器;
布尔匹配=真;
MatchWhile(谓词匹配器){
this.matcher=matcher;
}
@凌驾
公共布尔测试(T){
返回match&(match=matcher.test(t));
}
}
//隐藏可怕的东西。
静态流asStream(迭代器it){
返回StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,Spliterator.ORDERED),false);
}
列表trim2(列表,谓词为空){
//用三角板向右修剪以使其反转。
Deque reversedAndTrimmedAtEnd=asStream(新的ArrayQue(列表).DegendingIterator())
.filter(新的MatchWhile(isEmpty).negate())
.collect(收集器.toCollection(ArrayDeque::new));
//再次将其反转以向左修剪。
List leftTrimmed=asStream(reversedAndTrimmedAtEnd.dressingiterator())
.filter(新的MatchWhile(isEmpty).negate())
.collect(Collectors.toList());
返回左修剪;
}

一点黑客技术使之成为可能,但我不确定它是否更清晰

/**
 * Stateful predicate to only match until matching fails.
 * It seems this is not necessary in Java 9.
 */
static class MatchWhile<T> implements Predicate<T> {
    final Predicate<T> matcher;
    boolean match = true;

    MatchWhile(Predicate<T> matcher) {
        this.matcher = matcher;
    }

    @Override
    public boolean test(T t) {
        return match && (match = matcher.test(t));
    }
}

// Hides the horrible stuff.
static <T> Stream<T> asStream(Iterator<T> it) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,Spliterator.ORDERED), false);
}

<T> List<T> trim2(List<T> list, Predicate<T> isEmpty) {
    // Trim right using a Deque to reverse it.
    Deque<T> reversedAndTrimmedAtEnd = asStream(new ArrayDeque<>(list).descendingIterator())
            .filter(new MatchWhile<>(isEmpty).negate())
            .collect(Collectors.toCollection(ArrayDeque::new));
    // Reverse it again to trim left.
    List<T> leftTrimmed = asStream(reversedAndTrimmedAtEnd.descendingIterator())
            .filter(new MatchWhile<>(isEmpty).negate())
            .collect(Collectors.toList());

    return leftTrimmed;
}
/**
*只有在匹配失败之前才匹配的有状态谓词。
*这在Java9中似乎不是必需的。
*/
静态类MatchWhile实现谓词{
最终谓词匹配器;
布尔匹配=真;
MatchWhile(谓词匹配器){
this.matcher=matcher;
}
@凌驾
公共布尔测试(T){
返回match&(match=matcher.test(t));
}
}
//隐藏可怕的东西。
静态流asStream(迭代器it){
返回StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,Spliterator.ORDERED),false);
}
列表trim2(列表,谓词为空){
//用三角板向右修剪以使其反转。
Deque reversedAndTrimmedAtEnd=asStream(新的ArrayQue(列表).DegendingIterator())
.filter(新的MatchWhile(isEmpty).negate())
.collect(收集器.toCollection(ArrayDeque::new));
//再次将其反转以向左修剪。
List leftTrimmed=asStream(reversedAndTrimmedAtEnd.dressingiterator())
.filter(新的MatchWhile(isEmpty).negate())
.collect(Collectors.toList());
返回左修剪;
}

您的原始代码可读性强,效率高。推荐的

static <T> List<T> trim2(List<T> list, Predicate<T> isEmpty) {
    ListIterator<T> it = list.listIterator();
    while (it.hasNext() && isEmpty.test(it.next())) {
        it.remove();
    }
    it = list.listIterator(list.size());
    while (it.hasPrevious() && isEmpty.test(it.previous())) {
        it.remove();
    }
    return list;
}
static <T> List<T> trim3(List<T> list, Predicate<T> isEmpty) {
    Collection<T> ltrimreverse = list.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    Collection<T> rtrim = ltrimreverse.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    return new ArrayList<>(rtrim);
}
静态列表trim2(列表,谓词为空){
ListIterator it=list.ListIterator();
while(it.hasNext()&&isEmpty.test(it.next()){
it.remove();
}
it=list.listIterator(list.size());
while(it.hasPrevious()&&isEmpty.test(it.previous())){
it.remove();
}
退货清单;
}
使用Java9的流版本。只是为了见鬼,不推荐

static <T> List<T> trim2(List<T> list, Predicate<T> isEmpty) {
    ListIterator<T> it = list.listIterator();
    while (it.hasNext() && isEmpty.test(it.next())) {
        it.remove();
    }
    it = list.listIterator(list.size());
    while (it.hasPrevious() && isEmpty.test(it.previous())) {
        it.remove();
    }
    return list;
}
static <T> List<T> trim3(List<T> list, Predicate<T> isEmpty) {
    Collection<T> ltrimreverse = list.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    Collection<T> rtrim = ltrimreverse.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    return new ArrayList<>(rtrim);
}
静态列表trim3(列表,谓词为空){
集合ltrimreverse=list.stream().dropWhile(isEmpty)
.collect(ArrayDeque::new、ArrayDeque::push、ArrayDeque::addAll);
集合rtrim=ltrimreverse.stream().dropWhile(isEmpty)
.collect(ArrayDeque::new、ArrayDeque::push、ArrayDeque::addAll);
返回新的ArrayList(rtrim);
}

您的原始代码可读性强,效率高。推荐的

static <T> List<T> trim2(List<T> list, Predicate<T> isEmpty) {
    ListIterator<T> it = list.listIterator();
    while (it.hasNext() && isEmpty.test(it.next())) {
        it.remove();
    }
    it = list.listIterator(list.size());
    while (it.hasPrevious() && isEmpty.test(it.previous())) {
        it.remove();
    }
    return list;
}
static <T> List<T> trim3(List<T> list, Predicate<T> isEmpty) {
    Collection<T> ltrimreverse = list.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    Collection<T> rtrim = ltrimreverse.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    return new ArrayList<>(rtrim);
}
静态列表trim2(列表,谓词为空){
ListIterator it=list.ListIterator();
while(it.hasNext()&&isEmpty.test(it.next()){
it.remove();
}
it=list.listIterator(list.size());
while(it.hasPrevious()&&isEmpty.test(it.previous())){
it.remove();
}
退货清单;
}
使用Java9的流版本。只是为了见鬼,不推荐

static <T> List<T> trim2(List<T> list, Predicate<T> isEmpty) {
    ListIterator<T> it = list.listIterator();
    while (it.hasNext() && isEmpty.test(it.next())) {
        it.remove();
    }
    it = list.listIterator(list.size());
    while (it.hasPrevious() && isEmpty.test(it.previous())) {
        it.remove();
    }
    return list;
}
static <T> List<T> trim3(List<T> list, Predicate<T> isEmpty) {
    Collection<T> ltrimreverse = list.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    Collection<T> rtrim = ltrimreverse.stream().dropWhile(isEmpty)
        .collect(ArrayDeque::new, ArrayDeque::push, ArrayDeque::addAll);
    return new ArrayList<>(rtrim);
}
静态列表trim3(列表,谓词为空){
集合ltrimreverse=list.stream().dropWhile(isEmpty)
.collect(ArrayDeque::new、ArrayDeque::push、ArrayDeque::addAll);
集合rtrim=ltrimreverse.stream().dropWhile(isEmpty)
.collect(ArrayDeque::new、ArrayDeque::push、ArrayDeque::addAll);
返回新的ArrayList(rtrim);
}

如果您关心效率,您应该避免重复的单个
删除
操作,尤其是在
列表的开头
,因为最常用的实现,
ArrayList
在这一点上执行得不太好,因为删除条目时,它必须复制其内部数组中的所有剩余元素

最坏的情况,即以这种方式删除所有元素,将具有二次时间复杂度

public static <T> List<T> trim(List<T> list, Predicate<T> trimPredicate) {

    Objects.requireNonNull(list, "list is null");
    Objects.requireNonNull(trimPredicate, "trimPredicate is null");

    int lastMatch;

    for(ListIterator<T> it = list.listIterator(lastMatch = list.size());
        it.hasPrevious() && trimPredicate.test(it.previous());) lastMatch = it.nextIndex();

    if(lastMatch < list.size()) list.subList(lastMatch, list.size()).clear();

    for(ListIterator<T> it = list.listIterator(lastMatch = 0);
        it.hasNext() && trimPredicate.test(it.next()); ) lastMatch = it.previousIndex();

    if(lastMatch > 0) list.subList(0, lastMatch+1).clear();

    return list;
}

如果您关心效率,则应避免重复单个
删除
操作,尤其是在
列表
的开头,因为最常用的实现,
ArrayList
在这方面的性能不太好,因为删除条目时必须复制其内部数组中的所有剩余元素

最坏的情况,即以这种方式删除所有元素,将具有二次时间复杂度

public static <T> List<T> trim(List<T> list, Predicate<T> trimPredicate) {

    Objects.requireNonNull(list, "list is null");
    Objects.requireNonNull(trimPredicate, "trimPredicate is null");

    int lastMatch;

    for(ListIterator<T> it = list.listIterator(lastMatch = list.size());
        it.hasPrevious() && trimPredicate.test(it.previous());) lastMatch = it.nextIndex();

    if(lastMatch < list.size()) list.subList(lastMatch, list.size()).clear();

    for(ListIterator<T> it = list.listIterator(lastMatch = 0);
        it.hasNext() && trimPredicate.test(it.next()); ) lastMatch = it.previousIndex();

    if(lastMatch > 0) list.subList(0, lastMatch+1).clear();

    return list;
}

过滤非空的怎么样?我的意思是它相当基本-你做过任何研究吗?过滤操作是无状态的,所以我不能根据列表中的位置进行过滤。那么你想从列表中删除第一个和最后一个元素,如果它们是空的,对吗?这就是我所说的“删除前导和尾随空元素”的意思。过滤非空元素怎么样?我的意思是它相当基本-你做过任何研究吗?过滤操作是无状态的,所以我不能根据列表中的位置进行过滤。那么你想