ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Stream을 List로 변환하는 2가지의 방법(Collectors.toList(), Stream.toList())
    Back-End/Spring 2023. 4. 18. 06:46
    728x90

    개요

     

    사이드 프로젝트에서, 작성한 글에 대한 이미지 업로드 로직에서 이슈가 터지게 되었다.

     

    사진 업로드 기능은 이미지를 업로드 창에 올리거나, 기존의 것을 삭제하거나, 업로드 창에 올린 것을 다시 삭제하는 등

     

    다양한 경우의 수가 있어서 이를 잘 고려해서 설계해야한다.

     

    우리는 2개의 배열을 두어 (업로드 할 이미지, 삭제 될 이미지) 서버로 전달받도록 하였고, 삭제할 이미지는

     

    해당 포스트의 기존에 존재하던 이미지인 경우만 삭제하도록 구현하였다.

     

     

    문제점

     

    문제는 해당 메서드에서 발생했다.

     

    해당 메서드는 List를 받아 element 1개를 제외한 List를 만들어 반환 해 주는 메서드인데

     

    기존에는 주석처리 된 부분으로 코드 로직을 진행하였다. 

     

    하지만 java16 부터 등장한 toList() 메서드는 해당 메서드의 리턴 리스트 자료형이 unmodifiable하다고 한다.

     

     

    따라서, 이 후 해당 리스트에 add 연산을 하고자 하면 해당 예외가 발생했다.

     

    java.lang.UnsupportedOperationException: null
    	at java.util.AbstractList.add(AbstractList.java:148) ~[na:1.8.0_201]
    	at java.util.AbstractList.add(AbstractList.java:108) ~[na:1.8.0_201]

     

    이유는, 우리가 toList() 메서드로 받는 arrayList 클래스는 AbstractList<E> 추상 클래스를 상속받는데,

     

    해당 arrayList 클래스가 add 메서드를 override하지 않았기 때문에 추상클래스의 add 메서드가 그대로 호출이 되어 

     

    예외를 던지게 된 것이었다.

     

     

     

     

    결과적으로, Collectors.toList() 메서드를 통해 modifiable한 arrayList를 사용하였고, 정상적으로 로직이 작동하였다.

     

     

    하지만, Java 진영에서 Stream.toList() 를 권고하는 이유

     

     

    람다와 스트림을 도입하게 된 java 8 버전부터 stream연산의 결과를 취합하여 리스트로 반환하는 종단연산인 .collect(Collectors.toList()) 를 사용할 수 있었다.

     

    하지만 해당 메서드는 리턴되는 List가 수정이 가능(modifiable) 하다는 특징이 있어서, 메서드의 불변성을 지키기 위해 java10 에서 수정불가능한(unmodifiable) List 로 반환되도록 toUnmodifiableList() 가 새롭게 등장했다고 한다. 하지만 toUnmodfiableList() 는 이름이 장황해서, java16 에서는 이를 보완하기 위해 Stream.toList() 가 등장했다고 한다.

     

     

    결과적으로 Collectors.toList() 메서드를 사용하긴 했지만, 해당 메서드를 사용하지 않는 방향으로 코드를 리팩토링 해 봐야 겠다.

     

     

    댓글

Designed by Tistory.