λ‚˜μ˜ λͺ¨μ–‘

018 | Java - Enum, Annotation, Lambda, Stream λ³Έλ¬Έ

SEB/TIL

018 | Java - Enum, Annotation, Lambda, Stream

kexon 2022. 7. 18. 22:31

πŸ’™ Enum

🀍 History of Enum

더보기
  • μ„œλ‘œ κ΄€λ ¨λœ μƒμˆ˜(λ³€ν•˜μ§€ μ•ŠλŠ” κ°’, final)λ“€μ˜ μ§‘ν•©
  • ν•œμ •λ˜μ–΄ λ³€ν•˜μ§€ μ•ŠλŠ” 데이터λ₯Ό λ‹€λ£¨λŠ” 데 μ‚¬μš©
// κ³„μ ˆ
public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int AUTUMN = 3;
public static final int WINTER = 4;

// ν”„λ ˆμž„μ›Œν¬
public static final int DJANGO  = 1;
public static final int SPRING  = 2;
// => μ»΄νŒŒμΌμ—λŸ¬. κ³„μ ˆμ˜ SPRINGκ³Ό 쀑볡 λ°œμƒ!
interface Seasons {
	int SPRING = 1, SUMMER = 2, AUTUMN = 3, WINTER = 4;
}

interface Frameworks {
	int DJANGO = 1, SPRING = 2, NEST = 3, EXPRESS = 4;
}

⇒ 쀑볡 μƒμˆ˜λͺ… λ¬Έμ œλŠ” ν”Όν•  수 μžˆμ§€λ§Œ νƒ€μž… μ•ˆμ •μ„± λ¬Έμ œκ°€ 생김

if(Seasons.SPRING == Frameworks.SPRING) { }

⇒ 의미적으둜 λ‹€λ₯Έ κ°œλ…μ΄μ§€λ§Œ, μœ„ λ‘˜μ„ λΉ„κ΅ν•˜λ©΄ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠμŒ.

이걸 ν•΄κ²°ν•΄μ£Όλ €λ©΄ μ„œλ‘œ λ‹€λ₯Έ 객체둜 λ§Œλ“€μ–΄μ€˜μ•Όλ¨

class Seasons {
    public static final Seasons SPRING = new Seasons();
    public static final Seasons SUMMER = new Seasons();
    public static final Seasons FALL   = new Seasons();
    public static final Seasons WINTER = new Seasons();
}

class Frameworks {
    public static final Frameworks DJANGO  = new Frameworks();
    public static final Frameworks SPRING  = new Frameworks();
    public static final Frameworks NEST    = new Frameworks();
    public static final Frameworks EXPRESS = new Frameworks();
}

⇒ μƒμˆ˜λͺ… 쀑볡, νƒ€μž… μ•ˆμ •μ„± 문제 ν•΄κ²° κ°€λŠ₯. But, μ½”λ“œ 길어짐. μ‚¬μš©μž μ •μ˜νƒ€μž…μ΄λΌ switch문에 μ‚¬μš© λΆˆκ°€

μ΄λž˜μ„œ λ‚˜μ˜¨κ²Œ enum

enum Seasons { SPRING, SUMMER, FALL, WINTER }
enum Frameworks { DJANGO, SPRING, NEST, EXPRESS }

🀍 Use Enum

더보기

μ—΄κ±°ν˜•μ˜ μ‚¬μš©

enum μ—΄κ±°ν˜•μ΄λ¦„ {μƒμˆ˜λͺ…1, μƒμˆ˜λͺ…2, μƒμˆ˜λͺ…3, ...}

μ˜ˆμ‹œ

eums Seasons {
	SPRING,  //μ •μˆ˜κ°’ 0 ν• λ‹Ή
	SUMMER,  //μ •μˆ˜κ°’ 1 ν• λ‹Ή
	AUTUMN,  //μ •μˆ˜κ°’ 2 ν• λ‹Ή
	WINTER   //μ •μˆ˜κ°’ 3 ν• λ‹Ή
}
  • μ—΄κ±°ν˜•μ— μ„ μ–Έλœ μƒμˆ˜μ— μ ‘κ·Όν•˜λŠ” 방법: μ—΄κ±°ν˜•μ΄λ¦„.μƒμˆ˜λͺ…
enum Seasons { SPRING, SUMMER, AUTUMN, WINTER }

public class EnumExample {
    public static void main(String[] args) {
        System.out.println(Seasons.SPRING); // SPRING
    }
}
  • μ°Έμ‘°λ³€μˆ˜ favouriteSeason에 Seasons.SPRING λ‹΄κΈ°
enum Seasons { SPRING, SUMMER, AUTUMN, WINTER }

public class EnumExample {
    public static void main(String[] args) {
        Seasons favoriteSeason = Seasons.SPRING;
        System.out.println(favoriteSeason); // SPRING
    }
}

βœ… Ref. 

πŸ’™ Annotation

🀍 About Annotation

더보기
  • “정보λ₯Ό 전달해쀄 λŒ€μƒ”에 λͺ©μ μ„ λ‘ 
  • ν”„λ‘œκ·Έλž˜λ° 언어에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠμœΌλ©° 개발자/ν”„λ‘œκ·Έλž¨μ—κ²Œ 정보 제곡

