본문 바로가기
Java, JSP

[Java/자바] 스트림(Stream) 사용법

by LasBe 2022. 1. 25.
반응형

스트림(Stream)

스트림은 java8부터 추가된 배열이나 컬렉션의 요소(List, Map, Set)들을 더 편리하게 가공하고 처리하도록 해주는 반복자입니다.

 

람다식 사용과 연산 과정에서 불필요한 변수를 남기지 않기 때문에 코드가 간결해지고,

내부 반복자를 사용해 병렬처리가 쉽다는 장점이 있습니다.

 

처음 배울 땐 막막하고 무슨 소리인가 싶었지만 간단히 설명하자면

일반적인 배열로 중복을 제거하고 내림차순으로 정렬한 뒤 List의 형태로 반환한다고 했을 때,

  1. Set에 배열 값을 넣어 중복제거
  2. Set을 Iterator에 담기
  3. Iterator의 값을 리스트에 넣기
  4. List를 역정렬 후 반환

이러한 과정을 거치게 됩니다.

 

이 과정에선 많은 반복문과 코드량이 동반되지만, 스트림을 통해 처리한다면 단 한줄로 처리할 수 있습니다.

int[] arr = {1,2,3,4,5};

Array.stream(arr).boxed() // 스트림 생성
	.distinct() //중복 제거
    	.sorted(Comparator.reverseOrder()) //역정렬
	.collect(Collectors.toList()); //List 형태로 반환

 

위와 같이 스트림을 사용한다면 훨씬 단순하게 코딩할 수 있습니다.

 

데이터를 간단하고 편리하게 처리할 수 있도록 사용되는 스트림은 다양한 메소드가 존재합니다.

 

그 메소드 중에는 람다식을 이용해야 하는 상황들이 많아서, 람다식 사용법은 숙지하는게 좋습니다.

 

[Java/자바] 람다식(Lambda Expression), 함수형 인터페이스 사용법

람다식(Lambda Expression)이란 람다식이란 간단히 말해 메소드를 하나의 식으로 표현한 것입니다. 메소드를 람다식으로 표현하면 메소드의 이름이 필요없기 때문에, 람다식은 익명 클래스와 비슷한

lasbe.tistory.com

 

 

스트림 사용법

스트림의 사용은 크게 3단계로 구분지을 수 있습니다.

 

스트림 생성 ->  가공 및 연산 -> 반환

 

배열이나 컬렉션(List, Map) 형태를 스트림 형태로 생성한 뒤

데이터를 가공하거나 연산하는 메소드를 체이닝 형태로 이어주며 각 연산을 저장합니다.

중간 과정들이 끝나면 최종 결과를 사용자가 원하는 형태로 리턴해줍니다.

 

스트림에 대한 사용법과 메소드의 양은 글 하나에 모두 담기 힘들기때문에

주요 메소드와 컬렉션을 이용한 간단한 스트림 사용법을 알아보겠습니다.

 

주요 메소드

.count() 배열이나 컬렉션의 크기 리턴
.sorted()  /  .sorted(Comparator.reverseOrder()) 정렬 / 역정렬
.distince() 중복 삭제
.max(Type :: compare)  /  .min(Type :: compare)  최대, 최소 값
.average()  /  .sum() 평균 / 합계
.map((파라미터) -> 코드) 스트림 원소를 변환
.forEach((파라미터) -> {코드}) 각 인덱스의 값을 파라미터로 넘겨 코드를 반복 수행
filter(파라미터) -> {코드}) 조건에 부합하지 않는 값을 걸러낸다.
.reduce(값, 데이터타입::sum) 스트림의 값을 모두 하나로 합칠 때 사용
.collect(Collectors.toList()) / toList() -> toSet(), toMap()
스트림을 List(Set, Map) 타입으로 반환 
.getAsType() / Int, Long, Double, Float... 최종 값을 지정한 타입의 형태로 반환

 

 

예제 코드

class Member {
	public static int MALE = 0;
	public static int FEMALE = 1;
	private String name;
	private int sex;
	private int age;

	public Member(String name, int sex, int age) {
		this.name = name; this.sex = sex; this.age = age;
	}
	public String getName() { return name; }
	public int getSex() { return sex; }
	public int getAge() { return age; }
	
}

예제에서 사용될 클래스입니다.

 

멤버변수로 이름과 성별 나이를 갖고있고 getter 메소드를 통해 객체의 멤버변수를 리턴해줍니다.

 

List<Member> list = Arrays.asList(
		new Member("홍길동", Member.MALE, 30), 
		new Member("김나리", Member.FEMALE, 20),
		new Member("신용권", Member.MALE, 45), 
		new Member("박수미", Member.FEMALE, 27),
		new Member("홍길동", Member.MALE, 50));

리스트에 멤버 객체 5개를 넣어주겠습니다.

 

 

1) 40세 이하의 멤버 이름 추출하기

List<String> arr = list.stream() // 스트림 변환
	.filter(a -> a.getAge() < 40) // 40세 이하의 멤버들만 필터링
	.map(Member::getName) // 이름만 가져오기
	.sorted() // 정렬
	.collect(Collectors.toList());  // List 타입으로 반환

arr.stream()
	.forEach(System.out::println); // arr의 요소들을 전부 출력

list의 멤버들 중 40세 이하의 멤버 이름을 가져오는 코드입니다.

 

스트림 변환 -> 필터 -> 매핑 -> 정렬 -> 반환

작업의 순서대로 결과물들을 넘겨주며 최종 결과물을 반환합니다.

 

출력은 forEach를 통해 40세 이하 멤버 이름이 저장된 List의 객체를 모두 출력합니다.

 

 

2) 남자 멤버의 평균 나이 구하기

double ageAvg =list.stream() // 스트림 변환
    .filter(m->m.getSex() == Member.MALE) // 남자 멤버만 걸러내기
    .mapToInt(Member::getAge) // 스트림 요소를 int로 매핑
    .average() // 평균 구하기
    .getAsDouble(); // Double 타입으로 반환
		
System.out.println("남자 평균 나이 : "+ageAvg);

이번엔 average() 메소드의 연산을 위해 mapToInt로 나이 값을 정수 값으로 매핑해주었습니다.

 

그리곤 모든 중간 연산을 마친 뒤, getAsDouble() 메소드를 통해 Double 타입으로 최종 값을 반환했습니다.

 

더보기

자바 스트림, Stream, 컬렉션 스트림, 스트림 사용법, stream 사용법, 스트림 배열, 리스트 스트림

반응형

댓글


오픈 채팅