DevLog ๐Ÿ˜ถ

[๋ชจ๋˜์ž๋ฐ”์ธ์•ก์…˜] ๋ฉ”์„œ๋“œ ์ฐธ์กฐ : ๋žŒ๋‹ค๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ๋ณธ๋ฌธ

๐Ÿ“–/Modern Java in Action

[๋ชจ๋˜์ž๋ฐ”์ธ์•ก์…˜] ๋ฉ”์„œ๋“œ ์ฐธ์กฐ : ๋žŒ๋‹ค๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ

dolmeng2 2023. 4. 7. 00:14

๐Ÿ’ฌ ๋ชจ๋˜ ์ž๋ฐ” ์ธ ์•ก์…˜ ์ฑ•ํ„ฐ 3์„ ์ฝ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

 


โœ”๏ธ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ

๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋” ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ณด์ž.

// Before
inventory.sort((a1, a2) ->
         a1.getCourse().compareTo(a2.getCourse()));

// After
inventory.sort(comparing(Crew::getCourse));

๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ํ™œ์šฉํ•˜๋Š”, '๋ฉ”์†Œ๋“œ ์ฐธ์กฐ'๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋žŒ๋‹ค๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ตฌ๋ถ„์ž(::)๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

๐ŸŒฑ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•
1. ์ •์  ๋ฉ”์„œ๋“œ ์ฐธ์กฐ 
(args) -> ClassName.staticMethod(args) ==> ClassName::staticMethod

2. ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ 
(arg0, rest) -> arg0.instanceMethod(rest) ==> ClassName::instanceMethod

3. ๊ธฐ์กด ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ 
(args) -> expr.instanceMethod(args) ==> expr::instanceMethod

์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€, ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๊ฐ€ ์ฝ˜ํ…์ŠคํŠธ์˜ ํ˜•์‹๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋žŒ๋‹ค์‹์„ ์ถ•์•ฝํ•˜์—ฌ ํ˜ธ์ถœํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ๋žŒ๋‹ค์‹๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋•Œ, ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ์™€ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ ๋Œ€์ƒ ๋ฉ”์„œ๋“œ์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.

 

๋ง์„ ์ด๋ ‡๊ฒŒ ์“ฐ๋‹ˆ๊นŒ ์–ด๋ ค์šด๋ฐ, ์ฝ”๋“œ๋กœ ๋ณด๋ฉด ๊ฐ„๋‹จํ•˜๋‹ค.

public class Calculator {
    public int sum(int a, int b) {
        return a + b;
    }
}

์ธ์ž๋กœ ๋ฐ›์€ ๋‘ ๊ฐ’์„ ๋”ํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. ์šฐ๋ฆฌ๋Š” ํ˜ธ์ถœ๋ถ€์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Calculator calculator = new Calculator();
IntBinaryOperator operator = calculator::sum;

์ƒ์„ฑํ•œ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ์ธ calculator::sum์˜ ๋ฐ˜ํ™˜ํ˜•์„ IntBinaryOperator๋กœ ๋ฐ›์•˜๋‹ค.

IntBinaryOperator๋Š” int ํƒ€์ž…์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ 2๊ฐœ๋ฅผ ๋ฐ›์•„ int ํƒ€์ž…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

์ด๋•Œ, calculator::sum์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋Š” (int, int) -> int์ด๊ณ , IntBinaryOperator ์—ญ์‹œ ๋™์ผํ•˜๋‹ค.

 


โœ”๏ธ ์ƒ์„ฑ์ž ์ฐธ์กฐ

์ •์  ๋ฉ”์„œ๋“œ ์ฐธ์กฐ์ฒ˜๋Ÿผ, ํด๋ž˜์Šค๋ช…::new๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ƒ์„ฑ์ž์˜ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

// ๊ธฐ๋ณธ์ ์ธ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ๋ฒ•
Crew crew = new Crew();

