Java Stream different()函数删除重复项

时间:2020-02-23 14:34:31  来源:igfitidea点击:

Java Stream独特的()方法返回一个新的独特元素流。
在处理集合中的重复元素之前非常有用。

Java Stream different()方法

  • 使用equals()方法比较元素。
    因此,流元素必须正确实现equals()方法。

  • 如果流是有序的,则遇到顺序将保留。
    这意味着首先出现的元素将出现在不同的元素流中。

  • 如果流是无序的,那么生成的流元素可以是任何顺序。

  • 流distinct()是有状态的中间操作。

  • 由于有很大的缓冲开销,因此对有序并行流使用distinct()可能会导致性能下降。
    在这种情况下,请进行顺序流处理。

使用distinct()删除重复元素

让我们来看看如何使用stream different()方法从集合中删除重复的元素。

jshell> List<Integer> list = List.of(1, 2, 3, 4, 3, 2, 1);
list ==> [1, 2, 3, 4, 3, 2, 1]

jshell> List<Integer> distinctInts = list.stream().distinct().collect(Collectors.toList());
distinctInts ==> [1, 2, 3, 4]

Java Stream different()示例

使用Stream different()和forEach()仅处理唯一元素

由于distinct()是中间操作,因此我们可以将forEach()方法与它一起使用以仅处理唯一元素。

jshell> List<Integer> list = List.of(1, 2, 3, 4, 3, 2, 1);
list ==> [1, 2, 3, 4, 3, 2, 1]

jshell> list.stream().distinct().forEach(x -> System.out.println("Processing " + x));
Processing 1
Processing 2
Processing 3
Processing 4

Java Stream different()forEach()示例

使用自定义对象流distinct()

让我们看一个简单的示例,该示例使用distinct()从列表中删除重复的元素。

package com.theitroad.java;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class JavaStreamDistinct {

	public static void main(String[] args) {
		List<Data> dataList = new ArrayList<>();
		dataList.add(new Data(10));
		dataList.add(new Data(20));
		dataList.add(new Data(10));
		dataList.add(new Data(20));

		System.out.println("Data List = "+dataList);

		List<Data> uniqueDataList = dataList.stream().distinct().collect(Collectors.toList());

		System.out.println("Unique Data List = "+uniqueDataList);
	}

}

class Data {
	private int id;

	Data(int i) {
		this.setId(i);
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return String.format("Data[%d]", this.id);
	}
}

输出:

Data List = [Data[10], Data[20], Data[10], Data[20]]
Unique Data List = [Data[10], Data[20], Data[10], Data[20]]

unique()方法并未删除重复的元素。
这是因为我们没有在Data类中实现equals()方法。
因此,使用超类Object equals()方法来标识相等的元素。
Object类的equals()方法实现为:

public boolean equals(Object obj) {
  return (this == obj);
}

由于数据对象具有相同的ID,但它们引用的是不同的对象,因此认为它们不相等。
这就是为什么如果您打算对自定义对象使用流different()方法,那么实现equals()方法非常重要。

请注意,Collection类API使用equals()和hashCode()方法来检查两个对象是否相等。
因此最好为它们两个都提供一个实现。

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + id;
	return result;
}

@Override
public boolean equals(Object obj) {
	System.out.println("Data equals method");
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Data other = (Data) obj;
	if (id != other.id)
		return false;
	return true;
}

提示:您可以使用" Eclipse>源>生成equals()和hashCode()"菜单选项轻松地生成equals()和hashCode()方法。

添加equals()和hashCode()实现后的输出为:

Data List = [Data[10], Data[20], Data[10], Data[20]]
Data equals method
Data equals method
Unique Data List = [Data[10], Data[20