[JAVA] 특정 범위 정수 리스트 생성하기, toList() vs Collectors.toList()

Coastby·2023년 3월 7일
0

코딩테스트

목록 보기
11/11

백준 5597 과제 안 내신 분 문제를 풀다가 stream에서 특정 범위의 정수를 생성하는 메서드가 생각이 났다.
시도 했다가 다양한 것을 알게 되어서 포스트로 남긴다.

특정 범위의 정수 스트림 생성

IntStream과 LongStream은 지정된 범위의 연속된 정수를 스트림으로 생성해서 반환하는 range(), rangeClosed()를 가지고 있다.

IntStream   IntStream.range(int begin, int end)          //end 포함 x
IntStream   IntStream.rangeClosed(int begin, int end)    //end 포함 

이는 IntStream으로 반환되기 때문에 우리가 사용하기 위해서는 배열이나 리스트로 변환을 해야한다. 나는 리스트의 삭제를 사용하기 위해 ArrayList<Integer>로 변환을 원해서 아래와 같이 변환을 하였다.

  • intStream → ArrayList<Integer>
ArrayList<Integer> nums = (ArrayList<Integer>) IntStream.rangeClosed(1, 30).boxed().toList();

그러나, 이렇게 하니 ImmutableCollections을 ArrayList로는 캐스팅할 수 없다는 에러가 발생하였다.

Exception in thread "main" java.lang.ClassCastException: class java.util.ImmutableCollections$ListN cannot be cast to class java.util.ArrayList (java.util.ImmutableCollections$ListN and java.util.ArrayList are in module java.base of loader 'bootstrap')

  • 그래서 캐스팅을 하지 않고 List로 받았더니 UnsupportedOperationExcetpion이 발생하였다.
    ImmutableCollections을 변경하려고 해서 발생하였다.
List<Integer> nums = IntStream.rangeClosed(1, 30).boxed().toList();

nums.remove(nums.indexOf(n));
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
	at java.base/java.util.ImmutableCollections$AbstractImmutableList.remove(ImmutableCollections.java:258)

왜 이런 문제가 발생했는지 검색 결과 아래와 같은 내용을 찾을 수 있었다.

Before using this or converting old code, we should note that there is an important difference between these examples. The new Stream.toList()
returns an unmodifiable ArrayList
, where Collectors.toList()
returns a modifiable ArrayList
. I think this is probably the right decision as we should favor immutability whenever possible. If we need a mutable list, we can always use the pre-Java 16 way. Just be careful when updating old code to this new syntax, this small difference may cause an UnsupportedOperationExcetpion
to be thrown if the list ends up being modified elsewhere.

https://todd.ginsberg.com/post/java-16/stream-tolist/

  • 최종 코드
    수정 가능한 List로 받기 위해서는 stream에서 최종연산에 toList()를 사용하는 것이 아니라, collect(Collectors.toList())를 사용해야 한다.
    둘의 차이가 뭔지도 모르고 사용하고 있었는데, 코딩테스트를 통해 알게 되었다..
List<Integer> nums = IntStream.rangeClosed(1, 30).boxed().collect(Collectors.toList());

최종 코드

import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class B5597_과제안내신분 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		List<Integer> nums = IntStream.rangeClosed(1, 30).boxed().collect(Collectors.toList());

		for (int i = 0; i < 28; i++) {
			int n = sc.nextInt();
			nums.remove(nums.indexOf(n));
		}
		Collections.sort(nums);
		System.out.println(nums.get(0));
		System.out.println(nums.get(1));
	}

}
profile
훈이야 화이팅

0개의 댓글