Post

๐Ÿน chap8. ์ปฌ๋ ‰์…˜ API ๊ฐœ์„ 

8.1 ์ปฌ๋ ‰์…˜ ํŒฉํ† ๋ฆฌ

์ž๋ฐ” 9์—์„œ ์ž‘์€ ์ปฌ๋ ‰์…˜ ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์ œ๊ณต

  • ์ ์€ ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฆฌ์ŠคํŠธ ๋งŒ๋“ค๊ธฐ
1
2
3
4
5
// ํœด๊ฐ€๋ฅผ ํ•จ๊ป˜ ๋ณด๋‚ด๋ ค๋Š” ์นœ๊ตฌ ์ด๋ฆ„์„ ํฌํ•จํ•˜๋Š” ๊ทธ๋ฃน
List<String> friends = new ArrayList<>();
friends.add("Raphael");
friends.add("Olivia");
friends.add("Thibaut");

์„ธ ๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๋Š”๋ฐ๋„ ๋งŽ์€ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๋‹ค์Œ์ฒ˜๋Ÿผ Arrays.asList() ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

1
2
List<String> friends
    = Arrays.asList("Raphael", "Olivia", "Thibaut");

๊ณ ์ • ํฌ๊ธฐ์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋ฏ€๋กœ ์š”์†Œ๋ฅผ ๊ฐฑ์‹ ํ•  ์ˆœ ์žˆ์ง€๋งŒ ์ƒˆ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์š”์†Œ๋ฅผ ์‚ญ์ œํ•  ์ˆœ ์—†๋‹ค. ์š”์†Œ๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ์ž‘์—…์€ ๊ดœ์ฐฎ์ง€๋งŒ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค ํ•˜๋ฉด Unsupported OperationException์ด ๋ฐœ์ƒํ•œ๋‹ค.

1
2
3
List<String> friends = Arrays.asList("Raphael", "Olivia");
friends.set(0, "Richard");
friends.add("Thibaut");

UnsupportedOperationException ์˜ˆ์™ธ ๋ฐœ์ƒ

๋‚ด๋ถ€์ ์œผ๋กœ ๊ณ ์ •๋œ ํฌ๊ธฐ์˜ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฐ์—ด๋กœ ๊ตฌํ˜„๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ๋‹ค.

์ง‘ํ•ฉ์€? Arrays.asSet()์ด๋ผ๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ์—†์œผ๋ฏ€๋กœ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค. ๋ฆฌ์ŠคํŠธ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” HashSet ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
Set<String> friends
    = new HashSet<>(Arrays.asList("Raphael", "Olivia", "Thibaut"));

๋˜๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ์ŠคํŠธ๋ฆผ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
Set<String> friends
    = Stream.of("Raphael", "Olivia", "Thibaut")
            .collect(Collectors.toSet());

ํ•˜์ง€๋งŒ ๋‘ ๋ฐฉ๋ฒ• ๋ชจ๋‘ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด(๋ฆฌ์ŠคํŠธ) ํ• ๋‹น์„ ํ•„์š”๋กœ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ๊ณผ๋Š” ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ง‘ํ•ฉ์ด๋ผ๋Š” ์‚ฌ์‹ค๋„ ์ฃผ๋ชฉํ•ด์•ผํ•œ๋‹ค.

8.1.1 ๋ฆฌ์ŠคํŠธ ํŒฉํ† ๋ฆฌ

List.of ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

1
2
List<String> friends = List.of("Raphael", "Olivia", "Thibaut");
System.out.println(friends);

์œ„ ์ฝ”๋“œ์—์„œ friends ๋ฆฌ์ŠคํŠธ์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

1
2
List<String> friends = List.of("Raphael", "Olivia", "Thibaut");
friends.add("Chih-Chun");

์œ„ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด java.lang.UnsupportedOperationException์ด ๋ฐœ์ƒํ•œ๋‹ค. ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

set() ๋ฉ”์„œ๋“œ๋กœ ์•„์ดํ…œ์„ ๋ฐ”๊พธ๋ คํ•ด๋„ ๋น„์Šทํ•œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋”ฐ๋ผ์„œ set ๋ฉ”์„œ๋“œ๋กœ๋„ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์ œ์•ฝ์€ ๊ผญ ๋‚˜์œ๊ฒƒ๋งŒ์€ ์•„๋‹ˆ๋‹ค. ์ปฌ๋ ‰์…˜์ด ์˜๋„์น˜ ์•Š๊ฒŒ ๋ณ€ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ”๊ฟ”์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด ์ง์ ‘ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ null ์š”์†Œ๋Š” ๊ธˆ์ง€ํ•˜๋ฏ€๋กœ ์˜๋„์น˜ ์•Š์€ ๋ฒ„๊ทธ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์กฐ๊ธˆ ๋” ๊ฐ„๊ฒฐํ•œ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋‹ฌ์„ฑํ–ˆ๋‹ค.

๋ฆฌ์ŠคํŠธ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

  • ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ

    ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํ˜•์‹์„ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด ์‚ฌ์šฉ

    ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์ด ๋” ๋‹จ์ˆœํ•˜๊ณ  ๋ชฉ์ ์„ ๋‹ฌ์„ฑํ•˜๋Š”๋ฐ ์ถฉ๋ถ„ํ•˜๊ธฐ ๋•Œ๋ฌธ

  • ์ŠคํŠธ๋ฆผ API

    Collectors.toList() ๋“ฑ์˜ ์ปฌ๋ ‰ํ„ฐ๋กœ ์ŠคํŠธ๋ฆผ์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ ๊ฐ€๋Šฅ

    ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋ฉด ์‚ฌ์šฉ