μ• λ„ˆν…Œμ΄μ…˜μ˜ μ—­ν• 

  • μ»΄νŒŒμΌλŸ¬μ—κ²Œ 정보 제곡 ⇒ 문법 μ—λŸ¬ 체크
  • ν”„λ‘œκ·Έλž¨ λΉŒλ“œ μ‹œ 정보 제곡 ⇒ μ½”λ“œ μžλ™ 생성
  • λŸ°νƒ€μž„μ—κ²Œ 정보 제곡 ⇒ νŠΉμ • κΈ°λŠ₯ μ‹€ν–‰

μ• λ„ˆν…Œμ΄μ…˜μ˜ μ’…λ₯˜

  • ν‘œμ€€ μ• λ„ˆν…Œμ΄μ…˜: μžλ°”μ—μ„œ κΈ°λ³Έ 제곡
  • 메타 μ• λ„ˆν…Œμ΄μ…˜: μ• λ„ˆν…Œμ΄μ…˜μ— λΆ™μ΄λŠ” μ• λ„ˆν…Œμ΄μ…˜
  • μ‚¬μš©μž μ •μ˜ μ• λ„ˆν…Œμ΄μ…˜

🀍 ν‘œμ€€ μ• λ„ˆν…Œμ΄μ…˜ (*)

더보기

@Override

  • λ©”μ„œλ“œ μ•žμ—λ§Œ 뢙일 수 있음
  • μ„ μ–Έν•œ λ©”μ„œλ“œκ°€ μƒμœ„ 클래슀의 λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©ν•˜λŠ” λ©”μ„œλ“œλΌλŠ” 것을 μ»΄νŒŒμΌλŸ¬μ—κ²Œ μ•Œλ €μ€Œ
class Super {
	void run() {}
}
class Sub extends Super {
	@Override
	void rnu() {} // 컴파일 μ—λŸ¬ - μ˜€νƒ€
}

@Deprecated

  • μ•žμœΌλ‘œ μ‚¬μš©ν•˜μ§€ μ•Šμ„ 것을 ꢈμž₯ν•˜λŠ” ν•„λ“œλ‚˜ λ©”μ„œλ“œμ— λΆ™μž„
class OldClass {
	@Deprecataed
	int oldField;

	@Deprecated
	int getOldField() { return oldField; }
}

β“μ™œ λ©”μ„œλ“œλ₯Ό μ—†μ• λŠ” 것 λŒ€μ‹  @deprecatedλ₯Ό μ‚¬μš©ν• κΉŒ?

β—μžλ°”λŠ” ν•˜μœ„ ν˜Έν™˜μ„±μ„ μ€‘μš”μ‹œ μ—¬κΉ€. ν•˜μœ„ 버전과 ν˜Έν™˜μ„± λ•Œλ¬Έμ— @deprecatedλ₯Ό μ‚¬μš©ν•˜λ―€λ‘œ μ•žμœΌλ‘œλŠ” μ‚¬μš©ν•˜μ§€ 말라고 μ•Œλ €μ£ΌλŠ” 것!

@SuppressWarnings

  • 컴파일 κ²½κ³  λ©”μ‹œμ§€λ₯Ό μ œμ™Έμ‹œν‚¬ λ•Œ μ‚¬μš©
  • @SuppressWarnings("all") // λͺ¨λ“  κ²½κ³  μ œμ™Έ
  • λ‘˜ μ΄μƒμ˜ κ²½κ³ λ₯Ό ν•œλ²ˆμ— μ œμ™Έ
  • @SuppressWarnings({"deprecation", "unused", "null"})

@FunctionalInterface

  • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ„ μ–Έν•  λ•Œ, μ»΄νŒŒμΌλŸ¬κ°€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ˜ 선언이 λ°”λ₯΄κ²Œ μ„ μ–Έλ˜μ—ˆλŠ” μ§€ 확인
    • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€: 단 ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œ κ°€μ Έμ•Ό 함
    @FunctionalInterface
    public interface Runnable {
    	public abstract void run (); // ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œ
    }
    
  • λͺ©μ : λžŒλ‹€μ‹ μ‚¬μš© (1:1 λ§€μΉ­)

🀍 메타 μ• λ„ˆν…Œμ΄μ…˜

더보기
  • μ• λ„ˆν…Œμ΄μ…˜μ„ μœ„ν•œ μ• λ„ˆν…Œμ΄μ…˜ 
  • μ• λ„ˆν…Œμ΄μ…˜μ˜ μ μš©λŒ€μƒ λ˜λŠ” μœ μ§€ 기간을 μ •ν•˜λŠ” λ“± μ• λ„ˆν…Œμ΄μ…˜μ„ μ •μ˜ν•˜λŠ” 데 μ‚¬μš©

@Target

  • μ• λ„ˆν…Œμ΄μ…˜ μ •μ˜ μ‹œ 적용 λŒ€μƒμ„ μ§€μ •ν•˜λŠ”λ° μ‚¬μš©
  • java.lang.annotation.ElementType
  • μ˜ˆμ‹œ
import static java.lang.annotation.ElementType.*; 
//import문을 μ΄μš©ν•˜μ—¬ ElementType.TYPE λŒ€μ‹  TYPEκ³Ό 같이 μž‘μ„± κ°€λŠ₯

@Target({FIELD, TYPE, TYPE_USE})	// μ μš©λŒ€μƒ: FIELD, TYPE
public @interface CustomAnnotation { }	// μ •μ˜: CustomAnnotation

@CustomAnnotation	// μ μš©λŒ€μƒμ΄ TYPE인 경우
class Main {
	@CustomAnnotation	// μ μš©λŒ€μƒμ΄ FIELD인 경우
	int i;
}

