实际上,我知道减少重复的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/