8.1.2 ์ง‘ํ•ฉ ํŒฉํ† ๋ฆฌ

List.of์™€ ๋น„์Šทํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋Š” ์ง‘ํ•ฉ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

1
2
Set<String> friends = Set.of("Raphael", "Olivia", "Thibaut");
System.out.println(friends);

์ค‘๋ณต๋„๋‹ˆ ์š”์†Œ๋ฅผ ์ œ๊ณตํ•ด ์ง‘ํ•ฉ์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•˜๋ฉด Olivia๋ผ๋Š” ์š”์†Œ๊ฐ€ ์ค‘๋ณต๋˜์–ด ์žˆ๋‹ค๋Š” ์„ค๋ช…๊ณผ ํ•จ๊ป˜ IllegalArgumentException์ด ๋ฐœ์ƒํ•œ๋‹ค.

1
Set<String> friends = Set.of("Raphael", "Olivia", "Olivia");

8.1.3 ๋งต ํŒฉํ† ๋ฆฌ

์ž๋ฐ” 9์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋Š” ๋งต์„ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

Map.of

Map.of ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์— ํ‚ค์™€ ๊ฐ’์„ ๋ฒˆ๊ฐˆ์•„ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋งต์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

1
2
3
Map<String, Integer> ageOfFriends
    = Map.of("Raphael", 30, "Olivia", 25, "Thibaut", 26);
System.out.println(ageOfFriends);

์—ด ๊ฐœ ์ดํ•˜์˜ ํ‚ค์™€ ์Œ์„ ๊ฐ€์ง„ ์ž‘์€ ๋งต์„ ๋งŒ๋“ค ๋•Œ๋Š” ์ด ๋ฉ”์†Œ๋“œ๊ฐ€ ์œ ์šฉํ•˜๋‹ค.

Map.ofEntries

๊ทธ ์ด์ƒ์˜ ๋งต์—์„œ๋Š” Map.Entry<K, V> ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์œผ๋ฉฐ ๊ฐ€๋ณ€ ์ธ์ˆ˜๋กœ ๊ตฌํ˜„๋œ Map.ofEntries ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ํ‚ค์™€ ๊ฐ’์„ ๊ฐ์Œ€ ์ถ”๊ฐ€ ๊ฐ์ฒด ํ• ๋‹น์„ ํ•„์š”๋กœํ•œ๋‹ค.

1
2
3
4
5
6
7
import static java.util.Map.entry;

Map<String, Integer> ageOfFriends
    = Map.ofEntries(entry("Raphael", 30),
                    entry("Olivia", 25),
                    entry("Thibaut", 26));
System.out.println(ageOfFriends);

Map.entry๋Š” Map.Entry ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ์ƒˆ๋กœ์šด ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์ด๋‹ค.

  • Quiz. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋Š”?

    1
    2
    3
    
      List<String> actors = List.of("Keanu", "Jessica");
      actors.set(0, "Brad");
      System.out.println(actors);
    
    • ์ •๋‹ต

      UnsupportedOperationException์ด ๋ฐœ์ƒํ•œ๋‹ค. List.of๋กœ ๋งŒ๋“  ์ปฌ๋ ‰์…˜์€ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

8.2 ๋ฆฌ์ŠคํŠธ์™€ ์ง‘ํ•ฉ ์ฒ˜๋ฆฌ

์ž๋ฐ” 8์—์„œ๋Š” List, Set ์ธํ„ฐํŽ˜์ด์Šค์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

  • removeIf

    : ํ”„๋ ˆ๋””์ผ€์ดํŠธ๋ฅผ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. List๋‚˜ Set์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ๊ทธ ๊ตฌํ˜„์„ ์ƒ์†๋ฐ›์€ ๋ชจ๋“  ํด๋ž˜์Šค์— ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • replaceAll

    : ๋ฆฌ์ŠคํŠธ์—์„œ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์œผ๋กœ UnaryOperator ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์š”์†Œ๋ฅผ ๋ฐ”๊พผ๋‹ค.

  • sort

    : List ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ •๋ ฌํ•œ๋‹ค.

์ด๋“ค ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•œ ์ปฌ๋ ‰์…˜ ์ž์ฒด๋ฅผ ๋ฐ”๊พผ๋‹ค. ์ƒˆ๋กœ์šด ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“œ๋Š” ์ŠคํŠธ๋ฆผ ๋™์ž‘๊ณผ ๋‹ฌ๋ฆฌ ์ด๋“ค ๋ฉ”์„œ๋“œ๋Š” ๊ธฐ์กด ์ปฌ๋ ‰์…˜์„ ๋ฐ”๊พผ๋‹ค.

์™œ ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์„๊นŒ? ์ปฌ๋ ‰์…˜์„ ๋ฐ”๊พธ๋Š” ๋™์ž‘์€ ์—๋Ÿฌ๋ฅผ ์œ ๋ฐœํ•˜๋ฉฐ ๋ณต์žกํ•จ์„ ๋”ํ•œ๋‹ค.