// ์ƒ์„ฑ์ž ์ฐธ์กฐ ์ด์šฉํ•˜๊ธฐ
Supplier<Crew> sup = Crew::new;
Crew crew = sup.get(); // get์„ ํ†ตํ•ด ๊ฐ์ฒด ๊ฐ€์ ธ์˜ค๊ธฐ

// ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ ์ƒ์„ฑ์ž ์ฐธ์กฐ ์ด์šฉํ•˜๊ธฐ
Function<String, Crew> func = Crew::new;
Crew crew = func.apply("journey"); // ์ธ์ˆ˜ ์ „๋‹ฌ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

// ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ 2๊ฐœ์ธ ๊ฒฝ์šฐ
BiFunction<String, Integer, Crew> bi = Crew::new;
Crew crew = bi.apply("journey", 23);

์ธ์ž๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ธ ๊ฒฝ์šฐ์—๋Š”, ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ปค์Šคํ…€ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๋งŒ์•ฝ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ 4๊ฐœ์ธ ๊ฒฝ์šฐ, ์ƒ์„ฑ์ž ์ฐธ์กฐ๋ฅผ ํ™œ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ œ๋„ค๋ฆญ์„ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ž.

public interface CustomFunction<T1, T2, T3, T4, R> {
    R apply(T1 t1, T2 t2, T3 t3, T4 t4);
}

// ๊ฐ„๋‹จํ•œ ํฌ๋ฃจ ํด๋ž˜์Šค
public class Crew {
    private final String name;
    private final String nickname;
    private final int age;
    private final String courseName;

    public Crew(final String name, final String nickname, final int age, final String courseName) {
        this.name = name;
        this.nickname = nickname;
        this.age = age;
        this.courseName = courseName;
    }
}

๊ทธ๋Ÿฌ๋ฉด ์‹ค์ œ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์ ์šฉํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

CustomFunction<String, String, Integer, String, Crew> crewFactory = Crew::new;

 

๋˜ํ•œ, ์ƒ์„ฑ์ž ์ฐธ์กฐ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ธ์Šคํ„ด์Šคํ™” ํ•˜์ง€ ์•Š๋”๋ผ๋„ ์ƒ์„ฑ์ž์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

public class Crew {
    private final String courseName;

    public Crew(final String courseName) {
        this.courseName = courseName;
    }

    public String getCourseName() {
        return courseName;
    }
}

์œ„์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ํฌ๋ฃจ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

public class Main {
    private static final Map<String, Function<String, Crew>> map = new HashMap<>();

    public static void main(String[] args) throws IOException {
        map.put("backend", Crew::new);
        map.put("frontend", Crew::new);

        Crew crew = getCrew("backend", "backend");
        System.out.println(crew.getCourseName()); // backend
    }

    public static Crew getCrew(String course, String courseName) {
        return map.get(course).apply(courseName);
    }
}

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ, map์„ ํ†ตํ•ด ํŠน์ •ํ•œ ํ•ด์‹œ๊ฐ’์„ key๋กœ ๋‘๊ณ , ํ•ด๋‹น ํ•ด์‹œ๊ฐ’์œผ๋กœ ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด๋‘”๋‹ค. (์ผ์ข…์˜ ์บ์‹ฑ ๊ฐœ๋…์ด๋‹ค)

๊ทธ๋ฆฌ๊ณ , ํ•ด๋‹น ํ•ด์‹œ๊ฐ’์„ ํ†ตํ•ด map์— ์š”์ฒญํ•˜๋ฉด .apply()๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์ „์— ์ธ์Šคํ„ด์Šคํ™”ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

 


โœ”๏ธ ๋žŒ๋‹ค, ๋ฉ”์„œ๋“œ ์ฐธ์กฐ

์šฐ๋ฆฌ๋Š” ํฌ๋ฃจ์— ๋Œ€ํ•ด ์ •๋ ฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž. ์ด๋•Œ, ๋žŒ๋‹ค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฉ‹์ง€๊ฒŒ ๋ณ€ํ™˜์„ ํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

 