@Documented

  • μ• λ„ˆν…Œμ΄μ…˜μ— λŒ€ν•œ 정보가 javadoc으둜 μž‘μ„±ν•œ λ¬Έμ„œμ— ν¬ν•¨λ˜λ„λ‘ ν•˜λŠ” μ• λ„ˆν…Œμ΄μ…˜ μ„€μ •
  • μžλ°”μ—μ„œ μ œκ³΅ν•˜λŠ” ν‘œμ€€ μ• λ„ˆν…Œμ΄μ…˜κ³Ό 메타 μ• λ„ˆν…Œμ΄μ…˜ λͺ¨λ‘ @Documentedκ°€ 적용
    (@Override @SuppressWarningsλ₯Ό μ œμ™Έ)
@Documented
@Target(ElementType.Type)
public @interface CustomAnnotation { }

@Inherited

  • ν•˜μœ„ ν΄λž˜μŠ€κ°€ μ• λ„ˆν…Œμ΄μ…˜μ„ 상속 ⇒ μƒμœ„ ν΄λž˜μŠ€μ— 뢙은 μ• λ„ˆν…Œμ΄μ…˜λ“€μ΄ λ™μΌν•˜κ²Œ 적용
@Inherited // @SuperAnnotation이 ν•˜μœ„ ν΄λž˜μŠ€κΉŒμ§€ 적용
@interface SuperAnnotation{ }

@SuperAnnotation
class Super { }

class Sub extends Super{ } // Sub에 μ• λ„ˆν…Œμ΄μ…˜μ΄ 뢙은 κ²ƒμœΌλ‘œ 인식

@Retention

  • μ• λ„ˆν…Œμ΄μ…˜μ˜ 지속 μ‹œκ°„ κ²°μ •
  • μ• λ„ˆν…Œμ΄μ…˜ μœ μ§€μ •μ±…(μœ μ§€λ˜λŠ” κΈ°κ°„ μ§€μ • 속성)
    • SOURCE: μ†ŒμŠ€ νŒŒμΌμ— 쑴재. 클래슀 νŒŒμΌμ—λŠ” μ‘΄μž¬ν•˜μ§€ μ•ŠμŒ
    • CLASS: 클래슀 νŒŒμΌμ— 쑴재. μ‹€ν–‰ μ‹œ μ‚¬μš©λΆˆκ°€, κΈ°λ³Έκ°’
    • RUNTIME: 클래슀 νŒŒμΌμ— 쑴재. μ‹€ν–‰ μ‹œ μ‚¬μš© κ°€λŠ₯
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE) 
//μ˜€λ²„λΌμ΄λ”©μ΄ μ œλŒ€λ‘œ λ˜μ—ˆλŠ”μ§€ μ»΄νŒŒμΌλŸ¬κ°€ ν™•μΈν•˜λŠ” μš©λ„ 
//클래슀 νŒŒμΌμ— 남길 ν•„μš” 없이 μ»΄νŒŒμΌμ‹œμ—λ§Œ ν™•μΈν•˜κ³  사라짐
public @interface Override(){ }

⇒ μœ„ μ˜ˆμ œμ—μ„œ @OverrideλŠ” 컴파일러 μ‚¬μš© ν›„ 끝 ⇒ μ‹€ν–‰ μ‹œ μ‚¬μš© x

@Repeatable

  • μ• λ„ˆν…Œμ΄μ…˜ 반볡 μ‚¬μš© κ°€λŠ₯
  • μ‚¬μš©μž νƒ€μž… μ• λ„ˆν…Œμ΄μ…˜ μ •μ˜
@Repeatable(Works.class) // ToDo μ• λ„ˆν…Œμ΄μ…˜μ„ μ—¬λŸ¬ 번 λ°˜λ³΅ν•΄μ„œ μ“Έ 수 있게 ν•œλ‹€.  
@interface Work{  
    String value();  
}
  • 반볡 μ‚¬μš©
@Work("μ½”λ“œ μ—…λ°μ΄νŠΈ")  
@Work("λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©")  
class Main{ }
  • μ—¬λŸ¬λ²ˆ 적용 κ°€λŠ₯ ⇒ ν•˜λ‚˜λ‘œ λ¬Άμ–΄μ£ΌλŠ” 별도 μ• λ„ˆν…Œμ΄μ…˜ μž‘μ„± ν•„μš”
@interface Works {  // μ—¬λŸ¬κ°œμ˜ ToDoμ• λ„ˆν…Œμ΄μ…˜μ„ 담을 μ»¨ν…Œμ΄λ„ˆ μ• λ„ˆν…Œμ΄μ…˜ ToDos
    Work[] value(); 
}

@Repeatable(Works.class) // μ»¨ν…Œμ΄λ„ˆ μ• λ„ˆν…Œμ΄μ…˜ μ§€μ • 
@interface Work {
	String value();
}

🀍 μ‚¬μš©μž μ •μ˜ μ• λ„ˆν…Œμ΄μ…˜

더보기
  • μ‚¬μš©μž 직접 μ •μ˜ν•΄μ„œ μ‚¬μš©
@interface μ• λ„ˆν…Œμ΄μ…˜λͺ… { // μΈν„°νŽ˜μ΄μŠ€ μ•žμ— @기호λ₯Ό λΆ™μ—¬ μ •μ˜ 
	νƒ€μž… μš”μ†Œλͺ…(); // μ• λ„ˆν…Œμ΄μ…˜ μš”μ†Œ μ„ μ–Έ
}
  • java.lang.annotation μΈν„°νŽ˜μ΄μŠ€λ₯Ό 상속받기 λ•Œλ¬Έμ— λ‹€λ₯Έ ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό 상속 받을 수 μ—†μŒ