8.2.1 removeIf ๋ฉ”์„œ๋“œ

๋‹ค์Œ์€ ์ˆซ์ž๋กœ ์‹œ์ž‘๋˜๋Š” ์ฐธ์กฐ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง„ ํŠธ๋žœ์žญ์…˜์„ ์‚ญ์ œํ•˜๋Š” ์ฝ”๋“œ๋‹ค.

1
2
3
4
5
for (Transaction transaction : transactions) {
    if (Character.isDigit(transaction.getReferenceCode().charAt(0))) {
        transactions.remove(transaction);
    }
}

์œ„ ์ฝ”๋“œ๋Š” ConcurrentModificationException์„ ์ผ์œผํ‚จ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ for-each ๋ฃจํ”„๋Š” Iterator ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์œ„ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ด์„๋œ๋‹ค.

1
2
3
4
5
6
7
for (Iterator<Transaction> iterator = transactions.iterator(); iterator.hasNext(); ) {
    Transaction transaction = iterator.next();
    if (Character.isDigit(transaction.getReferenceCode().charAt(0))) {
        // ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ๋ณ„๋„์˜ ๋‘ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์ปฌ๋ ‰์…˜์„ ๋ฐ”๊พธ๊ณ  ์žˆ๋Š” ๋ฌธ์ œ
        **transactions.remove(transaction);**
    }
}

๋‘ ๊ฐœ์˜ ๊ฐœ๋ณ„ ๊ฐ์ฒด๊ฐ€ ์ปฌ๋ ‰์…˜์„ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ฃผ๋ชฉํ•˜์ž.

  • Iterator ๊ฐ์ฒด, next(), hasNext()๋ฅผ ์ด์šฉํ•ด ์†Œ์Šค๋ฅผ ์งˆ์˜ํ•œ๋‹ค.
  • Collection ๊ฐ์ฒด ์ž์ฒด, remove()๋ฅผ ํ˜ธ์ถœํ•ด ์š”์†Œ๋ฅผ ์‚ญ์ œํ•œ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ฐ˜๋ณต์ž์˜ ์ƒํƒœ๋Š” ์ปฌ๋ ‰์…˜์˜ ์ƒํƒœ์™€ ์„œ๋กœ ๋™๊ธฐํ™”๋˜์ง€ ์•Š๋Š”๋‹ค. Iterator ๊ฐ์ฒด๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ ๊ฐ์ฒด์˜ remove() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•จ์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
for (Iterator<Transaction> iterator = transactions.iterator(); iterator.hasNext(); ) {
    Transaction transaction = iterator.next();
    if (Character.isDigit(transaction.getReferenceCode().charAt(0))) {
        **iterator.move();**
    }
}

์ฝ”๋“œ๊ฐ€ ์กฐ๊ธˆ ๋ณต์žกํ•ด์กŒ๋‹ค. ์ด ์ฝ”๋“œ ํŒจํ„ด์€ ์ž๋ฐ” 8์˜ removeIf ๋ฉ”์„œ๋“œ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ฝ”๋“œ๊ฐ€ ๋‹จ์ˆœํ•ด์งˆ ๋ฟ ์•„๋‹ˆ๋ผ ๋ฒ„๊ทธ๋„ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค. removeIf ๋ฉ”์„œ๋“œ๋Š” ์‚ญ์ œํ•  ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ”„๋ ˆ๋””์ผ€์ดํŠธ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค.

1
2
transactions.removeIf(transaction -> 
    Character.isDigit(transaction.getReferenceCode().charAt(0)));

8.2.2 replaceAll ๋ฉ”์„œ๋“œ

List ์ธํ„ฐํŽ˜์ด์Šค์˜ replaceAll ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋ฆฌ์ŠคํŠธ์˜ ๊ฐ ์š”์†Œ๋ฅผ ์ƒˆ๋กœ์šด ์š”์†Œ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. ์ŠคํŠธ๋ฆผ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

1
2
3
4
5
referenceCodes.stream()
    .map(code -> Character.toUpperCase(code.charAt(0)) 
                + code.subString(1))
    .collect(Collectors.toList())
    .forEach(System.out::println);

ํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ๋Š” ์ƒˆ ๋ฌธ์ž์—ด ์ปฌ๋ ‰์…˜์„ ๋งŒ๋“ ๋‹ค. ๊ธฐ์กด์˜ ์ปฌ๋ ‰์…˜์„ ๋ฐ”๊พธ๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์Œ์ฒ˜๋Ÿผ ListIterator ๊ฐ์ฒด (์š”์†Œ๋ฅผ ๋ฐ”๊พธ๋Š” set() ๋ฉ”์„œ๋“œ ์ง€์›)๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
for (ListIterator<String> iterator = referenceCodes.listIterator(); iterator.hasNext(); ) {
    String code = iterator.next();
    iterator.set(Character.toUpperCase(code.charAt(0)) + code.substring(1));
}