1. sort() ๋ฉ”์„œ๋“œ์—๊ฒŒ ๋™์ž‘ ํŒŒ๋ผ๋ฏธํ„ฐํ™” ์ ์šฉํ•˜๊ธฐ

// crew์— ๋Œ€ํ•œ comparator ์ƒ์„ฑํ•˜๊ธฐ
public class CrewComparator implements Comparator<Crew> {
    public int compare(Crew a1, Crew a2) {
        return Integer.compare(a1.getAge(), a2.getAge());
    }
}

// ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ธ์ž๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
List<Crew> crews = new ArrayList<>();
crews.sort(new CrewComparator());

sort๊ฐ€ ์–ด๋–ค ์‹์œผ๋กœ ์ •๋ ฌํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ๊ธฐ์ค€์„ ์ธ์ž๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค.

 

 

2. ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๊ณ , ์ต๋ช… ํด๋ž˜์Šค ํ™œ์šฉํ•˜๊ธฐ

List<Crew> crews = new ArrayList<>();

crews.sort(new Comparator<Crew>() {
  @Override
  public int compare(final Crew o1, final Crew o2) {
      return Integer.compare(o1.getAge(), o2.getAge());
  }
});

ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ , ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด์„œ ๋ฐ”๋กœ ์œ„์™€ ๊ฐ™์ด ์ •์˜๋ฅผ ํ•˜์˜€๋‹ค.

์ฐธ๊ณ ๋กœ, age์˜ ํƒ€์ž…์ด Integer๋ผ๋ฉด ๋ฐ”๋กœ o1.getAge().compareTo(o2.getAge())๋ฅผ ํ™œ์šฉํ•ด๋„ ์ข‹๋‹ค.

์œ„์—์„œ๋Š” primitive ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  Integer.compare๋ฅผ ํ™œ์šฉํ•˜์˜€๋‹ค.

(int ํƒ€์ž…์ด๋ผ๊ณ  ํ•ด์„œ ๋‘ ๊ฐ’์„ ๋ฐ”๋กœ ๋บ€ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ฉด ์˜ค๋ฒ„ํ”Œ๋กœ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์กฐ์‹ฌํ•ด์•ผ ํ•œ๋‹ค.)

 

 

3. ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•ด์„œ ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ

ํ˜„์žฌ Comparator๋Š” compare()๋ผ๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•˜๋‚˜๋งŒ ์กด์žฌํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

์ด๋•Œ, ์ถ”์ƒ ๋ฉ”์„œ๋“œ์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜ (= ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ)๋Š” (T, T) → int์ด๋ฉฐ, ์šฐ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ์‹œ๊ทธ๋‹ˆ์ฒ˜์™€ ๋™์ผํ•˜๊ฒŒ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

List<Crew> crews = new ArrayList<>();
crews.sort((Crew o1, Crew o2) -> Integer.compare(o1.getAge(), o2.getAge()));

์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ปจํ…์ŠคํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋žŒ๋‹ค์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹์„ ์ถ”๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์•ž์— ์„ ์–ธํ•œ Crew๋Š” ์ œ๊ฑฐํ•ด์ค˜๋„ ๋œ๋‹ค.

List<Crew> crews = new ArrayList<>();
crews.sort((o1, o2) -> Integer.compare(o1.getAge(), o2.getAge()));

์œ„ ์ฝ”๋“œ๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํ•ด๋ณด์ž.