βœ… Ref. 

πŸ’™ Lambda

🀍 λžŒλ‹€μ‹

더보기
  • λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜μ˜ μ‹μœΌλ‘œ ν‘œν˜„ν•œ 것 ⇒ μ½”λ“œ κ°„κ²°, λͺ…ν™•
  • ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° 기법 지원
//κΈ°μ‘΄ λ©”μ„œλ“œ ν‘œν˜„ 방식
void sayhello() {
	System.out.println("HELLO!")
}

//μœ„μ˜ μ½”λ“œλ₯Ό λžŒλ‹€μ‹μœΌλ‘œ ν‘œν˜„ν•œ 식
() -> System.out.println("HELLO!")
  • νŠΉμ§•
    • λ°˜ν™˜νƒ€μž…κ³Ό 이름 μƒλž΅ κ°€λŠ₯ ⇒ 읡λͺ…ν•¨μˆ˜(anonymous function)
    • λ©”μ„œλ“œ 바디에 싀행문이 ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•  경우 μ€‘κ΄„ν˜Έ μƒλž΅ κ°€λŠ₯
    • λ§€κ°œλ³€μˆ˜ νƒ€μž… μœ μΆ” κ°€λŠ₯ν•  경우 λ§€κ°œλ³€μˆ˜ νƒ€μž… μƒλž΅ κ°€λŠ₯
    • 읡λͺ…객체 → μ„ μ–Έκ³Ό λ™μ‹œμ— 생성

🀍 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

더보기
  • μžλ°”μ—μ„œ ν•¨μˆ˜λŠ” λ°˜λ“œμ‹œ 클래슀 μ•ˆμ—μ„œ μ •μ˜ ⇒ λ©”μ„œλ“œ 독립적 x
  • λžŒλ‹€μ‹ → 객체 ⇒ 이름이 μ—†κΈ° λ•Œλ¬Έμ— 읡λͺ… 클래슀
    • 읡λͺ…ν΄λž˜μŠ€: κ°μ²΄μ˜ μ„ μ–Έκ³Ό 생성을 λ™μ‹œμ— 함
      단 ν•˜λ‚˜μ˜ 객체만 μƒμ„±ν•˜κ³  단 ν•œλ²ˆλ§Œ μ‚¬μš©λ˜λŠ” 일회용 클래슀
public class LamdaEx {
    public static void main(String[] args) {
		   /* Object obj = new Object() {
            int sum(int num1, int num2) {
                return num1 + num1;
            }
        };
			*/ 
		FunctionEx exFunction = (num1, num2) -> num1 + num2
		System.out.println(exFunction.sum(10,15))
}

@FunctionalInterface // μΈν„°νŽ˜μ΄μŠ€κ°€ λ°”λ₯΄κ²Œ μ •μ˜λ˜μ—ˆλŠ”μ§€ μ»΄νŒŒμΌλŸ¬κ°€ 확인할 수 있게 ..
interface FunctionEx {
		public abstract int sum(int num1, int num2);
}
  • κΈ°μ‘΄ μΈν„°νŽ˜μ΄μŠ€ 문법을 ν™œμš©ν•˜μ—¬ λžŒλ‹€μ‹μ„ λ‹€λ£¨λŠ” 것
    • κ°€λŠ₯ν•œ 이유? λžŒλ‹€μ‹λ„ κ²°κ΅­ ν•˜λ‚˜μ˜ 객체이기 λ•Œλ¬Έ → μΈν„°νŽ˜μ΄μŠ€μ— μ •μ˜λœ μΆ”μƒλ©”μ„œλ“œ κ΅¬ν˜„ κ°€λŠ₯
  • λžŒλ‹€μ‹ : μΈν„°νŽ˜μ΄μŠ€ λ©”μ„œλ“œ = 1 : 1
@FunctionalInterface
public interface FunctionalInterface {
    public int accept(int x, int y);
}
import static java.lang.Integer.sum;

public class FunctionalInterfaceEx {
    public static void main(String[] args) throws Exception {
        FunctionalInterface ex;

        ex = (x, y) -> {
            int result = x + y;
            return result;
        };
        ex = (x, y) -> { return x + y; };
        ex = (x, y) -> x + y;
        ex = (x, y) -> sum(x, y);
    }

    public static int sum(int x, int y){
        return x + y;
    }
}

/* 좜λ ₯: λ‹€ 7*/

🀍 λ©”μ„œλ“œ 레퍼런슀

더보기
  • λžŒλ‹€μ‹μ—μ„œ λΆˆν•„μš”ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό μ œκ±°ν•  λ•Œ 주둜 μ‚¬μš©
    ⇒ λžŒλ‹€μ‹μœΌλ‘œ 간단해진 읡λͺ… 객체λ₯Ό 더! κ°„λ‹¨ν•˜κ²Œ! μ‚¬μš©
(left, right) -> Math.max(left, right);

// μœ„μ˜ λ©”μ„œλ“œλ₯Ό μ°Έμ‘° λ©”μ„œλ“œλ‘œ λ³€κ²½
// ν΄λž˜μŠ€μ΄λ¦„ :: λ©”μ„œλ“œμ΄λ¦„
Math :: max

정적 λ©”μ„œλ“œμ™€ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ μ°Έμ‘°