์ฝ”๋“œ๊ฐ€ ์กฐ๊ธˆ ๋ณต์žกํ•ด์กŒ๋‹ค. ์ปฌ๋ ‰์…˜ ์ž์ฒด๋ฅผ Iterator ๊ฐ์ฒด์™€ ํ˜ผ์šฉํ•˜๋ฉด ๋ฐ˜๋ณต๊ณผ ์ปฌ๋ ‰์…˜ ๋ฐ˜๋ณต์ด ๋™์‹œ์— ์ด๋ฃจ์–ด์ง€๋ฉด์„œ ์‰ฝ๊ฒŒ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚จ๋‹ค. ์ž๋ฐ” 8์˜ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
referenceCodes.replaceAll(code -> Character.toUpperCase(code.charAt(0))
                                + code.substring(1));

8.3 ๋งต ์ฒ˜๋ฆฌ

์ž๋ฐ” 8์—์„œ๋Š” Map ์ธํ„ฐํŽ˜์ด์Šค์— ๋ช‡ ๊ฐ€์ง€ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด์„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ตฌํ˜„ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ์ด๋“ค ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ ๊ฒƒ์ด๋‹ค.

8.3.1 forEach ๋ฉ”์„œ๋“œ

๋งต์—์„œ ํ‚ค์™€ ๊ฐ’์„ ๋ฐ˜๋ณตํ•˜๋ฉฐ ํ™•์ธํ•˜๋Š” ์ž‘์—…์€ ๋งค์šฐ ๊ท€์ฐฎ๋‹ค. ์‹ค์ œ๋กœ๋Š” Map.Entry<K, V>์˜ ๋ฐ˜๋ณต์ž๋ฅผ ์ด์šฉํ•ด ๋งต์˜ ํ•ญ๋ชฉ ์ง‘ํ•ฉ์„ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
for (Map.Entry<String, Integer> entry: ageOfFriends.entrySet()) {
    String friend = entry.getKey();
    Integer age = entry.getValue();
    System.out.println(friend + " is " + age + " years old");
}

์ž๋ฐ” 8๋ถ€ํ„ฐ Map ์ธํ„ฐํŽ˜์ด์Šค๋Š” BiConsumer(ํ‚ค์™€ ๊ฐ’์„ ์ธ์ˆ˜๋กœ๋ฐ›์Œ)๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์€ forEach ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•˜๋ฏ€๋กœ ์ฝ”๋“œ๋ฅผ ์กฐ๊ธˆ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
ageOfFriends.forEach((friend, age)
    -> System.out.println(friend + " is " + age + " years old"));

8.3.2 ์ •๋ ฌ ๋ฉ”์„œ๋“œ

๋‹ค์Œ ๋‘ ๊ฐœ์˜ ์ƒˆ๋กœ์šด ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋งต์˜ ํ•ญ๋ชฉ์„ ๊ฐ’ ๋˜๋Š” ํ‚ค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Entry.comparingByValue
  • Entry.comparingByKey
1
2
3
4
5
6
7
8
9
Map<String, String> favoriteMovies
    = Map.ofEntries(
        entry("Raphael", "Star Wars"),
        entry("Cristina", "Matrix"),
        entry("Olivia", "James Bond"));

favoriteMovies.entrySet().stream()
    .sorted(Entry.comparingByKey())
    .forEachOrdered(System.out::println); // ์‚ฌ๋žŒ์˜ ์ด๋ฆ„์„ ์•ŒํŒŒ๋ฒณ ์ˆœ์œผ๋กœ ์ŠคํŠธ๋ฆผ ์š”์†Œ ์ฒ˜๋ฆฌ 

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

1
2
3
Cristina=Matrix
Olivia=James Bond
Raphael=Star Wars

8.3.3 getOrDefault ๋ฉ”์„œ๋“œ

๊ธฐ์กด์—๋Š” ์ฐพ์œผ๋ ค๋Š” ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด null์ด ๋ฐ˜ํ™˜๋˜๋ฏ€๋กœ NullPointerException์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ์š”์ฒญ ๊ฒฐ๊ณผ๊ฐ€ null์ธ์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

getOrDefault ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜ : ํ‚ค
  • ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜ : ๊ธฐ๋ณธ๊ฐ’

๋งต์— ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋ฐ›์€ ๊ธฐ๋ณธ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

1
2
3
4
5
6
Map<String, String> favoriteMovies
    = Map.ofEntries(
        entry("Raphael", "Star Wars"),
        entry("Olivia", "James Bond"));
System.out.println(favoriteMovies.getOrDefault("Olivia", "Matrix"));  //James Bond ์ถœ๋ ฅ
System.out.println(favoriteMovies.getOrDefault("Thibaut", "Matrix")); // Matrix ์ถœ๋ ฅ

ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋”๋ผ๋„ ๊ฐ’์ด null์ธ ์ƒํ™ฉ์—์„œ getOrDefault๊ฐ€ null์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค. โ†’ ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋Š๋ƒ์˜ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋‘ ๋ฒˆ์จฐ ์ธ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜๋ ์ง€ ๊ฒฐ์ •๋œ๋‹ค.

8.3.4 ๊ณ„์‚ฐ ํŒจํ„ด

