Java Stream API | JeongKeepsCalm

Java Stream API

Stream Pipeline(구조)

  • Source (소스): 컬렉션, 배열 등
  • Intermediate Operations(중간 처리): 0개 이상의 filter, map 등의 중간처리
  • Terminal Operation(종결 처리): Collect, reduce 등


IntStream

1
2
3
4
5
6
7
8
9
10
11
int[] intArr = {1, 2, 3, 4, 5};
// IntStream intStream = Stream.of(intArr);
IntStream intStream = Arrays.stream(intArr);
System.out.println("intStream.sum() : " + intStream.sum());
System.out.println("intStream.count() : " + intStream.count());
System.out.println("intStream.average() : " + intStream.average());

// 인덱스 반환
public int indexOf(Object o) {
        return IntStream.range(0, size).filter(i -> o.equals(elementData[i])).findFirst().orElse(-1);
}

IntStream 은 sum(), count(), average(), min(), max() 등 숫자 관련 함수를 제공한다.


Sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Stream<Student> studentStream = Stream.of(
        new Student("ojg",3,300),
        new Student("ldn",1,200),
        new Student("sns",2,100),
        new Student("ees",2,150),
        new Student("gxx",3,290),
        new Student("dwz",3,180)
);

// 반별로 정렬
// studentStream.sorted(Comparator.comparing(Student::getBan).reversed() 
studentStream.sorted(Comparator.comparing((Student s) -> s.getBan()).reversed() // 람다로 변경.
        .thenComparing(Comparator.naturalOrder())) // 기본 정렬
        .forEach(System.out::println);


Optional

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Optional<String> optStr = Optional.of("abcde");
Optional<Integer> optInt = optStr.map(String::length);

System.out.println("optStr : "+optStr.get()); // abcde
System.out.println("optInt : "+optInt.get()); // 5

int result1 = Optional.of("123").filter(x -> x.length() > 0).map(Integer::parseInt).get();
int result2 = Optional.of("").filter(x -> x.length() > 0).map(Integer::parseInt).orElse(-1); // 필터를 타지 않는다.

System.out.println("result1 : "+result1); // 123
System.out.println("result2 : "+result2); // -1

Optional.of("456").map(Integer::parseInt).ifPresent(x-> System.out.printf("result3 : %s%n",x)); // 456

OptionalInt optInt1 = OptionalInt.of(0); // 0 저장.
OptionalInt optInt2 = OptionalInt.empty(); // 빈 객체 저장.

System.out.println(optInt1); // OptionalInt[0]
System.out.println(optInt2); // OptionalInt.empty

System.out.println(optInt1.isPresent()); // true
System.out.println(optInt2.isPresent()); // false

System.out.println(optInt1.getAsInt()); // 0
System.out.println(optInt1.equals(optInt2)); // false           


allMatch, anyMatch

1
2
boolean b = Arrays.asList(-3, 23, 66, -7, 88).stream().allMatch(v -> v > 0); // false
boolean b2 = Arrays.asList(-3, 23, 66, -7, 88).stream().anyMatch(v -> v > 0); // true


reduce ( 이전 값과 연관 )

1
2
3
4
5
6
7
8
String greetings[] = { "hi", "hello", "안녕", "안녕하세요" };

// 람다식으로 직접 구현
System.out.println(Arrays.stream(greetings).reduce("", (s1, s2) -> {
  System.out.println(s1 + " : "+s2);
  if (s1.getBytes().length >= s2.getBytes().length) return s1; // 가장 긴 문자열 하나만 리턴한다.
  else return s2;
}));

reduce(“”, …) : 빈 문자로 초깃값 설정


1
2
3
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// numbers.reduce((x, y) -> (x + y)).ifPresent(s -> System.out.println("sum : " + s));
numbers.reduce(Integer::sum).ifPresent(s -> System.out.println("sum2 : " + s));


collect

  • Collector: 인터페이스
  • Collectors: 클래스 ( Collector 인터페이스 구현 )
  • collect(): 최종연산 ( 그룹별로 다루기위해 사용 )

joining

1
2
3
4
5
6
7
String[] stringArr = {"aaa", "bbb", "ccc", "ddd", "eee"};
String joined = Arrays.stream(stringArr).collect(Collectors.joining(","));
List<String> list = Arrays.stream(joined.split(",")).collect(Collectors.toList());
List<String> list2 = Arrays.stream(joined.split(",")).map(v -> "(" + v + ")").collect(Collectors.toList());

System.out.println(list);  // [aaa, bbb, ccc, ddd, eee]
System.out.println(list2); // [(aaa), (bbb), (ccc), (ddd), (eee)]


기본문제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// [문제 1] 1,2,3,4,5,6을 담고 있는 리스트를 만들고 역순 정렬 
// 1
List<Integer> list =  Arrays.asList(1, 2, 3, 4, 5, 6);
Collections.sort(list, (a, b) -> b.compareTo(a));
// 2
List<Integer> list = List.of(1, 2, 3, 4, 5, 6).stream().sorted((a, b) -> b - a).collect(Collectors.toList());

