2022-05-19(Java_Effective)

이상수·2022년 5월 23일
0

TIL Java/Git/etc

목록 보기
16/17
post-thumbnail
  1. 시작하게 된 계기 및 다짐 😮
  • 이번 코드스테이츠의 백엔드 엔지니어링 개발자 부트캠프에 참여하게 되면서 현직개발자 분들의 빠른 성장을 위한 조언 중 자신만의 블로그를 이용하여 배운 것 들을 정리하는게 많은 도움이 된다 하여 시작하게 되었다.

    • 그 날 배웠던 것을 길지 않아도 좋으니 정리하며 복습하는 습관 기르기
    • 주말에 다음주에 배울 내용들을 예습
    • 코딩 문제와 java코드들은 꾸준히 학습
  1. 학습 목표 😮
목표결과
enum(열거형) 이해 및 활용O
에너테이션 개념 및 사용 이유/활용O
람다(Lambda) 이해 및 사용법O
스트림의 특징과 사용목적 및 주요 메서드 활용O
  1. 정리

enum


열거형(enum) 
 - 서로 관련이 있는 것들을 모아서 그것들에 번호를 매겨놓은것
 - static변수 참조처럼, 따로 new를 통한 객체생성없이 열거형.상수명 으로도 호출가능

 ex) 
       enum 열거형이름{ 상수형1, 상수형2, 상수형3... } 
       열거형이름 열거형 변수 = 열거형이름.상수명;

열거 객체 메소드
 - name() : 열거 객체가 가지고 있는 문자열 리턴(정의시 상수이름과 동일)
 - ordinal() : 열거 객체의 순번을 리턴합니다.
 - compareTo() : 주어진 매개값과 비교해서 순천 차이를 리턴합니다.
 - valueOf(String name) : 주어진 문자열(name)의 열거 객체를 리턴합니다.
 - values() : 모든 열거 객체들을 배열로 리턴합니다. (열거 객체 배열)


public static final 문제점
 - final 키워드를 사용시, 상수명이 중복되는 경우가 발생 
 - Interface로 구현시, 이는 해결되지만 타입안정성에 문제가 생김
  ex) 의미적으로 비교할 수 없는 개념임에도 불구하고 비교가 되어 문제가 발생
 - 클래스로 구현시, 코드가 길어지고 switch문 사용 불가
   ==> switch문은 (기본타입과 enum타입만 사용가능, 사용자 정의타입 x)

enum 장점 
 - 상수명의 중복을 피할 수 있습니다.
 - 타입에 대한 안정성을 보장합니다.
 - 코드가 단순해지고 가독성이 좋아집니다.
 - switch문에 사용할 수 있습니다.






Annotation


에너테이션(Annotation)
 - 주석과 같은 개념으로, 프로그램에게 정보는 제공하는 역할
 - 런타임에 특정 기능을 수행하도록 정보를 제공
 - 프로그램을 빌드할 때 코드를 자동으로 생성할 수 있도록 정보를 제공
   ex) @Test // 에너테이션
        public void run(){};
 

표준 에너테이션 
 - 자바에서 기본제공 에너테이션
 1. @Override : 컴파일러에게 메서드를 오버라이딩하는 것이라고 알림
 2. @Deprecated : 	앞으로 사용하지 않을 대상을 알릴 때 사용
 3. @FunctionalInterface : 함수형 인터페이스라는 것을 알림
    ==> 함수형 인터페이스는 하나의 추상메서드만 존재해야함
    ==> default 메서드 : 기본적 제공, 원하면 오버라이딩 해서 사용가능
    ==> static 메서드 : 무조건 사용 필수
 4. @SuppressWarning : 컴파일러가 경고메세지를 나타내지 않음