  • 정적 λ©”μ„œλ“œ μ°Έμ‘°
클래슀 :: μ •μ λ©”μ„œλ“œλͺ…
  • μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ μ°Έμ‘°
μ°Έμ‘°λ³€μˆ˜ :: μΈμŠ€ν„΄μŠ€λ©”μ„œλ“œλͺ…

 μ˜ˆμ‹œ

// Calculator.java

public class Calculator {
    public static int staticMethod(int x, int y) {
        return x + y;
    }

    public int instanceMethod(int x, int y) {
        return x * y;
    }
}
import java.util.function.IntBinaryOperator;

public class MethodReferences {
    public static void main(String[] args) {
        IntBinaryOperator operator;

        /*  μ •μ λ©”μ„œλ“œ
         * ν΄λž˜μŠ€μ΄λ¦„ :: λ©”μ„œλ“œμ΄λ¦„
         */
        operator = Calculator::staticMethod;
        System.out.println("μ •μ λ©”μ„œλ“œ: " + operator.applyAsInt(3, 5));

        /*  μΈμŠ€ν„΄μŠ€λ©”μ„œλ“œ
         * μΈμŠ€ν„΄μŠ€μ΄λ¦„ :: λ©”μ„œλ“œμ΄λ¦„
         */
        Calculator calculator = new Calculator();
        operator = calculator::instanceMethod;
        System.out.println("μΈμŠ€ν„΄μŠ€λ©”μ„œλ“œ: " + operator.applyAsInt(3, 5));
    }
}

μƒμ„±μž μ°Έμ‘°

  • μƒμ„±μž μ°Έμ‘° == 객체생성
  • 객체 생성 & 리턴 λžŒλ‹€μ‹ ⇒ μƒμ„±μž 참쑰둜 λŒ€μΉ˜ κ°€λŠ₯
(a, b) -> { return new 클래슀(a, b); };
  • μƒμ„±μž 참쑰둜 ν‘œν˜„
클래슀 :: new

βœ… Ref. 

더보기

πŸ’™ Stream

🀍 Stream νŠΉμ§•

더보기
  • 슀트림: 데이터λ₯Ό μ—°μ†μ μœΌλ‘œ μ „λ‹¬ν•˜λŠ” ν†΅λ‘œ
  • λ°°μ—΄, μ»¬λ ‰μ…˜μ˜ μ €μž₯μš”μ†Œλ₯Ό ν•˜λ‚˜μ”© μ°Έμ‘°ν•΄μ„œ λžŒλ‹€μ‹μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” 반볡자
  • λ‹€μ–‘ν•œ 데이터 μ†ŒμŠ€(List, Set, Map, λ°°μ—΄ λ“±)λ‘œλΆ€ν„° μŠ€νŠΈλ¦Όμ„ λ§Œλ“€κ³ , ν‘œμ€€ν™”λœ λ°©λ²•μœΌλ‘œ λ‹€λ£° 수 μž‡μŒ

μ„ μ–Έν˜•μœΌλ‘œ 데이터 μ†ŒμŠ€ 처리

  • “무엇"을 μˆ˜ν–‰ν•˜λŠ”μ§€κ°€ μ€‘μš”
  • λ‚΄λΆ€ λ™μž‘ 원리λ₯Ό λͺ°λΌλ„ μ½”λ“œκ°€ 무슨 일을 ν•˜λŠ”μ§€ 이해 κ°€λŠ₯

μ˜ˆμ‹œ

  • List에 μžˆλŠ” μˆ«μžλ“€ 쀑 4보닀 큰 짝수 합계 κ΅¬ν•˜κΈ°
import java.util.List;

public class ImperativeProgrammingEx{
    public static void main(String[] args){
        List<Integer> numbers = List.of(1, 3, 6, 7, 8, 11);

	// λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°
        int sum = 0;
        for(int number : numbers) {
            if(number > 4 && (number % 2 == 0)) {
                sum += number;
            }
        }

        // μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ° - 슀트림
        int sum = numbers.stream()
                         .filter(number -> number > 4 && (number % 2 == 0))
                         .mapToInt(number -> number)
                         .sum();
    }
}

λžŒλ‹€μ‹μœΌλ‘œ μš”μ†Œ 처리 μ½”λ“œ 제곡

  • 슀트림이 μ œκ³΅ν•˜λŠ” λŒ€λΆ€λΆ„μ˜ μš”μ†Œ 처리 λ©”μ„œλ“œ ⇒ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ λ§€κ°œνƒ€μž…μ„ 가짐
  • ⇒ λžŒλ‹€μ‹ λ˜λŠ” λ©”μ„œλ“œ μ°Έμ‘°λ₯Ό μ΄μš©ν•΄μ„œ μš”μ†Œ 처리 λ‚΄μš©μ„ λ§€κ°œκ°’μœΌλ‘œ 전달할 수 있음
stream.forEach(s -> {
    String name = s.getName();
    int score = s.getScore();
    System.out.println(name + ": " + score);
});

λ‚΄λΆ€ 반볡자의 μ‚¬μš©μœΌλ‘œ 병렬 μ²˜λ¦¬μ— 용이

