2021-01-11
우선 Stream 은 자바의 배열 / 리스트 / 맵 등의 컬렉션의 데이터들을 하나씩 참조하여 람다식으로 처리할 수 있는 반복자이다. 기존 자바 7 이전의 반복자 Iterator보다 보다 코드량이 줄었으며, 람다식의 사용으로 간결하고 편리해졌다고 볼 수 있다.
이제 코드를 통해 어떤식으로 사용이 되는지 알아보자.
package sStream;
public class People {
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
@Override
public int hashCode() {
return name.hashCode() + age;
}
}
▲ 위는 예제로 사용할 People이라는 클래스이다.
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("bbb", 35));
plist.add(new People("ccc", 45));
Stream<People> pstream = plist.stream();
pstream.forEach(info -> System.out.println(info.getName()));
}
}
우선 People을 타입으로 받는 list를 하나를 선언해주고 생성자를 통해 3가지의 객체를 넣어주었다. 이후 반복자 이용을 위한 Stream에 마찬가지로 People을 타입을 받게 생성해주고 리스트의 stream() 메서드를 통해 하나의 Stream 반복자를 선언해주면 된다.
이제 하나씩 데이터를 출력해주기위해 stream의 메서드인 forEach를 이용해 하나씩 꺼내 주면 된다. (여기서의 forEach는 for문의 forEach와 동일한 기능을 수행한다.) 이후 소괄호 안에 변수를 하나 선언해주고 람다식을 통해 해당 변수가 수행할 반복문을 코드로 작성해주면 된다. 해당 코드를 출력하면 아래와 같이 People 객체의 이름이 넣어준 순서대로 출력되는 것을 확인할 수 있다.
이제 해당 데이터를 필터링해 원하는 데이터만 추출하도록 해보자.
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", 45));
plist.add(new People("aaa", 55));
plist.add(new People("bbb", 35));
plist.add(new People("ccc", 45));
Stream<People> pstream = plist.stream();
double average = pstream
.filter(people -> people.getName().equals("aaa"))
.mapToInt(People :: getAge)
// p -> People.getAge
// 스트림의 요소를 다른 요소로 대체하는 작업
.average()
.getAsDouble();
System.out.println(String.format("%.2f", average));
}
}
리스트는 기존과 동일하게 People 클래스를 타입으로 가지고 있으며, filter를 사용하기 위해 일부로 이름이 "aaa"인 사람들을 다수 리스트에 넣어 주었다. 여기서 내가 원하는 데이터는"aaa라는 이름의 사람들의 평균나이는 어떻게 되느냐?"라는 것이다. 이를 위해 double형 변수 average를 선언해주고 여기에 Stream 변수인 pstream을 통해 하나의 평균값을 도출하도록 람다식을 선언하였다. 해당 람다식의 내용을 하나씩 살펴보자.
filter는 소괄호안에 변수명을 선언해주고 람다식으로 (->) 원하는 데이터를 추출하면 된다. 예제에서는 변수 poeple에 이름 중 "aaa"만 추출하였다.
mapToInt는 말그대로 인트형 자료구조로 맵핑하여 새로운 스트림을 만드는 것으로 소괄호 안의 내용(People :: getAge)은 주석에 달려 있듯이 람다식 p(변수명) -> People.getAge를 간략히 한 것이다.
average는 새롭게 추출한 스트림의 데이터들의 값을(여기서는 "aaa" 이름의 사람들의 나이)를 가지고 말그대로 평균값을 도출하게 된다.
getAsDouble는 최종집게 된 average의 값을 더블형 변수에 넣기 위해 추출하는 메서드로 생각하면 되며, 여기서 추출된 값은 처음에 선언한 변수 average에 담기게 된다.
이제 해당 필터링한 값을 출력해보면 아래와 같은 "aaa"라는 이름을 가진 사람들의 평균 나이 값이 출력되는 것을 확인할 수 있다.