// [문제 2] 1~100숫자를 리스트에 담고 2와 3의 배수를 제거하고 남은 수에 곱하기 2
List<Integer> list = IntStream.rangeClosed(0, 100)
        .filter(v -> v % 2 != 0 && v % 3 != 0)
        .mapToObj(v -> v * 2)
        .collect(Collectors.toList());

// [문제 3] 3,1,6,7,2,3,6 정수 원소를 가진 리스트를 만들고 중복 제거 후, 정렬 한 뒤 리스트로 만들기
List.of(3, 1, 6, 7, 2, 3, 6).stream().distinct().sorted().collect(Collectors.toList());

// [문제 4] 스트림으로 로또번호 만들어서 리스트 만들기
// 1
IntStream ints = new Random().ints(1, 46);
List list = ints.distinct().limit(6).sorted().boxed().collect(Collectors.toList());
// 2
List<Integer> list = new Random().ints(6, 1, 46).boxed().collect(Collectors.toList());
// box() : IntStream 을 Stream<Integer> 로 변환

// [문제 5] "dd", "aaa", "CC", "cc", "b" 원소를 리스트에 담고 스트림으로 병렬처리하고 각 문자열의 합을 출력  
int sum = List.of("dd", "aaa", "CC", "cc", "b").stream().parallel().mapToInt(v -> v.length()).sum();

// [문제 6] 1~10 홀수만 스트림으로 출력 
// 1
List list = IntStream.iterate(1, v -> v+2).limit(5).boxed().collect(Collectors.toList());
// 2
List<Integer> list2 = IntStream.rangeClosed(1, 10).filter(v -> v % 2 != 0).boxed().collect(Collectors.toList());

// [문제 7] 파일배열에 확장자를 가져오고 중복제거한 후 대문자로 바꿔라 
File[] fileArr = {new File("Ex1.java")
                , new File("Ex1.bak")
                , new File("Ex2.java")
                , new File("Ex1")
                , new File("Ex1.txt")};

List list = Stream.of(fileArr).map(v -> v.getName())
        .filter(v -> v.indexOf(".") != -1)
        .map(v -> v.substring(v.indexOf(".") + 1))
        .map(String::toUpperCase)
        .distinct()
        .collect(Collectors.toList());

List<String> list = Arrays.stream(fileArr)
        .map(File::getName)
        .map(fileName -> {
            int index = fileName.lastIndexOf(".");
            return index == -1 ? "" : fileName.substring(index + 1);
        })
        .distinct()
        .filter(v -> !v.equals(""))
        .map(v -> v.toUpperCase())
        .collect(Collectors.toList());

// [문제 8] 소문자로 바꾸고 중복제거해서 단어 출력 
String[] lineArr = {"Believe or not It is true", "Do or do not There is no try"};
List<String> list = Arrays.stream(lineArr).flatMap(v -> Stream.of(v.split(" +"))) //  " +" : 하나 이상의 공백 (정규식)
        .peek(v -> System.out.println(v))
        .map(String::toLowerCase) // .map(v -> v.toLowerCase())
        .distinct()
        .collect(Collectors.toList());


코드 활용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// filter
List<CmmnDetailCode> chpList = chbrList.stream()
  .filter(x -> "00".equals(x.getCode().substring(2, x.getCode().length()))
        && !"0000".equals(x.getCode())
        && !x.getCode().matches(".*[a-zA-Z].*")
  )
  .collect(Collectors.toList());

List<CodeDetail> collect = codeList.stream()
  .filter(i -> i.getCode().startsWith("00", 2))
  .collect(Collectors.toList()); 

// groupingBy
Map<String, List<LectureHistoryResponseVO>> groupedByCategory = lectureList.stream().collect(Collectors.groupingBy(LectureHistoryResponseVO::getCategoryNo));
Collection<List<LectureHistoryResponseVO>> categoryList = groupedByCategory.values();

// sort
List<CoreAttachFileVO> fileResult = coreAttachFileService.selectAttachFileList(coreAttachFileVO).stream().sorted(Comparator.comparing(CoreAttachFileVO::getRegDt)).collect(Collectors.toList());

// forEach
list.stream().forEach(x -> x.setReStatus( x.getReStatus().equals("Y") ? "완료" : "대기"));

// sum
reception = lssVOS.stream().mapToInt(item -> Integer.parseInt(item.getReception())).sum();

// Map 활용
public List<Map<String, Object>>  selectList(Map<String, Object> param) {
  
  Map<String, String> keyToValue = new HashMap<>();

  keyToValue.put("person", "1");
  keyToValue.put("anonymity", "2");
  keyToValue.put("company", "3");  

  List<String> checkedList = keyToValue.entrySet().stream()
    .filter(v -> "1".equals(param.get(v.getKey())))
    .map(Map.Entry::getValue)
    .collect(Collectors.toList());  

  param.put("checkedList", checkedList);  

  return dao.selectList01(param);

}