๋งต์— ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์–ด๋–ค ๋™์ž‘์„ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•ด์•ผํ•˜๋Š” ์ƒํ™ฉ์ด ํ•„์š”ํ•œ ๋•Œ๊ฐ€ ์žˆ๋‹ค. ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ์—ฐ์‚ฐ์„ ์ œ๊ณตํ•œ๋‹ค.

  • computeIfAbsent

    : ์ œ๊ณต๋œ ํ‚ค์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์ด ์—†์œผ๋ฉด(๊ฐ’์ด ์—†๊ฑฐ๋‚˜ ๋„), ํ‚ค๋ฅผ ์ด์šฉํ•ด ์ƒˆ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ณ  ๋งต์— ์ถ”๊ฐ€ํ•œ๋‹ค.

  • computeIfPresent

    : ์ œ๊ณต๋œ ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋ฉด ์ƒˆ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ณ  ๋งต์— ์ถ”๊ฐ€ํ•œ๋‹ค.

  • compute

    : ์ œ๊ณต๋œ ํ‚ค๋กœ ์ƒˆ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ณ  ๋งต์— ์ €์žฅํ•œ๋‹ค.

์ •๋ณด๋ฅผ ์บ์‹œํ•  ๋•Œ computeIfAbsent๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํŒŒ์ผ ์ง‘ํ•ฉ์˜ ๊ฐ ํ–‰์„ ํŒŒ์‹ฑํ•ด SHA-256์„ ๊ณ„์‚ฐํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•  ๋•Œ, ๊ธฐ์กด์— ์ด๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ–ˆ๋‹ค๋ฉด ์ด ๊ฐ’์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

๋งต์„ ์ด์šฉํ•ด ์บ์‹œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ MessageDigest ์ธ์Šคํ„ด์Šค๋กœ SHA-256 ํ•ด์‹œ๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
Map<String, byte[]> dataToHash = new HashMap<>();
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");

์ด์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•œ๋‹ค.

1
2
3
4
5
6
7
lines.forEach(line -> 
    dataToHash.computeIfAbsent(line, this::calculateDigest));
    // line - ๋งต์—์„œ ์ฐพ์„ ํ‚ค, this::calculateDigest - ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋™์ž‘ ์‹คํ–‰

private byte[] calculateDigest(String key) { // ํ—ฌํผ๊ฐ€ ์ œ๊ณต๋œ ํ‚ค์˜ ํ•ด์‹œ๋ฅผ ๊ณ„์‚ฐ
    return messageDigest.digest(key.getBytes(StandardCharsets.UTF_8));
}

์—ฌ๋Ÿฌ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๋งต ์ฒ˜๋ฆฌ์—๋„ ์ด ํŒจํ„ด์„ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Map<K, List>์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ํ•ญ๋ชฉ์ด ์ดˆ๊ธฐํ™”๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
// Raphael์—๊ฒŒ ์ค„ ์˜ํ™” ๋ชฉ๋ก ๋งŒ๋“ค๊ธฐ 
String friend = "Raphael";
List<String> movies = friendsToMovies.get(friend);
if (movies == null) { // ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
    movies = new ArrayList<>();
    friendsToMovies.put(friend, movies);
}
movies.add("Star Wars"); //์˜ํ™”๋ฅผ ์ถ”๊ฐ€

System.out.println(friendsToMovies); // {Raphael: [Star Wars]}

computeIfAbsent๋Š” ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐ’์„ ๊ณ„์‚ฐํ•ด ๋งต์— ์ถ”๊ฐ€ํ•˜๊ณ  ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋ฉด ๊ธฐ์กด ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

1
2
friendsToMovies.computeIfAbsent("Raphael", name -> new ArrayList<>())
                .add("Star Wars"); //{Raphael: [Star Wars]}

8.3.5 ์‚ญ์ œ ํŒจํ„ด

์ž๋ฐ” 8์—์„œ๋Š” ํŠน์ •ํ•œ ๊ฐ’๊ณผ ์—ฐ๊ด€๋˜์—ˆ์„ ๋•Œ๋งŒ ํ•ญ๋ชฉ์„ ์ œ๊ฑฐํ•˜๋Š” remove ์˜ค๋ฒ„๋กœ๋“œ ๋ฒ„์ „ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

๊ธฐ์กด์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
String key = "Raphael";
String value = "Jack Reacher 2";
if (favoriteMovies.containsKey(key) && 
        Objects.equals(favoriteMovies.get(key), value)) {
    favoriteMovies.remove(key);
    return true;
}
else {
    return false;
}

์ž๋ฐ” 8 ์ดํ›„๋กœ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
favoriteMovies.remove(key, value);

8.3.6 ๊ต์ฒด ํŒจํ„ด

๋งต์˜ ํ•ญ๋ชฉ์„ ๋ฐ”๊พธ๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‘ ๊ฐœ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ๋งต์— ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

  • replaceAll

    : BiFunction์„ ์ ์šฉํ•œ ๊ฒฐ๊ณผ๋กœ ๊ฐ ํ•ญ๋ชฉ์˜ ๊ฐ’์„ ๊ต์ฒดํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์ด์ „์— ์‚ดํŽด๋ณธ List์˜ replaceAll๊ณผ ๋น„์Šทํ•œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

  • Replace

    : ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋ฉด ๋งต์˜ ๊ฐ’์„ ๋ฐ”๊พผ๋‹ค. ํ‚ค๊ฐ€ ํŠน์ • ๊ฐ’์œผ๋กœ ๋งคํ•‘๋˜์—ˆ์„ ๋•Œ๋งŒ ๊ฐ’์„ ๊ต์ฒดํ•˜๋Š” ์˜ค๋ฒ„๋กœ๋“œ ๋ฒ„์ „๋„ ์žˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋งต์˜ ๋ชจ๋“  ๊ฐ’์˜ ํ˜•์‹์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
