/ JAVAJUNGSUK

Ch14-26~29. 스트림 중간연산

자바의 정석 기초편

0. 목차



Chapter14. 람다와 스트림

Ch14 - 26. 스트림의 중간연산 : skip(), limit()

Ch14 - 27. 스트림의 중간연산 : filter(), distinct()

Ch14 - 28. 스트림의 중간연산 : sorted()

Ch14 - 29. 스트림의 중간연산 : Comparator의 메서드



Ch14 - 26. 스트림의 중간연산 : skip(), limit()


skip()

▷ 앞에서부터 n개 건너뛰기
Stream<T> skip(long n)



limit()

▷ maxSize 이후의 요소부터는 자르기
Stream<T> limit(long maxSize)



▶ 예시

skip(), limit()
IntStream intStream = IntStream.rangeClosed(1, 10); // 12345678910
intStream
.skip(3) // 123 -3칸 건너뛰고 시작→ 45678910
.limit(5) // 45678-여기서 부터 뒤는 LIMIT!→ 910
.forEach(System.out::print);



Ch14 - 27. 스트림의 중간연산 : filter(), distinct()


filter()

▷ 조건식을 주고, 조건에 맞지 않는 요소 제거
Stream<T> filter(Predicate<? super T> predicate)



distinct()

▷ 중복 제거
Stream<T> distinct()



▶ 예시

distinct()
IntStream intStream = IntStream.of(1, 2, 2, 3, 3, 4, 5, 5, 6,); // 123456
intStream
.distinct()
.forEach(System.out::print); // 중복 제거 후 123456 출력
filter()
IntStream intStream = IntStream.rangeClosed(1, 10); // 12345678910
intStream
.filter(i -> i % 2 == 0) // 2의 배수!
.forEach(System.out::print); // 246810
  • filter()는 중간 연산이므로 반복 가능
      IntStream intStream = IntStream.rangeClosed(1, 10); // 12345678910
      intStream
      .filter(i -> i % 2! == 0) // 2의 배수가 아니다!, 12345678910 → 13579
      .filter(i -> i % 3! == 0) // 3의 배수가 아니다!, 13579 → 157
      .forEach(System.out::print); // 157
        
      // && 사용하여 한 줄로 작성 가능
      filter(i -> i % 2! == 0 && i -> i % 3! == 0)
    





Ch14 - 28. 스트림의 중간연산 : sorted()


sorted()

▷ 스트림 요소의 기본 정렬(Comparable)로 정렬
▷ 정렬에 필요한 정렬기준을 주지 않으면 기본 정렬 적용
Stream<T> sorted()
▷ 지정 된 Comparator로 정렬
Stream<T> sorted(Comparator<? super T> comparator)



▶ 문자열 스트림 정렬 방법

▷ 출력 결과

CCaaabcdd

  • sorted()
     strStream.sorted() // 기본 정렬
     strStream.sorted(Comparator.naturalOrder()) // 기본 정렬
     strStream.sorted((s1, s2) -> s1.compareTo(s2)); // 람다식 가능
     strStream.sorted(String::compareTo); // 위의 람다식을 메서드 참조로 변경
    


▷ 출력 결과

ddccbaaaCC

  • sorted()
     strStream.sorted(Comparator.reverseOrder()) // 기본 정렬의 역순
     strStream.sorted(Comparator.<String>naturalOrder().reversed())
    


▷ 출력 결과

aaabCCccdd

  • sorted()
     strStream.sorted(String.CASE_INSENSITIVE_ORDER) // 대소문자 구분 안함
    
    • String.CASE_INSENSITIVE_ORDER
      // String 클래스가 Comparator를 만들어 두고 사용하라고 준 아이템(?) 같은 거
      statioc Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsenstiveComparator();
      


▷ 출력 결과

ddCCccbaaa

  • sorted()
     strStream.sorted(String.CASE_INSENSITIVE_ORDER.reversed()) // 대소문자 구분 안함의 역순
    


▷ 출력 결과

bddCCccaaa

  • sorted()
     strStream.sorted(Comparator.comparing(String::length)) // 길이 순 정렬
     strStream.sorted(Comparator.comparingInt(String::length)) // 오토박싱 안함
    