Comparator๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
        Function<? super T, ? extends U> keyExtractor) {
    Objects.requireNonNull(keyExtractor);
    return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

 

Comparator๋Š” ์œ„์™€ ๊ฐ™์ด ๋‚ด๋ถ€์ ์œผ๋กœ comparing()์ด๋ผ๋Š” ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ ๋‚ด๋ถ€ ์ธ์ž๋กœ Function<T>ํ˜•์„ ๋ฐ›๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. Function์˜ ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ๋Š” T → R์ด๊ณ , ์—ฌ๊ธฐ์„œ T๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ •๋ ฌํ•  ๊ฐ์ฒด, R๋Š” ์ •๋ ฌ ๊ธฐ์ค€์— ๋Œ€ํ•œ ํ•„๋“œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

 

์šฐ๋ฆฌ๋Š” ํฌ๋ฃจ๋ฅผ ๋‚˜์ด ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋‹ค์Œ๊ณผ ๊ฐ™์ด Comparator์˜ ์ •์  ๋ฉ”์„œ๋“œ comparing์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

Comparator<Crew> c = Comparator.comparing((Crew a) -> a.getAge());

๊ทธ๋ฆฌ๊ณ , ๋‹ค์‹œ sort์˜ ์ธ์ž๋กœ Comparator๋ฅผ ๋„˜๊ฒจ์ฃผ์ž.

List<Crew> crews = new ArrayList<>();
crews.sort(Comparator.comparing((Crew crew) -> crew.getAge()));

 

4. ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ, ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์ด์šฉํ•˜์ž!

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด์„œ ์กฐ๊ธˆ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

List<Crew> crews = new ArrayList<>();
crews.sort(Comparator.comparing(Crew::getAge));

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ดˆ๋ฐ˜์— ๋น„ํ•ด ๋งค์šฐ ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง€๋ฉฐ, crew์˜ age๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๋ผ๋Š” ๊ฒƒ์„ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 


โœ”๏ธ ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์‘์šฉํ•˜๊ธฐ

์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์กฐํ•ฉํ•˜์—ฌ ๋ณต์žกํ•œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค!

์ด๋Š” ๋””ํดํŠธ ๋ฉ”์„œ๋“œ ๋•๋ถ„์ธ๋ฐ, ์ฑ•ํ„ฐ๊ฐ€ ๋‚˜์•„๊ฐ€๋ฉฐ ์„œ์„œํžˆ ํ’€๋ฆด ๋‚ด์šฉ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ง€๊ธˆ์€ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜์ž.

์กฐ๊ธˆ ๋” ์Šคํ‚ฌ์ ์ธ ๋‚ด์šฉ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋„๋กœ ํ’€์–ด์„œ ์„ค๋ช…ํ•˜๊ธฐ๋ณด๋‹ค๋Š”, ์ด๋Ÿฐ ๊ฒƒ๋„ ์žˆ๊ตฌ๋‚˜… ํ•˜๊ณ  ๋„˜์–ด๊ฐ€๋Š” ์šฉ๋„๋กœ ์ •๋ฆฌํ•˜๋ฉด ์ข‹๋‹ค.

 

๐Ÿ’ฌ Comparator ํ™œ์šฉํ•˜๊ธฐ

์šฐ๋ฆฌ๊ฐ€ ๋งŒ์•ฝ ํฌ๋ฃจ๋“ค์˜ ๋‚˜์ด๋ฅผ ์—ญ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?

crews.sort(Comparator.comparing(Crew::getAge).reversed());

comparing()์˜ ๋ฆฌํ„ด๊ฐ’์€ ๊ฒฐ๊ตญ Comparator์ด๊ธฐ ๋•Œ๋ฌธ์—, chaining์„ ํ†ตํ•ด์„œ ์‰ฝ๊ฒŒ ์—ญ์ •๋ ฌ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

Comparator์—๋Š” reversed()๋ผ๋Š” ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ๊ตฌํ˜„๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ ‡๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

// Comparator.java
default Comparator<T> reversed() {
    return Collections.reverseOrder(this);
}

์œ„์˜ ์ฝ”๋“œ๊ฐ€ Comparator ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ์ด๋‹ค. 

 

ํ˜น์€, ํฌ๋ฃจ์˜ ๋‚˜์ด, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฆ„์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

crews.sort(Comparator.comparing(Crew::getAge)
        .reversed()
        .thenComparing(Crew::getName));

thenComparing์„ ํ†ตํ•ด์„œ ๋‘ ๋ฒˆ์งธ ์ •๋ ฌ ๊ธฐ์ค€์„ ๋„˜๊ฒจ์ฃผ๋ฉด ๋œ๋‹ค.

 

 

๐Ÿ’ฌ Predicate ํ™œ์šฉํ•˜๊ธฐ

๋งŒ์•ฝ, ์ฐธ-๊ฑฐ์ง“์œผ๋กœ ๋ถ„๋ฅ˜๋˜๋Š” ์กฐ๊ฑด์— ๋Œ€ํ•ด ํ•„ํ„ฐ๋ง์„ ์ง„ํ–‰ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒด์ด๋‹์„ ๊ฑธ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

// ๋ฐฑ์—”๋“œ์ธ ํฌ๋ฃจ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๋Š” predicate
Predicate<Crew> coursePredicate = (Crew crew) -> crew.getCourseName().equals("backend");

// ํ•ด๋‹น ํ•„ํ„ฐ๋ง์— ๋Œ€ํ•ด ๋ฐ˜์ „์‹œํ‚ค๋Š” predicate
Predicate<Crew> notBackendPredicate = coursePredicate.negate();

// predicate์˜ and (๊ต์ง‘ํ•ฉ), or (ํ•ฉ์ง‘ํ•ฉ)
// 20์‚ด ์ด์ƒ์ด๋ฉด์„œ ๋ฐฑ์—”๋“œ ์ฝ”์Šค๊ฑฐ๋‚˜, ์ด๋ฆ„์ด ์ ธ๋‹ˆ์ธ ์กฐ๊ฑด
coursePredicate.and(crew -> crew.getAge() >= 20)
        .or(crew -> crew.getName().equals("journey"));

 

๐Ÿ’ฌ Function ํ™œ์šฉํ•˜๊ธฐ

h = f.andThen(g)

andThen์€ ์ฃผ์–ด์ง„ ํ•จ์ˆ˜๋ฅผ ๋จผ์ € ์ ์šฉํ•œ ๊ฒฐ๊ณผ๋ฅผ, ๋‹ค๋ฅธ ํ•จ์ˆ˜์˜ ์ž…๋ ฅ์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค.

 

h = f.compose(g)

compose๋Š” ์ธ์ˆ˜๋กœ ์ฃผ์–ด์ง„ ํ•จ์ˆ˜๋ฅผ ๋จผ์ € ์‹คํ–‰ํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ์ œ๊ณตํ•œ๋‹ค.

// andThen() : g(f(x))
// (x + 1) * 2
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g);
int result = h.apply(1); // (1+1) * 2 = 4