// replaceAll์„ ์ ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” ๋งต์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. 
Map<String, String> favoriteMovies = new HashMap<>();
favoriteMovies.put("Raphael", "Star Wars");
favoriteMovies.put("Olivia", "james bond");
favoriteMovies.replaceAll((friend, movie) -> movie.toUpperCase());
System.out.println(favoriteMovies); // {Olivia=JAMES BOND, Raphael=STAR WARS}

์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด replace ํŒจํ„ด์€ ํ•œ ๊ฐœ์˜ ๋งต์—๋งŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‘ ๊ฐœ์˜ ๋งต์—์„œ ๊ฐ’์„ ํ•ฉ์น˜๊ฑฐ๋‚˜ ๋ฐ”๊ฟ”์•ผ ํ•œ๋‹ค๋ฉด merge ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•œ๋‹ค.

8.3.7 ํ•ฉ์นจ

๋‘ ๊ทธ๋ฃน์˜ ์—ฐ๋ฝ์ฒ˜๋ฅผ ํฌํ•จํ•˜๋Š” ๋‘ ๊ฐœ์˜ ๋งต์„ ํ•ฉ์นœ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ๋‹ค์Œ์ฒ˜๋Ÿผ putAll์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
Map<String, String> family = Map.ofEntries(
    entry("Teo", "Star Wars"),
    entry("Cristina", "James Bond"));
Map<String, String> friends = Map.ofEntries(
    entry("Raphael", "Star Wars"));
Map<String, String> everyone = new HashMap<>(family);
everyone.putAll(friends); // friends์˜ ๋ชจ๋“  ํ•ญ๋ชฉ์„ everyone์œผ๋กœ ๋ณต์‚ฌ

์ค‘๋ณต๋œ ํ‚ค๊ฐ€ ์—†๋‹ค๋ฉด ์œ„ ์ฝ”๋“œ๋Š” ์ž˜ ์ž‘๋™ํ•œ๋‹ค.

๊ฐ’์„ ์ข€ ๋” ์œ ์—ฐํ•˜๊ฒŒ ํ•ฉ์ณ์•ผ ํ•œ๋‹ค๋ฉด ์ƒˆ๋กœ์šด merge ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์ค‘๋ณต๋œ ํ‚ค๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ฉ์น ์ง€ ๊ฒฐ์ •ํ•˜๋Š” BiFunction์„ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค.

family์™€ friends ๋‘ ๋งต ๋ชจ๋‘์— Cristina๊ฐ€ ๋‹ค๋ฅธ ์˜ํ™” ๊ฐ’์œผ๋กœ ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

1
2
3
4
5
6
Map<String, String> family = Map.ofEntries(
    entry("Teo", "Star Wars"),
    entry("Cristina", "James Bond"));
Map<String, String> friends = Map.ofEntries(
    entry("Raphael", "Star Wars"),
    entry("Cristina", "Matrix"));

forEach์™€ merge ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ์ถฉ๋Œ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋Š” ๋‘ ์˜ํ™”์˜ ๋ฌธ์ž์—ด์„ ํ•ฉ์น˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.

1
2
3
4
5
6
7
8
Map<String, String> everyone = new HashMap<>(family);
friends.forEach((k, v) ->
    // ์ค‘๋ณต๋œ ํ‚ค๊ฐ€ ์žˆ์œผ๋ฉด ๋‘ ๊ฐ’์„ ์—ฐ๊ฒฐ 
    everyone.merge(k, v, (movie1, movie2) -> movie1 + " & " + movie2));
System.out.println(everyone);

// ๊ฒฐ๊ณผ
// Outputs {Raphael=Star Wars, Cristina=James Bond & Matrix, Teo=Star Wars}

์ž๋ฐ”๋…์—์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ merge ๋ฉ”์„œ๋“œ๋Š” null๊ฐ’๊ณผ ๊ด€๋ จ๋œ ๋ณต์žกํ•œ ์ƒํ™ฉ๋„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

merge๋ฅผ ์ด์šฉํ•ด ์ดˆ๊ธฐํ™” ๊ฒ€์‚ฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์˜ํ™”๋ฅผ ๋ช‡ ํšŒ ์‹œ์ฒญํ–ˆ๋Š”์ง€ ๊ธฐ๋กํ•˜๋Š” ๋งต์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ํ•ด๋‹น ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ค๊ธฐ ์ „์— ๊ด€๋ จ ์˜ํ™”๊ฐ€ ์ด๋ฏธ ๋งต์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
Map<String, Long> moviesToCount = new HashMap<>();
String movieName = "JamesBond";
long count = moviesToCount.get(movieName);
if (count == null) {
    moviesToCount.put(movieName, 1);
}
else {
    moviesToCount.put(movieName, count + 1);
}

์œ„ ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ์ฒ˜๋Ÿผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
moviesToCount.merge(movieName, 1L, (key, count) -> count + 1L);