메타 에너테이션 
 - ★에너테이션에 붙이는 에너테이션
 -- ”java.lang.annotation.ElementType.*”
     import문을 이용하여 ElementType.TYPE 대신 TYPE과 같이 간단히 작성
      ==> @Target({FIELD, TYPE, TYPE_USE})

 1. @Target : 애너테이션을 정의할 때 적용 대상을 지정하는데 사용한다.
    ``` FILED(멤버변수,열거형 상수), TYPE(클래스,인터페이스,열거형)
 2. @Documented : 애너테이션 정보를 javadoc으로 작성된 문서에 포함시킨다.
 3. @Inherited : 애너테이션이 하위 클래스에 상속되도록 한다.
 4. @Retention : 애너테이션이 유지되는 기간을 정하는데 사용한다.
 5. @Repeatable : 애너테이션을 반복해서 적용할 수 있게 한다.
   ==> @interface ToDos {    // 여러개의 ToDo애너테이션을 담을 컨테이너 애너테이션 ToDos
          ToDo[] value(); }      // ToDo애너테이션 배열 타입의 요소를 선언. 이름이 반드시 value여야 함  
   
   ==> @Repeatable(ToDos.class) // ToDo 애너테이션을 여러 번 반복해서 쓸 수 있게 한다.  
          @interface ToDo{  
          String value(); }

  ==> @ToDo("update test codes.")  
         @ToDo("override test methods") 

사용자 정의 에너테이션 
 -- import java.lang.annotation.*;
 - 인터페이스와 비슷하게 정의

 ex) 
     @Target(ElementType.FIELD)//애너테이션이 적용 가능한 대상을 FIELD로 정해줍니다.
     @Retention(RetentionPolicy.RUNTIME)//코드 실행시 까지 애너테이션이 유지되게 정해줍니다.
     @Documented //애너테이션 정보를 javadoc으로 작성된 문서에 포함시킨다.
      public @interface BackendFramework { //백엔드 프레임워크를 지정해주는 애너테이션을 작성합니다.
         enum Frameworks {SPRING, DJANGO, EXPRESS}

         Frameworks backendFramework() default Frameworks.DJANGO; }

     
      public class KimCoding {
	@BackendFramework(backendFramework = BackendFramework.Frameworks.SPRING)
	private String KimCodingBackend;}






Lambda


람다

- 함수 지향 언어, 코드가 매우 간결해짐
- 컬렉션요소 필터링/ 매핑해서 원하는 결과를 쉽게 집계
★ 람다식은 매개변수를 가지는 코드 블록이지만 런타임에 익명 구현 객체를 생성

 ex) ★★
      타입 변수명 = new 타입(){
              public void run() {..}           ==>       타입 변수명 = ()  -> { ... } ;     (람다식 형태)
       } 
      ★★

      // 1. 기본 작성
	(타입 매개변수) -> { ... }

      // 2. 매개변수가 1개 일 때, 매개변수 () 생략가능
	매개변수 -> { ... }

      // 3. 매개변수가 2개 이상이고, 리턴문만 존재할 때는 return을 생략가능
	(매개변수1, 매개변수2) -> 리턴값;
	(num1, num2) -> {return num1 + num2} // return문만 존재하므로
	(num1, num2) -> num1 + num2 // return 생략가능, 중괄호도 생략

      // 4. 매개변수가 2개 이상이고, 실행문을 실행하고 결과값을 리턴할 경우
	(매개변수1, 매개변수2) -> { ... };

      // {}안의 코드가 return문이 아니고한줄일 경우, {} 생략가능
         return 문만 존재할시, {}와 return 문 생략가능

    



함수형 인터페이스
 - 단하나의 추상메서드만을 포함하는 인터페이스

 ex) @FunctionalInterface
      public interface MyFunctionalInterface {                       
      public void accept();                             ==> MyFunctionalInterface example = () -> { ... };
      }                                                               -> example.accept();

   :  accept(); 실행시  {} 안의 코드 실행                            함수 오버라이딩 = (매개변수) -> {실행코드};
                                                                                    변수.함수명(매개변수 줄것)



메서드 레퍼런스 
 - 람다식에서 불필요한 매개변수를 제거하는 목적
 - 람다식과 마찬가지로, 인터페이스의 익명 구현 객체로 생성
 - 정적/인스턴스 메서드를 참조할 수 있고, 생성자 참조도 가능

1. 정적 메서드
 - 클래스 :: 메서드 

2. 인스턴스 메서드 
 - 객체를 생성한 뒤, 참조변수 뒤에 
 - 참조변수 :: 메서드     


  ex) 
        (left, right) -> Math.max(left, right);    ==>            Math :: max; 
   
         IntBinaryOperator operato = Math :: max;


         IntBinaryOperator operator;

         //static method
         operator = Calculator::staticMethod;
         System.out.println("정적메서드 결과 : " + operator.applyAsInt(3, 5));

         //instance method
         Calculator calculator = new Calculator();
         operator = calculator::instanceMethod;
         System.out.println("인스턴스 메서드 결과 : "+ operator.applyAsInt(3, 5));


3. 매개변수의 메서드 레퍼런스
 - 람다식의 매개변수를 사용하여 메서드를 호추 사용
 
 ex)
      (a,b) -> {a.instanceMethod(b);};         ==>           클래스::instanceMethod

4. 생성자 참조
 - 객체를 생성하고 리턴하도록 람다식의 생성자 참조로 대치 가능

 ex) (a,b) -> {return new 클래스(a,b);};      ==>            클래스 :: new






Stream

스트림
 - 배열,컬렉션의 저장요소를 하나씩 참조하여 람다식으로 처리할 수 있도록 해주는 반복자
 - 복잡한 연산 수행 및 가독성,재사용성이 높은 코드 작성
 - 스트림은 Read_only로 읽기만 할 뿐 변경 불가
 - 일회용으로써, 한번 사용하면 닫히므로, 필요하다면 새로운 스트림 생성 필요
 - 요소단위로 하나씩 스트림을 거쳐서 최종 연산까지


# 선언형 프로그래밍 
 - '어떻게' 수행하는지보다 '무엇을'수행하는지 관심을 두는 프로그래밍

# 내부반복자
 - 컬렉션 내부에서 요소들을 반복시키고 개발자는 요소당 처리해야할 코드만 제공하는 코드패턴
 - 어떻게 반복시킬지를 컬렉션에게 맡겨두어, 개발자는 요소 처리 코드에만 집중할 수 있다는 장점
 - 중간 연산에서는 매핑,필터링,정렬을 수행하고 최종 연산에서는 카운팅,평균,총합등의 집계 수행

# 외부반복자
 - 사용자가 코드를 이용해 for,while등을 이용해 반복하는 형태


파이프라인 구성(.)
 - 여러개의 스트림이 연결되어 있는 구조로, 최종 연산을 제외하고 모두 중간 연산 스트림이다.
 - 최종 연산이 시작되기 전까지 중간 연산들은 기다리다가 최종 연산이 시작되면 데이터의 흐름이 시작됨

# 리덕션
 - 대량의 데이터를 가공해서 축소하는 것, 합계,평균값,카운팅등이 리덕션의 결과물





스트림 코드

- Stream<type> stream_ = 스트림_만들_변수.stream();   :  스트림 으로 만들기
- Stream(type) stream_ = Stream.of("a","b","c") 
                                  Arrays.stream(new string[] {"a","b","c"});    : 스트림 생성


★★ boxed() : 원시타입 -> 참조/객체 타입으로 변환(배열)
- .filter() : 조건에 맞는 데이터만 정제하여 더 작은 컬렉션
- .distinct() : 중복된 요소 제거
- ★★.map() : 기존의 Stream요소들을 대체하는 연산, 인자로 함수형 인터페이스 funtion을 받음
   (mapToInt(), mapToLong(), mapToDouble()) 
- .flatMap() : 요소를 대체하는 복수 개의 요소들로 구성된 새로운 스트림 리턴 (1차원으로 평면화)
  # map은 스트림의 스트림(Stream<Stream>, flatMap은 스트림(Stream)을 반환 , 사진
- .sorted() : default로 오름차순으로 정렬되며 내림차순으로 하려면 Comparator.reverseOrder()을 이용
  # 클래스에 직접 비교 메서드를 작성하여 사용하여도 됨 (클래스.메서드(인스턴스::메서드(내부)))
- .peek() : 중간 연산 메서드로, 요소를 하나씩 돌면서 출력, 디버깅을 위함
  # forEach()는 최종연산이므로 한번만 사용가능하지만, 이는 중간 연산이라 여러번 가능


- forEach() :   스트림의 모든 요소 출력 , 요소를 하나씩 연산
- allMatch() : 모든 요소들이 주어진 predicate의 조건 만족하는지 조사
- anyMatch() : 최소한 한개의 요소가 매개값으로 만족하는지 조사
- noneMatch() : 모든 요소들이 만족하지 않는지 조사
- reduce(초기값, (a,b) -> a+b) : 최대 3개의 매개변수를 받고, 
                                         병렬 연산결과를 합치기 위함 
  # 위의 reduce는 sum()을 이용한 방법
- collect() : List,set,Map등으로 결과를 수집하고 싶을때, 일반적으로 List로 수집하는 경우가 많음
  (toList,toCollection,toMap(Function.identity() = 인자를 그대로 전달), joining("구분자")(String 한줄로)) 
- toArray() : Array로 반환 ()안에는 클래스::new 형식 or x -> new String[x]

---------
- sum()
- count()
- average()
- max()
- min()
==> 기본타입에 사용
---------

ex)
      long sum = Arrays.stream(intArr).sum();

      .filter(x -> x.startsWith("조건"))
      .map(s -> s.toUpperCase()) 
      .stream_.forEach(System.out::println);
      .allMatch(x -> x%2 == 0);
      .toArray(String[]::new)



스트림 리턴타입
-  Stream :                                                   소스 : 컬렉션 
- IntStream,LongStream,DoubleStream :                      배열
- IntStream :                                                         int 범위
- LongStreram :                                                     long 범위

ex) 
     IntStream stream_ = IntStream.range(4,10) ;   ==> 인트범위 스트림  4 ~9 

---




Optional<T> 
 - null값으로 인해 에러가 발생하는 현상을 객체 차원에서 효율적으로 방지하고자 도입
 - 모든 클래스를 담을 수 있는 final 클래스(상속 불가)
 - 객체 생성시 of() or ofNullable()을 사용 (참조변수의 값이 null일 가능성이 있다면 ofNullable()사용)
 - .isPresent() 를 이용하여 null인지 여부를 리턴


Optional 코드
 - .isPresent() : null인지 여부를 리턴
 - Optional.of() , ofNullable() : 객체 생성
 - .<타입>empty();  : 참조변수를 기본값으로 초기화
 - .get() : 해당 값 가져오기
 - orElse() : null 값일 경우 디폴트 값 지정가능
 - .map() : 스트림과 같은 형법

 ★★  Optionalt의 경우 객체 형식이므로 getAsInt(),getAsDouble()나 orElse()를 이용하여 기본타입으로 변환할 수 있음

ex) 

   public final class Optional<T> {
 	private final T value; // T타입의 참조변수       ==>  정의되어 있음
   }
   
   Optional<String> opt1 = Optional.ofNullable(null);
   System.out.println(opt1.isPresent());




--- 

컬렉션과 스트림의 차이점
 - 컬렉션 : 즉시수행 (Eager)
 - 스트림 : Lazy, Short-circuit( 지연,단락평가)
 - 스트림은 최종 연산을 호출해야 그제야 나머지 작업들이 처리됨
      






  1. 피드백 😮
  • 자바에서 많이 활용하는 enum,에너테이션에 추가적으로 lambda와 stream을 학습하였다. enum의 경우 기존에 배웠던 언어에서도 사용하는 개념이라 비교적 쉽게 이해할 수 있었는데 에너테이션의 경우 한번도 사용해 본적이 없고 이해하기도 쉽지 않은 개념이다. 현업에서 많은 사용이 있다하니 추가적으로 학습하며 코드를 작성할 때 @functionalInterface같은 비교적 쉽게 사용할 수 있는 것들은 사용해 봐야겠다.

  • Lambda의 경우 축약형 함수로, 코드를 간결하게 하기 위하여 사용하는데 아직 Java에 익숙해지지 않은 상태로 사용하려니 새로 언어를 배우는 것 같다. 이는 Java에 좀더 익숙해지면서 사용하여야 겠다. stream도 마찬가지로 자바에 익숙해지면서 사용해야 겠다.

  1. 앞으로 해야 될 것 😮
  • 매일 꾸준히 할 것
    • 꾸준히 velog 작성
    • Java 언어 및 Algorithm 공부(Coding-Test)
    • 틈틈히 운동 하기

  • 내일 해야 할 것
    • 파일 I/O 생성/조작
    • JVM 구조와 Thread 이해 ★
profile
Will be great Backend-developer

0개의 댓글