TIL: 2024/04/25 - Java stream, 정렬

White 와잇·2024년 4월 25일

TIL

목록 보기
6/40
post-thumbnail

정리

자바 스트림 stream

  • 자료구조(String 포함)들을 stream 클래스로 변환
  • 원시형, 참조형에 따라 Stream<T> 사용 여부 다름
  • 원시형 배열(int[], long[], double[], ...)은 Stream 클래스가 아닌 IntStream 등의 클래스로 생성
  • 원시형 중 문자형 배열(char[])은 불가
    해결법: String으로 바꾸거나, Character 래퍼 클래스를 사용 (= 참조형으로 변경)
  • map 사용법: 스트림객체.map(매핑할 함수)
    자주 사용하는 매핑함수 형태는 람다로 바로 구현 또는 Class::method 를 입력, 주의점은 메서드 이름 옆에() 괄호는 넣지 않음
  • filter 사용법: map과 거의 동일, 함수가 predicate여야 함(Boolean 리턴)
  • stream -> list: .collect(Collectors.toList()) 를 이용해서 List로 반환
    바로 .toList()를 하면 되는 듯

정렬

  • 자료구조를 정렬 (배열, 컬렉션) -> String을 다이렉트로 정렬해주는 함수는 없는 듯(오늘 고민한 내용), 있다면 누군가 알려주십쇼 헤업미
  • Arrays.sort(배열, Comparator), Collections.sort(컬렉션, Comparator)
  • 사용법 C++과 유사 compare함수 넣듯이 Comparator(인터페이스)의 구현체를 넘김
  • 사용자가 Comparator 클래스/Comparable 인터페이스로 직접 구현한 클래스를 사용
  • 자주 사용되는 제공 Comparator/Comparable:
    Collections.reverseOrder(),
  • Comparator 익명 객체로 직접 구현 (Integer 타입) (내림차순 예시)
Collections.sort(myList, new Comparator<int>() {
    @Override
    public int compare(int a, int b) {
        return b - a;
    }
});
  • 람다식으로 한 줄에 사용하기 (내림차순) (Comparator 익명 클래스의 람다식)
Arrays.sort(arr, (a, b) -> b - a);
Collections.sort(list, (a, b) -> b - a);
  • Comparable은 인터페이스이므로 사용 클래스에 implements Comparable 하고,
    compareTo 메서드를 Override함 compareTo(T t) 매개변수 1개인 것은
    '매개변수로 들어온 값'과 this의 멤버를 비교(알아서 잘)
  • 주의점: 사용자 정의 compare는 정렬 배열(arr)이 원시형(int)은 안됨. 래퍼(Integer)사용, 생략(오름차순)시 int형 가능
  • 잘 설명된 정렬 참고 페이지: 배열 정렬, Comparable 정렬 방법, Comparator 정렬 방법

어려웠던 것들

  • IntStream을 정렬할 때 역정렬 Comparator.reverseOrder() 오류
    --> 알아내는 데 오래걸림⭐
    해결법: 박싱(boxing)
  • 문자열 정렬 문제: 프로그래머스 정수 내림차순으로 배치하기
import java.util.Arrays;
import java.util.Collections;

class Solution {
    public long solution(long n) {
        long answer = 0;
        String s = String.valueOf(n);
        String[] arr = s.split("");
        Arrays.sort(arr, Collections.reverseOrder());
        s = "";
        for (String a : arr) s += a;
        answer = Long.parseLong(s);
        return answer;
    }
}

--> 예전에 C++로 편하게 .sort() 했던 것들인데..... 4시간 동안 풀었음..

그 이유는 우선 스트림을 사용해보고자 했는데
스트림을 가공하면서 형변환 이슈로 꼬이는 것들이 많았고
아직 스트림 클래스의 형 분류?와 (자꾸 타입이 맞지 않다며 에러가 난다) 위의 박싱 이슈 같은.
map을 사용한 매핑방법으로 스트림 요소의 형태를 바꿔야 하나 고민하다가 ~ mapToInt, mapToObj... 같은걸 사용해야 하는건지도 헷갈리고, 또 정작 원하는 mapToChar는 없는 것 같고.. <- 여기에서 스트림 사용을 중단.

일단 컬렉션을 사용하지 않으려고 했음. 문제의 자료가 숫자 하나만 받는 것이어서 가장 작고 간단한, 가벼운 코드를 만들려고 한 것 때문.

(long -> String -> Int -> char[] -> String -> long)
"컬렉션을 사용하지 않고" 숫자를 문자단위의 분리(char[])를 거치는 데 이 따위의 형 변환을 해야 했음. 너무 비효율적인 거 아닌가해서, 애초에 가벼운 코드를 만들고 싶었는데 원하는 방향성이 아니게 됨

  1. 좋은 변환 메서드가 있지 않을까
  2. String 클래스에 문자 정렬 기능이 혹시라도 있지 않을까 (가능하다면 굉장히 쉽게 풀릴 것이다)

위 두 가지를 고민했었고 찾지 못했음 😠 Collection.sort()와 String[].sort()는 많은데!
char[].sort()도 있겠거니 하고 찾아 헤맸는데 왜 안되는 것인가.. 논리적으로 같은 정렬 방법을 적용하면 될 것 같은데 이게 안 된다고?
원시형들은 일단 내가 얻은 지식 안에서는 안될 것 같다는 결론을 내림

그래서 결국
str[]에 담을 데이터를 String[]에 담는 방법을 채택하였더니 구글 검색에서 많이 볼 수 있었던 Arrays.sort()로 해결함

결론

  • 정렬(sort)은 편하게 쓰기위해 컬렉션 또는 스트링 배열로 접근해야겠다
  • 스트림 공부 해야지(정확히는 타입 변환에 따른 차이에서 나오는 오류들?)
    스트림이 많은 자료구조를 다룰 수 있게 만들어지다 보니 경우마다 사용법이 다르다.
  • 좀 더 이해되려면 제네릭 이해도를 높여야 한다고 판단
  • 정렬 Comparable 구현 원리 공부
profile
웹개발 도전! 데브옵스 도전!

0개의 댓글