์œ„ ์ฝ”๋“œ์—์„œ merge์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” 1L์ด๋‹ค. ์ž๋ฐ”๋…์— ๋”ฐ๋ฅด๋ฉด ์ด ์ธ์ˆ˜๋Š” โ€œํ‚ค์™€ ์—ฐ๊ด€๋œ ๊ธฐ์กด ๊ฐ’์— ํ•ฉ์ณ์งˆ ๋„์ด ์•„๋‹Œ ๊ฐ’ ๋˜๋Š” ๊ฐ’์ด ์—†๊ฑฐ๋‚˜ ํ‚ค์— ๋„ ๊ฐ’์ด ์—ฐ๊ด€๋˜์–ด ์žˆ๋‹ค๋ฉด ์ด ๊ฐ’์„ ํ‚ค์™€ ์—ฐ๊ฒฐโ€ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

ํ‚ค์˜ ๋ฐ˜ํ™˜๊ฐ’์ด ๋„์ด๋ฏ€๋กœ ์ฒ˜์Œ์—๋Š” 1์ด ์‚ฌ์šฉ๋œ๋‹ค. ๊ทธ ๋‹ค์Œ๋ถ€ํ„ฐ๋Š” ๊ฐ’์ด 1๋กœ ์ดˆ๊ธฐํ™”๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ BiFunction์„ ์ ์šฉํ•ด ๊ฐ’์ด ์ฆ๊ฐ€๋œ๋‹ค.

  • Quiz. ๋‹ค์Œ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•œ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜์‹œ์˜ค.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
      Map<String, Integer> movies = new HashMap<>();
      movies.put("JamesBond", 20);
      movies.put("Matrix", 15);
      movies.put("Harry Potter", 5);
      Iterator<Map.Entry<String, Integer>> iterator = 
          movies.entrySet().iterator();
        
      while (iterator.hasNext()) {
          Map.Entry<String, Integer> entry = iterator.next();
          if (entry.getValue() < 10) {
              iterator.remove();
          }
      }
      System.out.println(movies); //{Matrix=15, JamesBond=20}
    
    • ์ •๋‹ต

      ๋งต์˜ ํ•ญ๋ชฉ ์ง‘ํ•ฉ์— ํ”„๋ ˆ๋””์ผ€์ดํŠธ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ํ•ญ๋ชฉ์„ ์‚ญ์ œํ•˜๋Š” removeIf ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

      1
      
        movies.entrySet().removeIf(entry -> entry.getValue() < 10);
      

8.4 ๊ฐœ์„ ๋œ ConcurrentHashMap

ConcurrentHashMap ํด๋ž˜์Šค๋Š” ๋™์‹œ์„ฑ ์นœํ™”์ ์ด๋ฉฐ ์ตœ์‹  ๊ธฐ์ˆ ์„ ๋ฐ˜์˜ํ•œ HashMap ๋ฒ„์ „์ด๋‹ค.

ConcurrentHashMap์€ ๋‚ด๋ถ€ ์ž๋ฃŒ๊ตฌ์กฐ์˜ ํŠน์ • ๋ถ€๋ถ„๋งŒ ์ž ๊ถˆ ๋™์‹œ ์ถ”๊ฐ€, ๊ฐฑ์‹  ์ž‘์—…์„ ํ—ˆ์šฉํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋™๊ธฐํ™”๋œ Hashtable ๋ฒ„์ „์— ๋น„ํ•ด ์ฝ๊ธฐ ์“ฐ๊ธฐ ์—ฐ์‚ฐ ์„ฑ๋Šฅ์ด ์›”๋“ฑํ•˜๋‹ค.(์ฐธ๊ณ ๋กœ, ํ‘œ์ค€ HashMap์€ ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•จ)

8.4.1 ๋ฆฌ๋“€์Šค์™€ ๊ฒ€์ƒ‰

ConcurrentHashMap์€ ์ŠคํŠธ๋ฆผ์—์„œ ๋ดค๋˜ ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ์ข…๋ฅ˜์˜ ์„ธ ๊ฐ€์ง€ ์ƒˆ๋กœ์šด ์—ฐ์‚ฐ์„ ์ง€์›ํ•œ๋‹ค.

  • forEach

    : ๊ฐ (ํ‚ค, ๊ฐ’) ์Œ์— ์ฃผ์–ด์ง„ ์•ก์…˜์„ ์‹คํ–‰

  • reduce

    : ๋ชจ๋“  (ํ‚ค, ๊ฐ’) ์Œ์„ ์ œ๊ณต๋œ ๋ฆฌ๋“€์Šค ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ฒฐ๊ณผ๋กœ ํ•ฉ์นจ

  • search

    : ๋„์ด ์•„๋‹Œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๋•Œ๊นŒ์ง€ ๊ฐ (ํ‚ค, ๊ฐ’) ์Œ์— ํ•จ์ˆ˜๋ฅผ ์ ์šฉ

๋‹ค์Œ์ฒ˜๋Ÿผ ํ‚ค์— ํ•จ์ˆ˜ ๋ฐ›๊ธฐ, ๊ฐ’, Map.Entry, (ํ‚ค, ๊ฐ’) ์ธ์ˆ˜๋ฅผ ์ด์šฉํ•œ ๋„ค ๊ฐ€์ง€ ์—ฐ์‚ฐ์„ ์ง€์›ํ•œ๋‹ค.

  • ํ‚ค, ๊ฐ’์œผ๋กœ ์—ฐ์‚ฐ(forEach, reduce, search)
  • ํ‚ค๋กœ ์—ฐ์‚ฐ(forEachKey, reduceKeys, searchKeys)
  • ๊ฐ’์œผ๋กœ ์—ฐ์‚ฐ(forEachValue, reduceValues, searchValues)
  • Map.Entry ๊ฐ์ฒด๋กœ ์—ฐ์‚ฐ(forEachEntry, reduceEntries, searchEntries)

