java - 如何在List <T> JAVA 8中删除重复项

标签 java collections java-8

实际上,我知道减少重复的distinct()或将List分配给Set的方法,但是我有一些不同的问题。
如何使用流或可能是StreamEx的JAVA 8问题以下解决聪明的方法?

假设我们在List中有一个对象
A, A, A, B, B, A, A, A, C, C, C, A, A, B, B, A
现在我需要
A, B, A, C, A, B, A
因此,已删除重复项,但只有当下一个出现时才被删除,但如果下一个是另一个对象,则应保留。
我尝试了一些解决方案,但感觉很丑陋,而且不可读。

最佳答案

选项1:过滤器

您可以编写一个有状态的过滤器,但是绝对不要执行该,因为它违反了 filter(Predicate<? super T> predicate) 的约定:

predicate - a non-interfering, stateless predicate to apply to each element to determine if it should be included


public class NoRepeatFilter<T> implements Predicate<T> {
    private T prevValue;
    @Override
    public boolean test(T value) {
        if (value.equals(this.prevValue))
            return false;
        this.prevValue = value;
        return true;
    }
}

测试
List<String> result = Stream
        .of("A", "A", "A", "B", "B", "A", "A", "A", "C", "C", "C", "A", "A", "B", "B", "A")
//      .parallel()
        .filter(new NoRepeatFilter<>())
        .collect(Collectors.toList());
System.out.println(result);

输出
[A, B, A, C, A, B, A]
它必须是无状态的原因是,如果流是并行的,则它将失败,例如取消注释.parallel()再次运行测试:
[A, A, B, B, A, C, C, C, A, B, B, A]
选项2:收集器

一个有效的解决方案是使用 Collector 创建自己的 of(...) :
public class NoRepeatCollector {
    public static <E> Collector<E, ?, List<E>> get() {
        return Collector.of(ArrayList::new,
                            NoRepeatCollector::addNoRepeat,
                            NoRepeatCollector::combineNoRepeat);
    }
    private static <E> void addNoRepeat(List<E> list, E value) {
        if (list.isEmpty() || ! list.get(list.size() - 1).equals(value))
            list.add(value);
    }
    private static <E> List<E> combineNoRepeat(List<E> left, List<E> right) {
        if (left.isEmpty())
            return right;
        if (! right.isEmpty())
            left.addAll(left.get(left.size() - 1).equals(right.get(0))
                        ? right.subList(1, right.size()) : right);
        return left;
    }
}

测试
List<String> result = Stream
        .of("A", "A", "A", "B", "B", "A", "A", "A", "C", "C", "C", "A", "A", "B", "B", "A")
//      .parallel()
        .collect(NoRepeatCollector.get());
System.out.println(result);

输出(带有和不带有.parallel())
[A, B, A, C, A, B, A]
选项3:循环

如果您输入的是 List (或其他 Iterable ),则可以使用简单的循环删除重复的值:
public static <E> void removeRepeats(Iterable<E> iterable) {
    E prevValue = null;
    for (Iterator<E> iter = iterable.iterator(); iter.hasNext(); ) {
        E value = iter.next();
        if (value.equals(prevValue))
            iter.remove();
        else
            prevValue = value;
    }
}

测试
List<String> list = new ArrayList<>(Arrays.asList(
        "A", "A", "A", "B", "B", "A", "A", "A", "C", "C", "C", "A", "A", "B", "B", "A"));
removeRepeats(list);
System.out.println(list);

输出
[A, B, A, C, A, B, A]

关于java - 如何在List <T> JAVA 8中删除重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49213102/

相关文章:

ruby - 在 Ruby 中是否有性能原因更喜欢大小而不是长度或计数?

java - 使用 Spark 和 java 编写 CSV 文件 - 处理空值和引号

java - Spring Integration + @Aysnc - 网关与 ServiceActivator

java - 在 Dalvik VM(Android 的 VM)上,您不能在 Sun VM 中做什么?

C# - 如何知道对象是否是 ICollection 的衍生物

java - XStream 避免收集 xml 元素

java - 为什么只有在使用 count() 函数时才执行 map() 函数内的表达式?

java - CompletableFuture | thenApplyAsync 与 thenCompose 及其用例

java - 您需要使用 JDK 运行构建或在类路径中包含 tools.jar

java - 需要有关使用对特定对象的实例方法的引用的基本信息