// compose() : f(g(x)) 
// (x * 2) + 1
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.compose(g);
int result = h.apply(1); // (1*2) + 1 = 3

์ฝ”๋“œ ๋‚ด๋ถ€๋Š” ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค :D

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
}

 


๋งˆ์ง€๋ง‰์œผ๋กœ ์ •๋ฆฌํ•ด๋ณด์ž! ์ฑ•ํ„ฐ 3์€ ๋‚ด์šฉ์ด ๋งŽ์ง€๋งŒ, ๊ทธ๋งŒํผ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ด์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

- ๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์ต๋ช… ํ•จ์ˆ˜์˜ ์ผ์ข…์ด๋‹ค. ์ด๋ฆ„์€ ์—†์ง€๋งŒ, ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฆฌ์ŠคํŠธ, ๋ฐ”๋””, ๋ฐ˜ํ™˜ ํ˜•์‹์„ ๊ฐ€์ง€๋ฉฐ ์˜ˆ์™ธ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ๋‹ค.
- ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ•˜๋‚˜์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋งŒ์„ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.
- ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ณณ์—์„œ๋งŒ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
- ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์ด์šฉํ•ด์„œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์ฆ‰์„์œผ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์ „์ฒด๊ฐ€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋กœ ์ทจ๊ธ‰๋œ๋‹ค.
- ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ์žฌ์‚ฌ์šฉํ•˜๊ณ , ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
Comments