์ด๋“ค ์—ฐ์‚ฐ์€ ConcurrentHashMap์˜ ์ƒํƒœ๋ฅผ ์ž ๊ทธ์ง€ ์•Š๊ณ  ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ์ ์„ ์ฃผ๋ชฉํ•ด์•ผํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋“ค ์—ฐ์‚ฐ์— ์ œ๊ณตํ•œ ํ•จ์ˆ˜๋Š” ๊ณ„์‚ฐ์ด ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด, ๊ฐ’, ์ˆœ์„œ ๋“ฑ์— ์˜์กดํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

๋˜ํ•œ ์ด๋“ค ์—ฐ์‚ฐ์— ๋ณ‘๋ ฌ์„ฑ ๊ธฐ์ค€๊ฐ’์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค. ๋งต์˜ ํฌ๊ธฐ๊ฐ€ ์ฃผ์–ด์ง„ ๊ธฐ์ค€๊ฐ’๋ณด๋‹ค ์ž‘์œผ๋ฉด ์ˆœ์ฐจ์ ์œผ๋กœ ์—ฐ์‚ฐ์„ ์‹คํ–‰ํ•œ๋‹ค. ๊ธฐ์ค€๊ฐ’์„ 1๋กœ ์ง€์ •ํ•˜๋ฉด ๊ณตํ†ต ์Šค๋ ˆ๋“œ ํ’€์„ ์ด์šฉํ•ด ๋ณ‘๋ ฌ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•œ๋‹ค.

Long.MAX_VALUE๋ฅผ ๊ธฐ์ค€๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ํ•œ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋กœ ์—ฐ์‚ฐ์„ ์‹คํ–‰ํ•œ๋‹ค. ์†Œํ”„ํŠธ์›จ์–ด ์•„ํ‚คํ…์ฒ˜๊ฐ€ ๊ณ ๊ธ‰ ์ˆ˜์ค€์˜ ์ž์› ํ™œ์šฉ ์ตœ์ ํ™”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด ๊ธฐ์ค€๊ฐ’ ๊ทœ์น™์„ ๋”ฐ๋ฅด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์ด ์˜ˆ์ œ์—์„œ๋Š” reduceValues ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋งต์˜ ์ตœ๋Œ“๊ฐ’์„ ์ฐพ๋Š”๋‹ค.

1
2
3
4
5
// ์—ฌ๋Ÿฌ ํ‚ค์™€ ๊ฐ’์„ ํฌํ•จํ•˜๋„๋ก ๊ฐฑ์‹ ๋  ConcurrentHashMap
ConcurrentHashMap<String, Long> map = new ConcurrentHashMap<>();
long parallelismThreshold = 1;
Optional<Integer> maxValue = 
    Optional.ofNullable(map.reduceValues(parallelismThreshold, Long::max));

int, long, double ๋“ฑ์˜ ๊ธฐ๋ณธ๊ฐ’์—๋Š” ์ „์šฉ each reduce ์—ฐ์‚ฐ์ด ์ œ๊ณต๋˜๋ฏ€๋กœ reduceValuesToInt, reduceKeysToLong ๋“ฑ์„ ์ด์šฉํ•˜๋ฉด ๋ฐ•์‹ฑ์ž‘์—…์„ ํ•  ํ•„์š”๊ฐ€ ์—†๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ž‘์—…์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

8.4.2 ๊ณ„์ˆ˜

ConcurrentHashMap ํด๋ž˜์Šค๋Š” ๋งต์˜ ๋งคํ•‘ ๊ฐœ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” mappingCount ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๊ธฐ์กด์˜ size ๋ฉ”์„œ๋“œ ๋Œ€์‹  ์ƒˆ ์ฝ”๋“œ์—์„œ int๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” mappingCount ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

โ†’ int์˜ ๋ฒ”์œ„๋ฅผ ๋„˜์–ด์„œ๋Š” ์ดํ›„์˜ ์ƒํ™ฉ์„ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ

8.4.3 ์ง‘ํ•ฉ๋ทฐ

ConcurrentHashMap ํด๋ž˜์Šค๋Š” ConcurrentHashMap์„ ์ง‘ํ•ฉ ๋ทฐ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” keySet์ด๋ผ๋Š” ์ƒˆ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๋งต์„ ๋ฐ”๊พธ๋ฉด ์ง‘ํ•ฉ๋„ ๋ฐ”๋€Œ๊ณ  ๋ฐ˜๋Œ€๋กœ ์ง‘ํ•ฉ์„ ๋ฐ”๊พธ๋ฉด ๋งต๋„ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค. newKeySet์ด๋ผ๋Š” ์ƒˆ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ConcurrentHashMap์œผ๋กœ ์œ ์ง€๋˜๋Š” ์ง‘ํ•ฉ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

This post is licensed under CC BY 4.0 by the author.