  • μ™ΈλΆ€λ°˜λ³΅μž(external iterator)
    • κ°œλ°œμžκ°€ μ½”λ“œλ‘œ 직접 μ»¬λ ‰μ…˜μ˜ μš”μ†Œλ₯Ό λ°˜λ³΅ν•΄μ„œ κ°€μ Έμ˜€λŠ” μ½”λ“œ νŒ¨ν„΄
    • indexλ₯Ό μ‚¬μš©ν•˜λŠ” forλ¬Έ, iteratorλ₯Ό μ΄μš©ν•˜λŠ” whileλ¬Έ
  • λ‚΄λΆ€λ°˜λ³΅μž(internal iterator)
    • μ»¬λ ‰μ…˜ λ‚΄λΆ€: μš”μ†Œ 반볡 / 개발자: μš”μ†Œ λ‹Ή μ²˜λ¦¬ν•΄μ•Ό ν•  μ½”λ“œλ§Œ μ œκ³΅ν•˜λŠ” μ½”λ“œ νŒ¨ν„΄
    • 이점
      • μš”μ†Œ λ°˜λ³΅μ€ μ»¬λ ‰μ…˜μ—κ²Œ, κ°œλ°œμžλŠ” μš”μ†Œ 처리 μ½”λ“œμ— 집쀑
      • μš”μ†Œ 반볡 μˆœμ„œ λ³€κ²½, λ©€ν‹°μ½”μ–΄ CPU μ΅œλŒ€ν•œ ν™œμš©
        ⇒ μš”μ†Œλ“€μ„ λΆ„λ°°μ‹œμΌœ 병렬 μž‘μ—…μ„ λ„μ™€μ£Όλ―€λ‘œ 효율적인 μš”μ†Œ 반볡 κ°€λŠ₯
        • 병렬 슀트림 μ‚¬μš©: 슀트림 parallel() λ©”μ„œλ“œ μ‚¬μš©

쀑간 μ—°μ‚°κ³Ό μ΅œμ’… μ—°μ‚°

  • μŠ€νŠΈλ¦Όμ€ μ»¬λ ‰μ…˜μ˜ μš”μ†Œμ— λŒ€ν•΄ 쀑간 μ—°μ‚°κ³Ό μ΅œμ’… 연산을 μˆ˜ν–‰ν•  수 있음
    • 쀑간 μ—°μ‚°: λ§€ν•‘, 필터링, μ •λ ¬ 등을 μˆ˜ν–‰
    • μ΅œμ’… μ—°μ‚°: 반볡, μΉ΄μš΄νŒ…, 평균, 총합 λ“±μ˜ 집계 μˆ˜ν–‰
  • 예λ₯Ό λ“€μ–΄ 학생 객체λ₯Ό μš”μ†Œλ‘œ κ°€μ§€λŠ” μ»¬λ ‰μ…˜μ΄ μžˆλ‹€κ³  κ°€μ •ν•  λ•Œ,
    • 쀑간 μ—°μ‚°: ν•™μƒμ˜ 점수λ₯Ό 좜λ ₯
    • μ΅œμ’… μ—°μ‚°: 점수의 평균값을 μ‚°μΆœ

🀍 νŒŒμ΄ν”„λΌμΈ

더보기
  • λ¦¬λ•μ…˜(Reduction): λŒ€λŸ‰μ˜ 데이터λ₯Ό 가곡해 μΆ•μ†Œν•˜λŠ” 것
    • κ²°κ³Όλ¬Ό: λ°μ΄ν„°μ˜ 합계, 평균값, μΉ΄μš΄νŒ…, μ΅œλŒ€κ°’, μ΅œμ†Œκ°’ λ“±

νŒŒμ΄ν”„λΌμΈ

  • ꡬ쑰: μ—¬λŸ¬κ°œμ˜ 슀트림이 μ—°κ²°
  • λͺ¨λ‘ 쀑간 μ—°μ‚° 슀트림(μ΅œμ’… μ—°μ‚° μ œμ™Έ)
쀑간 슀트림이 생성될 λ•Œ μš”μ†Œλ“€μ΄ λ°”λ‘œ 쀑간 μ—°μ‚°(필터링, λ§€ν•‘, μ •λ ¬)λ˜λŠ” 것이 μ•„λ‹ˆλΌ μ΅œμ’… 연산이 μ‹œμž‘λ˜κΈ° μ „κΉŒμ§€λŠ” μ§€μ—°λ˜κ³ , μ΅œμ’… 연산이 μ‹œμž‘λ  λ•Œ μ»¬λ ‰μ…˜μ˜ μš”μ†Œκ°€ ν•˜λ‚˜μ”© 쀑간 μŠ€νŠΈλ¦Όμ—μ„œ μ—°μ‚°λ˜κ³  μ΅œμ’… μ—°μ‚°κΉŒμ§€ 였게 됨

🀍 슀트림 생성, 쀑간 μ—°μ‚°, μ΅œμ’… μ—°μ‚°

더보기

슀트림 생성

  • stream(): Collection μΈν„°νŽ˜μ΄μŠ€μ— μ •μ˜
    Collection μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ 객체(List, Set λ“±)듀은 λͺ¨λ‘ 이 λ©”μ„œλ“œλ‘œ 슀트림 생성 κ°€λŠ₯
  • stream() μ‚¬μš© ⇒ ν•΄λ‹Ή Collection의 객체 μ†ŒμŠ€λ‘œ ν•˜λŠ” Stream λ°˜ν™˜
  • 슀트림 μ‚¬μš© μ‹œ 주의점
    • Read-only
    • Disposable

쀑간 μ—°μ‚°

  • 쀑간 연산은 μ—°μ‚° κ²°κ³Όλ₯Ό 슀트림으둜 λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ— μ—°μ†ν•΄μ„œ μ—¬λŸ¬ 번 μˆ˜ν–‰ κ°€λŠ₯

필터링 - filter(), distinct()

