반응형

자바 8에서는 Stream이 추가되었는데, 이 기술은 컬렉션이나 배열등을 람다식으로 표현하여 간결하고 가독성 좋은 코드를 만들어주고 복잡하고 많은 양의 코드를 원하는 인스턴스끼리 조합하여 필터링을 해주는등 편리함을 제공합니다.

보통 컬렉션의 첫번째 값을 가져오거나, 특정 조건을 만족하는 데이터만 필터링을 하거나 중복데이터를 제거하거나 이러한 작업을 한결 더 편하게 가공해줍니다.

 

바로 예시부터 보겠습니다.

아래의 컬렉션을 기준으로 예제들을 진행하겠습니다.

 

예시데이터

name, jum이라는 문자열이 키값으로 해당 키값에 해당하는 데이터를 넣어놓은 LIST입니다.

List<HashMap<Object, Object>> list = new ArrayList<HashMap<Object, Object>>();
list.add(new HashMap<Object, Object>(){{put("name", "영희");put("jum", 95);}});
list.add(new HashMap<Object, Object>(){{put("name", "영수");put("jum", 80);}});
list.add(new HashMap<Object, Object>(){{put("name", "민수");put("jum", 75);}});
list.add(new HashMap<Object, Object>(){{put("name", "철수");put("jum", 79);}});
list.add(new HashMap<Object, Object>(){{put("name", "민희");put("jum", 85);}});
list.add(new HashMap<Object, Object>(){{put("name", "유리");put("jum", 40);}});
System.out.println("---- Original ----");
list.forEach(System.out::println);

6명의 학생 컬렉션

 

해당 list데이터를 점수가 80점 이상인 데이터만 처리하라고 하면 어떻게 해야할까요?

각각 HashMap데이터의 "jum"인 키를 조회하여 값이 80점 이상인 데이터만 새로운 컬렉션에 넣어주면 될겁니다.

 

반복문을 통한 필터링

아래 소스를 보시죠. forEach 람다식으로 표현하였습니다.

List<HashMap<Object, Object>> fliter_list = new ArrayList<HashMap<Object, Object>>();
list.forEach(x->{
  int jum = (int) x.get("jum");
  if(jum > 80) {
    fliter_list.add(x);
  }
});
System.out.println("---- Filtering ----");
fliter_list.forEach(System.out::println);

필터링한 데이터

80점 이상인 영희와 민희데이터만 가져온 걸 볼 수 있습니다.

 

 

stream filter

80점 이상인 데이터만 필터링하기

Stream<HashMap<Object, Object>> fliter_list = list.stream().filter(xx-> (int) xx.get("jum") > 80);
System.out.println("---- Filtering ----");
fliter_list.forEach(System.out::println);

stream filter 처리

위에서 복잡하게 80점 이상인 데이터만 호출하여 표출하던 부분이 filter를 통해 손 쉽게 가공이 되었습니다.

 

이번에는 80점 이상이면서 이름에 "영"이라는 String이 들어간 데이터를 필터링 해보겠습니다.

Stream<HashMap<Object, Object>> fliter_list = list.stream().filter(xx-> 
	(int) xx.get("jum") > 80 && xx.get("name").toString().contains("영")
);
System.out.println("---- Filtering ----");
fliter_list.forEach(System.out::println);

 

&&연산자를 통해 80점이상과 영이라는 String이 둘 조건이 만족되는 데이터만 필터링 된 것을 볼 수 있습니다.

둘중 하나만 만족해도 나오게 하려면 or 연산자인 || 으로 처리하면 됩니다.

 

 

stream을 사용하면서 유의해야 할 점은 최종연산자까지 사용을 해야 동작을 한다는 것입니다.

중간연산자(filter, peek, distinct, ...)까지만 정의하면 의미없는 코드가 되며, 최종연산(collect, forEach, count, ...)을 처리해야 그때부터 중간연산자들도 동작을 시작합니다.

 


중복제거하기 distinct

List<String> animals = Arrays.asList("dog", "cat", "dog", "cat", "monkey", "rabbit");
Stream<String> filter = animals.stream().distinct();
filter.forEach(System.out::println);

중복된 dog, cat의 문자열배열이 사라진 것을 볼 수 있다.

 

list내 map객체의 중복된 key값 제거는 단순하게 distinct를 활용하여 제거는 힘듭니다.

JAVA Functional 처리를 통한 필터링처리가 필요한데, 이부분은 추후 포스팅하도록 하겠습니다.

 

 

반응형