[Java] Stream 중복된 값 제거 /필터링(distinct)

2021-02-16


Set / Map 컬렉션일 경우 상관이 없겠지만, list 함수는 중복된 값이 다수 들어가 있을 가능성이 있다. 이러한 경우 contains를 통해 foreach문을 돌면서 비교하는 방법도 있겠지만 Stream을 이용하면 좀 더 손쉽게 중복처리를 할 수 있다. 오늘은 이와 같은 방법을 알아보도록 하자.


- 에제 코드

 

package sStream;

public class People {
	
	private String name;
	private int age;
	
	public People(String name, int age) {
		this.name = name;
		this.age = age;
	}// 생성자
	
	
	//// getter / setter 
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof People) {
			People human = (People) obj;
			return human.name.equals(name) && human.age == age;
		}else {
			return false;
		}
	} // equals 동등성비교
	
	@Override
	public int hashCode() {
		return name.hashCode() + age;
	} // hashCode 재정의

}

package sStream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class main {

	public static void main(String[] args) {
		List<People> plist = new ArrayList<People>();
		
		plist.add(new People("aaa", 25));
		plist.add(new People("aaa", 25));
		plist.add(new People("bbb", 35));
		plist.add(new People("bbb", 35));
		plist.add(new People("ccc", 45));	
 	}
}

 

위의 코드를 보면 People 이라는 사용자 정의의 클래스를 제네릭타입으로 받는 리스트가 선언되어 있다. 다만 해당 리스트에 들어가 있는 각각의 객체를 살펴보면, 이름이 'aaa' / 'bbb' 라는 사람은 중복된 값이 들어가 있는 것을 확인할 수 있는데, 이를 제거한 값들만 출력해 보도록 하자.


- 중복 제거 코드(Stream)

 

package sStream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class main {

	public static void main(String[] args) {
		List<People> plist = new ArrayList<People>();
		
		plist.add(new People("aaa", 25));
		plist.add(new People("aaa", 25));
		plist.add(new People("bbb", 35));
		plist.add(new People("bbb", 35));
		plist.add(new People("ccc", 45));
		plist.stream()
			.distinct()
			.forEach(name -> System.out.println(name.getName()));        
 	}
}

 

우선 리스트 자체 메소드 중 stream이라는 메소드가 있는데, 이를 통해서 stream을 람다식으로 표현할 수 있게 도와준다. plist를 stream 형태로 만든 후 중복값을 제거하는 메소드인 distinct 라는 메소드를 사용한다. 해당 메소드는 People에서의 이름과 나이가 같으면, 둘이 동등한 객체로 보고 중복값을 제거하게 된다. 이후 forEach문으로 통해 각각의 중복되지 않은 People 이름을 출력해보면 아래와 같은 결과를 얻을 수 있다. (여기서 동등성 비교가 가능한 이유는 기존의 People 클래스에서 equals 와 hashcode를 재정의 해주었기 때문이다.)