[TIL] 2021. 02.22

✍️이펙티브 자바 - 스트림(stream)]

1. 익명 클래스보다는 람다를 사용하라.

  • 함수 객체(function object) : 추상 메서드를 하나만 담은 인터페이스

  • 타입을 명시해야 코드가 더 명확할 때만 제외하고는 람다의 모든 매개변수 타입은 생략하자.

  • 코드 자체가 동작이 명확하지 않고 코드 라인이 길어지면 람다 지양

  • (낡은 기법) compartor를 익명 클래스로 사용

	Collections.sort(word, new Comparator<String>() {
    	public int compare(String s1, String s2) {
        	return Integer.compare(s1.length(), s2.length());
        }
    }
  • (추천 한다)람다식을 함수 객체로 사용
	Collections.sort(words,
    	(s1, s2) -> (Integer.compare(s1.length(), s2.length()));
  • 비교자 생성 메서드 혹은 List 인터페이스가 추가된 메서드 사용
	//비교자 생성 메서드 사용하기
	Collections.sort(words, comparingInt(String::length));
    	//List 인터페이스에 추가된 sort 메서드
	words.sort(comparingInt(String::length));
  • Enum는 상수별 클래스를 두는 것보다 열거타입에 인스턴스 필드를 두는 편이 좋다.
    //상수별 클래스 두는 방법
    public enum Operator {
	PLUS("+") {
    	   public double apply(double x, double y) { return x + y;};
        }
     	private final String symbol;
     	Operation (String symbol) { this.symbol = symbol;}

     	public abstract double apply(double x, double y);
    }
    // 함수 객체(람다)를 인스턴스 필드에 저장해 상수별 동작을 구현한 열거 타입
    public enum Operator {
		PLUS("+", (x, y) -> x + y); 	
		
 	   private final String symbol;
    	   private final DoubleBinaryOperator op;
       
    	Operation (String symbol, DoubleBinaryOperator op {
      		this.symbol = symbol;
        	this.op = op;
    	}
       
 	public double apply (double x, double y) {
    		return op.applyAsDouble(x, y);
    	}
    }
      

2. 람다보다는 메서드 참조를 사용하라.

  • 람다보다 더욱 간결하게 만드는 방법 : 메서드 참조(Method reference)
  • 장점 : 잘 드러내는 이름을 지어줄 수 있고 친절한 설명을 문서로 남길 수 있다.
  • 매개변수 수가 늘어날수록 메서드 참조로 제거 가능.
    //람다
    map.merge(key, 1, (count, incr) -> count + incr);
   
    //메서드 참조
    map.merge(key, 1, Integer::sum);
  • 람다가 메서드 참조보다 간결할 때가 있다
   //메서드 참조
   service.execute(GoshThisClassNameIsHumongous::action);
   //람다 
   service.execute(() -> action());
  • 메서드 참조의 유형 5가지
메서드 참조 유형같은 기능을 하는 람다
정적Integer::parseIntstr -> Integer.parseInt(str)
한정적(인스턴스)Integer.now()::isAfterInstant then = Instant.now();
비한정적(인스턴스)String::toLowerCasestr -> str.toLowerCase();
클래스 생성자TreeMap<K, V>::new() -> new TreeMap<K, V>()
배열의 생성자int[]::newlen -> new int[len]

🧮알고리즘 문제 회고

프로그래머스 - 순위 검색 풀이 과정

  • 1차 도전
    알고리즘 스터디의 지정 문제를 풀었다. 문제를 풀면서 느낀 것은 아직 개념이 부족한다는 것을 다시 한번 상기시켰다. 문제를 보고 1차적으로 생각한 것은 스트림으로 데이터 파싱을 해야겠다는 것이었다. 그래서 바로 문자열 배열info와 문자열 배열 query를 파싱해서 stream에 filter를 5개를 처리해서 작업했다ㅋㅋㅋㅋ. 정확성에서는 통과했지만 효율성에서는 모두 시간초과가 발생했다. 다시 한번 데이터를 확인해보니까 총 데이터를 처리할 경우 50억인데 반해 O(n)을 적용할 수 있는 데이터 수가 대략 10억(?)으로 알고 있다. 비효율적인 방법이었다.
  • 2차 도전
    도저히 떠오르지 않아 다른 블로그 글을 레퍼런스로 참고했다. 우선 자료구조를 HashMap을 선택했다. 우선적으로 각각의 모든 경우의 조합을 key로 구하고 그 값을 List<>를 사용해서 처리했다. 그리고 내부 List를 정렬하고 그 값을 이분 탐색하는 로직으로 구현한 방식이었다. 해당 로직대로 문제를 풀다보니 시간복잡도가 O(logN)이어서 효율성 테스트에서 통과했던 것 같다.
  • 알고리즘 스터디를 하면서 느끼는 것
    스터디를 하면서 느끼는 것은 나의 부족한 점을 계속해서 확인해볼 수 있는 것이다. 이번 문제를 풀면서 느낀 것은 아직 Map interface와 관련된 메서드를 잘 활용하지 못했다는 점이다. compute, computeIfAbsent, computeIfPresent, getOrDefault 메서드를 사용하는데도 생소해서 제대로 적용하지 못했고 막상 혼자서 BinarySearch 로직을 작성하는데 도중에 기억이 나지 않아서 계속해서 막혔다. 항상 알고리즘을 풀면서 느끼는 것이 푸는데 다시 풀거나 비슷한 것을 못푸는 문제였는데 아직도 개념이 단단하지 않은 것 같다. 그리고 느낀 것은 문제 해결도 중요하지만 기본적인 로직은 암기가 필요한 것 같다. 계속해서 알고리즘 문제를 정리하면서 핵심 알고리즘은 정리해서 암기하고 부족한 부분을 계속해서 정리해놓아야겠다.🔥🔥🔥

💪To-Do-List

  • 미션4 리뷰를 받았다🎉. 미션4수정하기.
  • 프로그래머스 레벨2 알고리즘 챌린지(3문제)
  • 스프링입문을 위한 자바 객체지향의 원리와 이해 3장
  • 자바의 정석 - 2.3. 스트림의 중간 연산부터 스트림 마무리 하기(하루만에 다 못봐...)
  • 이코테 내용 훑어보기

좋은 웹페이지 즐겨찾기