[05] Collection API

MIIINยท2023๋…„ 4์›” 2์ผ
0

Modern Java

๋ชฉ๋ก ๋ณด๊ธฐ
5/8
post-thumbnail

๐Ÿ  Collection Factory

Java SE 9๋ถ€ํ„ฐ Collection ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” Collection Factory Method๋ฅผ ์ง€์›ํ•œ๋‹ค.

List.of()

Immutable(๋ถˆ๋ณ€์˜) List๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ˆ˜์ •์ด๋‚˜ ์ถ”๊ฐ€๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

List<String> friends = List.of("Raphael", "Olivia", "Thibaut");

-- java.lang.UnsupportedOperationException ๋ฐœ์ƒ
friends.add("Chih-Chun");

Set.of()

Immutable Set์„ ๋งŒ๋“ค๋ฉฐ ์ค‘๋ณต๋œ ์š”์†Œ๊ฐ€ ์žˆ์œผ๋ฉด IllegalArgumentException์ด ๋ฐœ์ƒํ•œ๋‹ค.

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

Map.of() / Map.ofEntries()

Immutable Map์„ ๋งŒ๋“ ๋‹ค.

-- ์ฒซ๋ฒˆ์งธ ๋ฐฉ๋ฒ•
Map<String, Integer> ageOfFriends = Map.of("Rahael", 30, "Olivia", 25, "Thibaut", 26);

-- ๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•
Map<String, Integer> ageOfFriends =
	Map.ofEntries(
		Map.entry("Raphael", 30),
		Map.entry("Olivia", 25),
		Map.entry("Thibaut", 26));

๐Ÿ“œ List & Set Method

๋‹ค์Œ์€ Java SE 8์—์„œ List, Set Interface์— ์ถ”๊ฐ€๋œ ๋ฉ”์„œ๋“œ์ด๋‹ค.

removeIf()

List/Set์—์„œ Predicate๋ฅผ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.

transactions.removeIf(transaction -> transaction.getVale() < 500);

replaceAll()

List์—์„œ UnaryOperator ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์š”์†Œ๋ฅผ ๋ฐ”๊พผ๋‹ค.

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

sort()

List์—์„œ ์š”์†Œ๋“ค์„ ์ •๋ ฌํ•œ๋‹ค.

referenceCodes.sort(Comparator.comparing(String::toString));

๐Ÿ—ฝ Map Method

Java SE 8์—์„œ Map Interface์— ์—ฌ๋Ÿฌ Default Method๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

forEach()

BiConsumer(Key, Value)๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋ฐ˜๋ณตํ•œ๋‹ค.

ageOfFriends.forEach((name, age) -> {
	System.out.println(name + " is " + age + " years old");
});

Entry.comparingByValue() / Entry.comparingByKey()

Map์˜ ํ•ญ๋ชฉ์„ ๊ฐ’ ๋˜๋Š” ํ‚ค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Map<String, String> favouriteMovies =
		Map.ofEntries(
				Map.entry("Raphael", "Star Wars"),
				Map.entry("Cristina", "Matrix"),
				Map.entry("Olivia", "James Bond"));

favouriteMovies
		.entrySet()
		.stream()
		.sorted(Map.Entry.comparingByKey())
		.forEachOrdered(System.out::println);

getOrDefault()

ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด Null์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ NullPointerException์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด Null Check๋ฅผ ํ•ด์•ผ๋งŒ ํ•œ๋‹ค. getOrDefault() ๋ฉ”์„œ๋“œ๋Š” ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ํ‚ค๋ฅผ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๊ธฐ๋ณธ๊ฐ’์„ ๋ฐ›์•„, Map์— ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

favouriteMovies.getOrDefault("Olivia", "Matrix");
favouriteMovies.getOrDefault("Thibaut", "Matrix");

computeIfAbsent()

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

Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Raphael";
friendsToMovies.computeIfAbsent(friend, name -> new ArrayList<>()).add("Star Wars");

computeIfPresent()

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

friendsToMovies.computeIfPresent(friend, (s, strings) -> {
	strings.add("Matrix");
	return strings;
});

remove()

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

favouriteMovies.remove(key, value)

replaceAll()