  • filter(): 슀트림 쑰건에 λ§žλŠ” λ°μ΄ν„°λ§Œ 필터링
  • distinct(): 슀트림 μš”μ†Œ 쀑볡 제거

λ§€ν•‘ - map()

  • map(): κΈ°μ‘΄ Stream μš”μ†Œ → μƒˆλ‘œμš΄ Stream λŒ€μ²΄
    ⇒ 슀트림의 슀트림 λ°˜ν™˜
  • flatMap(): μš”μ†Œλ₯Ό λŒ€μ²΄ν•˜λŠ” 볡수 개의 μš”μ†Œλ“€λ‘œ κ΅¬μ„±λœ μƒˆλ‘œμš΄ 슀트림 리턴
    ⇒ 슀트림 λ°˜ν™˜

μ •λ ¬ - sorted()

  • Stream μš”μ†Œ μ •λ ¬
  • νŒŒλΌλ―Έν„°λ‘œ Comparator λ„˜κΈ°κΈ° κ°€λŠ₯
    • μ˜€λ¦„μ°¨μˆœ: Comparator 인자 없이 호좜
    • λ‚΄λ¦Όμ°¨μˆœ: reverseOrder μ‚¬μš©
list.stream()
    .sorted()	// μ˜€λ¦„μ°¨μˆœ
    .forEach(n -> System.out.println(n));
System.out.println();

list.stream()
    .sorted(Comparator.reverseOrder())	// λ‚΄λ¦Όμ°¨μˆœ
    .forEach(n -> System.out.println(n));

μ—°μ‚° κ²°κ³Ό 확인 - peek()

  • μ—°μ‚° 쀑간에 κ²°κ³Όλ₯Ό ν™•μΈν•˜μ—¬ λ””λ²„κΉ…ν•˜λ €κ³  ν•  λ•Œ μ‚¬μš©
intStream
	.filter(a -> a%2 ==0)
	.peek(n-> System.out.println(n))
	.sum();

μ΅œμ’… μ—°μ‚°

μ—°μ‚° κ²°κ³Ό 확인 - forEach()

  • νŒŒμ΄ν”„λΌμΈ λ§ˆμ§€λ§‰μ—μ„œ μš”μ†Œλ₯Ό ν•˜λ‚˜μ”© μ—°μ‚°
intStream
	.filter(a -> a%2 ==0)
	.forEach(n -> System.out.println(n));

λ§€μΉ­ - match()

  • Stream μš”μ†Œλ“€μ΄ νŠΉμ •ν•œ 쑰건을 μΆ©μ‘±ν•˜λŠ”μ§€ 검사
  • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ Predicate둜 ν•΄λ‹Ή 쑰건을 λ§Œμ‘±ν•˜λŠ”μ§€ 검사 → boolean λ°˜ν™˜
  • μ’…λ₯˜
    • allMatch(): λͺ¨λ“  μš”μ†Œλ“€μ΄ λ§€κ°œκ°’μœΌλ‘œ μ£Όμ–΄μ§„ Predicate 쑰건을 λ§Œμ‘±ν•˜λŠ”μ§€ 검사
    • anyMatch(): μ΅œμ†Œν•œ ν•œ 개의 μš”μ†Œκ°€ λ§€κ°œκ°’μœΌλ‘œ μ£Όμ–΄μ§„ Predicate 쑰건을 λ§Œμ‘±ν•˜λŠ”μ§€ 검사
    • noneMatch(): λͺ¨λ“  μš”μ†Œλ“€μ΄ λ§€κ°œκ°’μœΌλ‘œ μ£Όμ–΄μ§„ Predicate의 쑰건을 λ§Œμ‘±ν•˜μ§€ μ•ŠλŠ”μ§€ 검사
int[] intArr = {2,4,6};
boolean result = Arrays.stream(intArr).allMatch(a -> a % 2 == 0);
System.out.println("λͺ¨λ‘ 2의 λ°°μˆ˜μΈκ°€? " + result);			// true

result = Arrays.stream(intArr).anyMatch(a -> a % 3 == 0);
System.out.println("ν•˜λ‚˜λΌλ„ 3의 λ°°μˆ˜κ°€ μžˆλŠ”κ°€? " + result);		// true

result = Arrays.stream(intArr).noneMatch(a -> a % 3 == 0);
System.out.println("3의 λ°°μˆ˜κ°€ μ—†λŠ”κ°€? " + result);			// false

κΈ°λ³Έ 집계 - sum(), count(), average(), max(), min()

  • μš”μ†Œλ“€μ„ μ—°μ‚°ν•˜μ—¬ ν•˜λ‚˜μ˜ κ°’μœΌλ‘œ μ‚°μΆœν•˜λŠ” 것
int[] intArr = {1,2,3,4,5};

long count = Arrays.stream(intArr).count();
System.out.println("intArr의 전체 μš”μ†Œ 개수: " + count);

long sum = Arrays.stream(intArr).sum();
System.out.println("intArr의 전체 μš”μ†Œ ν•©: " + sum);

double avg = Arrays.stream(intArr).average().getAsDouble();
System.out.println("전체 μš”μ†Œμ˜ 평균값: " + avg);

int max = Arrays.stream(intArr).max().getAsInt();
System.out.println("μ΅œλŒ€κ°’: " + max);

int min = Arrays.stream(intArr).min().getAsInt();
System.out.println("μ΅œμ†Œκ°’: " + min);

int first = Arrays.stream(intArr).findFirst().getAsInt();
System.out.println("λ°°μ—΄μ˜ 첫번째 μš”μ†Œ: " + first);

λ‹€μ–‘ν•œ 집계 κ²°κ³Όλ¬Ό - reduce()