▷ 출력 결과

aaaddCCccb

  • sorted()
     strStream.sorted(Comparator.comparing(String::length).reversed()) // 길이 순 정렬의 역순
    



Ch14 - 29. 스트림의 중간연산 : Comparator의 메서드


▶ Comparator의 메서드 : comparing()

▷ comparing()으로 정렬 기준 제공
comparing(Function<T, U> keyExtractor)
comparing(Function<T, U> keyExtractor, Comparator<U> keyComparator)
▷ 예시
// 반별로 정렬
studentStream
.sorted(Comparator.comparing Student::getBan)
.forEach(System.out::println);



▶ Comparator의 메서드 : thenComparing()

▷ thenComparing()으로 추가 정렬 기준 제공
thenComparing(Comparator<T> other)
thenComparing(Function<T> keyExtractor)
thenComparing(Function<T, U> keyExtractor, Comparator<U> keyComp)
▷ 예시
studentStream
.sorted(Comparator.comparing Student::getBan) // 반별로 정렬
.thenComparing(Student::getTotalScore) // 총점 별로 정렬
.thenComparing(Student::getName) // 이름 별로 정렬
.forEach(System.out::println);


▶ 실습

▷ Stream 생성
Stream<Student> studentStream = Stream.of(
  new Student("이자바", 3, 300),
  new Student("김자바", 1, 200),
  new Student("안자바", 2, 100),
  new Student("박자바", 2, 150),
  new Student("소자바", 1, 200),
  new Student("나자바", 3, 290),
  new Student("감자바", 3, 180)
);
▷ 반별 정렬, 기본 정렬
studentStream.sorted(Comparator.comparing(Student::getBan) // 반별 정렬
.thenComparing(Comparator.naturalOrder())) // 기본 정렬
.forEach(System.out::println);
▷ Student 클래스 : 이름, 반, 성적
String name;
int ban;
int totalScore;

Student(String name, int ban, int totalScore) { 
  this.name = name;
  this.ban = ban;
  this.totalScore = totalScore;
}
▷ Student 클래스 : toString()
public String toString() { 
  return String.format("[%s, %d, %d]", name, ban, totalScore); 
}
▷ Student 클래스 : get()
String getName()     { return name; }
int getBan()         { return ban; }
int getTotalScore()  { return totalScore; }
▷ Student 클래스 : compareTo()
// 총점 내림차순을 기본 정렬로 작성
public int compareTo(Student s) { 
  return s.totalScore - this.totalScore;
}
▷ 전체
import java.util.*;
import java.util.stream.*;

class Ex14_5 {
	public static void main(String[] args) {
		Stream<Student> studentStream = Stream.of(
						new Student("이자바", 3, 300),
						new Student("김자바", 1, 200),
						new Student("안자바", 2, 100),
						new Student("박자바", 2, 150),
						new Student("소자바", 1, 200),
						new Student("나자바", 3, 290),
						new Student("감자바", 3, 180)
					);

		studentStream.sorted(Comparator.comparing(Student::getBan) // 반별 정렬
		 	.thenComparing(Comparator.naturalOrder())) // 기본 정렬
			.forEach(System.out::println);
	}
}

class Student implements Comparable<Student> {
	String name;
	int ban;
	int totalScore;
	
	Student(String name, int ban, int totalScore) { 
		this.name = name;
		this.ban = ban;
		this.totalScore =totalScore;
	}

	public String toString() { 
	   return String.format("[%s, %d, %d]", name, ban, totalScore); 
	}

	String getName()     { return name; }
	int getBan()         { return ban; }
	int getTotalScore()  { return totalScore; }

   // 총점 내림차순을 기본 정렬 작성
	public int compareTo(Student s) { 
		return s.totalScore - this.totalScore;
	}
}

// console
[김자바, 1, 200]
[소자바, 1, 200]
[박자바, 2, 150]
[안자바, 2, 100]
[이자바, 3, 300]
[나자바, 3, 290]
[감자바, 3, 180]