BiFunction์„ ์ ์šฉํ•œ ๊ฒฐ๊ณผ๋กœ ๊ฐ ํ•ญ๋ชฉ์˜ ๊ฐ’์„ ๊ต์ฒดํ•œ๋‹ค.

Map<String, String> favouriteMovies = new HashMap<>();
favouriteMovies.put("Raphael", "Star Wars");
favouriteMovies.put("Olivia", "james bond");
favouriteMovies.replaceAll((name, movie) -> movie.toUpperCase());

replace()

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

favouriteMovies.replace("Olivia", "JAMES BOND", "TOTORO");

putAll()

๋‘ ๊ฐœ์˜ ๋งต์„ ํ•ฉ์น˜๋ฉฐ, ์ค‘๋ณต๋œ ํ‚ค๋Š” ๋ฎ์–ด์“ด๋‹ค.

Map<String, String> family = Map.ofEntries(
		Map.entry("Teo", "Star Wars"),
		Map.entry("Cristina", "James Bond")
);
Map<String, String> friends = Map.ofEntries(
		Map.entry("Raphael", "Star Wars"),
		Map.entry("Cristina", "Matrix")
);
Map<String, String> everyone = new HashMap<>(family);
everyone.putAll(friends);

merge()

๋‘ ๊ฐœ์˜ ๋งต์„ ํ•ฉ์น˜๋ฉฐ, ์ค‘๋ณต๋œ ํ‚ค๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ฉ์น ์ง€ BiFunction์„ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค.

friends.forEach((k, v) -> everyone.merge(k, v, (movie1, movie2) -> movie1 + " & " + movie2));

-- ์˜ํ™” ์‹œ์ฒญ ๊ธฐ๋ก
Map<String, Long> moviesToCount = new HashMap<>();
String movieName= "James Bond";
moviesToCount.merge(movieName, 1L, (key, count) -> count + 1L);

๐Ÿ˜Ž ConcurrentHashMap

ConcurrentHashMap์€ ๋™์‹œ์„ฑ ์นœํ™”์ ์ด๋ฉฐ, ํŠน์ • ๋ถ€๋ถ„๋งŒ ์ž ๊ถˆ ๋™์‹œ ์ถ”๊ฐ€/๊ฐฑ์‹  ์ž‘์—…์„ ํ—ˆ์šฉํ•œ๋‹ค. ๋™๊ธฐํ™”๋œ Hashtable ๋ฒ„์ „์— ๋น„ํ•ด ์ฝ๊ธฐ ์“ฐ๊ธฐ ์—ฐ์‚ฐ ์„ฑ๋Šฅ์ด ์›”๋“ฑํ•˜๋ฉฐ, HashMap๊ณผ ๋‹ฌ๋ฆฌ Multi-Thread ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.

Reduce & Calculation

ConcurrentHashMap์€ ์„ธ ๊ฐ€์ง€ ์ƒˆ๋กœ์šด ์—ฐ์‚ฐ์„ ์ง€์›ํ•˜๋ฉฐ, ์•„๋ž˜์™€ ๊ฐ™์ด ๋„ค ๊ฐ€์ง€ ์—ฐ์‚ฐ ํ˜•ํƒœ๋ฅผ ์ง€์›ํ•œ๋‹ค.

(ํ‚ค, ๊ฐ’)ํ‚ค๊ฐ’Map.Entry
forEachforEachKeyforEachValueforEachEntry
reducereduceKeysreduceValuesreduceEntries
searchsearchKeyssearchValuessearchEntries

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

๋˜ํ•œ ๋ณ‘๋ ฌ์„ฑ ๊ธฐ์ค€๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ธฐ์ค€๊ฐ’์„ 1๋กœ ์ง€์ •ํ•˜๋ฉด ๊ณตํ†ต Thread Pool์„ ์ด์šฉํ•ด ๋ณ‘๋ ฌ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•œ๋‹ค.

ConcurrentHashMap<String, Long> map = new ConcurrentHashMap<>();
long parallelismThreshold = 1;
Optional<Long> maxValue = Optional.ofNullable(map.reduceValues(parallelismThreshold, Long::max));

Coefficient

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

KeySetView

ConcurrentHashMap์„ ์ง‘ํ•ฉ ๋ทฐ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” keySet ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.


profile
๋ฐฑ์—”๋“œ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€