1. 소개

이 예제에서는 Java Stream 을 사용 하여 Map  으로 작업  하는 방법에 대한 몇 가지 예 논의할 것  입니다. 이러한 연습 중 일부는 양방향 Map 데이터 구조를 사용하여 해결할 수 있지만 여기서는 기능적 접근 방식에 관심이 있습니다.

먼저 MapsStream 작업에 사용할 기본 아이디어를 설명합니다 . 그런 다음 Stream 을 사용하는 Maps 및 구체적인 솔루션과  관련된 몇 가지 다른 문제를 제시합니다 .

2. 기본 아이디어

주목해야 할 주요 사항은 Stream 은 Collection 에서 쉽게 얻을 수 있는 요소의 시퀀스라는 것 입니다.

은 시퀀스 없이 키에서 값으로 매핑되는 다른 구조를 갖습니다. 그러나 이것이 우리가 Map 구조를 다른 시퀀스로 변환할 수 없다는 것을 의미하지는 않습니다 . 그러면 Stream API를 사용하여 자연스럽게 작업할 수 있습니다.

Map 에서 다른 Collection 을 얻는 방법을 살펴보고  Stream 으로 피벗할 수 있습니다 .

Map<String, Integer> someMap = new HashMap<>();

키-값 쌍 세트를 얻을 수 있습니다.

Set<Map.Entry<String, Integer>> entries = someMap.entrySet();

Map 과 관련된 키 세트를 얻을 수도 있습니다 .

Set<String> keySet = someMap.keySet();

또는 값 집합으로 직접 작업할 수 있습니다.

Collection<Integer> values = someMap.values();

이것들은 각각 스트림을 가져와서 컬렉션을 처리할 수 있는 진입점을 제공합니다.

Stream<Map.Entry<String, Integer>> entriesStream = entries.stream();
Stream<Integer> valuesStream = values.stream();
Stream<String> keysStream = keySet.stream();

3. Stream 을 사용하여 Map키 가져오기

3.1. 입력 데이터

Map 이 있다고 가정해 보겠습니다 .

Map<String, String> books = new HashMap<>();
books.put(
"978-0201633610", "Design patterns : elements of reusable object-oriented software");
books.put(
  "978-1617291999", "Java 8 in Action: Lambdas, Streams, and functional-style programming");
books.put("978-0134685991", "Effective Java");

"Effective Java"라는 책의 ISBN을 찾는 데 관심이 있습니다.

3.2. 일치 검색

책 제목이  Map 에 존재할 수 없기 때문에 관련 ISBN이 없음을 나타낼 수 있습니다. Optional  을 사용하여 다음을 표현할 수 있습니다.

이 예에서 해당 제목과 일치하는 책의 키에 관심이 있다고 가정해 보겠습니다.

Optional<String> optionalIsbn = books.entrySet().stream()
  .filter(e -> "Effective Java".equals(e.getValue()))
  .map(Map.Entry::getKey)
  .findFirst();

assertEquals("978-0134685991", optionalIsbn.get());

코드를 분석해 봅시다. 먼저 이전에 본 것처럼 Map 에서 entrySet얻습니다 .

제목이 "Effective Java"인 항목만 고려하므로 첫 번째 중간 작업은 필터 가 됩니다.

우리는 전체 Map 항목에 관심이 있는 것이 아니라 각 항목의 키에 관심이 있습니다. 따라서 다음 연결 중간 작업은 바로 이 작업을 수행합니다. 새 스트림을 출력으로 생성하는 작업입니다. 여기에는 우리가 찾고 있는 제목과 일치하는 항목에 대한 키만 포함됩니다.

하나의 결과만 원 하므로 Stream 의 초기 값을 Optional 객체 로 제공하는 findFirst() 터미널 작업을 적용할 수 있습니다.

제목이 존재하지 않는 경우를 보자.

Optional<String> optionalIsbn = books.entrySet().stream()
  .filter(e -> "Non Existent Title".equals(e.getValue()))
  .map(Map.Entry::getKey).findFirst();

assertEquals(false, optionalIsbn.isPresent());

3.3. 여러 결과 검색

이제 문제를 변경하여 하나가 아닌 여러 결과를 반환하는 방법을 살펴보겠습니다.

여러 결과가 반환되도록 하려면 다음 책을  Map 에 추가해 보겠습니다 .

books.put("978-0321356680", "Effective Java: Second Edition");

따라서 이제 "Effective Java"로 시작하는 모든 책을 검색하면 두 개 이상의 결과를 얻을 수 있습니다.

List<String> isbnCodes = books.entrySet().stream()
  .filter(e -> e.getValue().startsWith("Effective Java"))
  .map(Map.Entry::getKey)
  .collect(Collectors.toList());

assertTrue(isbnCodes.contains("978-0321356680"));
assertTrue(isbnCodes.contains("978-0134685991"));

이 경우 우리가 수행한 작업은 필터 조건을 교체하여 문자열 동등성 을 비교하는 대신 Map 의 값 이 "Effective Java"로 시작 하는지 확인하는 것입니다.

이번에 는 첫 번째 항목을 선택하는 대신 결과 수집 하고 일치 항목을 List 에 넣습니다 .

4. Stream 을 사용하여 값  얻기

이제 Map의 다른 문제에 집중해 보겠습니다. 제목을  기반으로  ISBN을 가져오는 대신  ISBN 을 기반으로 제목 을 가져오려고  합니다 .

원래 Map 을 사용합시다 . ISBN이 "978-0"으로 시작하는 제목을 찾고 싶습니다.

List<String> titles = books.entrySet().stream()
  .filter(e -> e.getKey().startsWith("978-0"))
  .map(Map.Entry::getValue)
  .collect(Collectors.toList());

assertEquals(2, titles.size());
assertTrue(titles.contains(
  "Design patterns : elements of reusable object-oriented software"));
assertTrue(titles.contains("Effective Java"));

이 솔루션은 이전 문제 세트의 솔루션과 유사합니다. 항목 집합을 스트리밍한 다음 필터링, 매핑 및 수집합니다.

또한 이전과 마찬가지로 첫 번째 일치 항목만 반환하려는 경우 map 메서드 이후에 모든 결과를 List 에 수집하는 대신 findFirst() 메서드를 호출할 수 있습니다.

5. 결론

이 기사에서 우리는 기능적인 방식으로 Map 를 처리하는 방법을 시연 했습니다.

특히, Map 에 대한 관련 컬렉션을 사용하도록 전환하면 Stream 을 사용하는 처리 가 훨씬 쉽고 직관적이 되는 것을 보았습니다.

물론 이 기사의 모든 예제는 GitHub 프로젝트 에서 찾을 수 있습니다 .

Generic footer banner