  • λˆ„μ ν•˜μ—¬ ν•˜λ‚˜λ‘œ 응좕(reduce)ν•˜λŠ” 방식
  • μ•žμ˜ 두 μš”μ†Œμ˜ μ—°μ‚° κ²°κ³Όλ₯Ό λ°”νƒ•μœΌλ‘œ λ‹€μŒ μš”μ†Œμ™€ μ—°μ‚°
    • Accumulator: 각 μš”μ†Œλ₯Ό κ³„μ‚°ν•œ 쀑간 κ²°κ³Όλ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
    • Identity: 계산을 μˆ˜ν–‰ν•˜κΈ° μœ„ν•œ μ΄ˆκΈ°κ°’
    • Combiner: 병렬 슀트림(Parlallel Stream)μ—μ„œ λ‚˜λˆ„μ–΄ κ³„μ‚°λœ κ²°κ³Όλ₯Ό ν•˜λ‚˜λ‘œ ν•©μΉ¨
int[] intArr = {1,2,3,4,5};

long sum = Arrays.stream(intArr).sum();
System.out.println("intArr의 전체 μš”μ†Œ ν•©: " + sum);

int sum1 = Arrays.stream(intArr)
                .map(el -> el*2)
                .reduce((a,b) -> a+b)
                .getAsInt();
System.out.println("μ΄ˆκΈ°κ°’ μ—†λŠ” reduce: " + sum1);

int sum2= Arrays.stream(intArr)
                .map(el -> el*2)
                .reduce(0, (a,b) -> a+b);
System.out.println("μ΄ˆκΈ°κ°’ μ‘΄μž¬ν•˜λŠ” reduce: " + sum2)

Streamμš”μ†Œ λ‹€λ₯Έ μ’…λ₯˜λ‘œ μˆ˜μ§‘ - collect()

  • Stream의 μš”μ†Œλ“€μ„ λ‹€λ₯Έ μ’…λ₯˜(List, Set, Map λ“±)의 결과둜 μˆ˜μ§‘
  • 일반적으둜 List둜 Stream의 μš”μ†Œλ“€μ„ 많이 μˆ˜μ§‘
    자주 μ‚¬μš©ν•˜λŠ” μž‘μ—…μ€ Collectors κ°μ²΄μ—μ„œ static λ©”μ„œλ“œλ‘œ 제곡
    μ›ν•˜λŠ” 것이 μ—†μœΌλ©΄ Collector μΈν„°νŽ˜μ΄μŠ€λ₯Ό 직접 κ΅¬ν˜„ν•˜μ—¬ μ‚¬μš©

🀍 Optional<T>

더보기
  • NullPointerException(NPE)μ—μ„œ null κ°’μœΌλ‘œ 인해 μ—λŸ¬κ°€ λ°œμƒν•˜λŠ” ν˜„μƒμ„ 객체 μ°¨μ›μ—μ„œ 효율적으둜 λ°©μ§€ν•˜κ³ μž λ„μž…
  • μ—°μ‚° κ²°κ³Όλ₯Ό Optional에 λ‹΄μ•„μ„œ λ°˜ν™˜ν•˜λ©΄, λ”°λ‘œ 쑰건문을 μž‘μ„±ν•˜μ§€ μ•Šμ•„λ„ NPEκ°€ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ μ½”λ“œμž‘μ„± κ°€λŠ₯

Optional 객체 생성

  • of() μ‚¬μš©
  • μ°Έμ‘°λ³€μˆ˜μ˜ 값이 null일 κ°€λŠ₯성이 μžˆλ‹€λ©΄ ofNullable() μ‚¬μš©
Optional<String> opt1 = Optional.ofNullable(null);
Optional<String> opt2 = Optional.ofNullable("123");
Optional<String> opt3 = Optional.<String>empty();  // κΈ°λ³Έκ°’μœΌλ‘œ μ΄ˆκΈ°ν™”

λ©”μ„œλ“œ 체이닝

  • μ—¬λŸ¬ λ©”μ„œλ“œλ₯Ό μ—°κ²°ν•΄μ„œ μž‘μ„±

βœ… Ref. 

πŸ’œ μ˜€λŠ˜μ˜ 생각 쑰각λͺ¨μŒ

  • λ©”μ„œλ“œ λ ˆνΌλŸ°μŠ€λŠ” λžŒλ‹€μ‹μœΌλ‘œ 간단해진 읡λͺ…객체λ₯Ό 더 κ°„λ‹¨ν•˜κ²Œ μ‚¬μš©ν•˜λŠ” 것이닀. 간단해진 읡λͺ… 객체λ₯Ό 더! 간단!ν•˜κ²Œ!! μΈκ°„μ˜ μš•μ‹¬μ€ 끝이 μ—†κ³  … λ‚˜λŠ” λ¬΄μŠ¨λ§μΈμ§€ λͺ¨λ₯΄κ² κ³  … 😡‍πŸ’«
  • I/OλŠ” 내일 ... γ… .γ… 

'SEB > TIL' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

023 | Data Structure - Stack & Queue  (0) 2022.07.25
019 | Java - I/O, Thread, JVM  (0) 2022.07.19
017 | Java - πŸ₯ Practical | Collection Framework  (0) 2022.07.16
016 | Java - Generics, Collection Framework  (2) 2022.07.15
015 | Java  (0) 2022.07.13
Comments