Java에서 array를 List로 바꾸려면 어떻게 해야될까?

for문을 쓰는것이 당연하지만 왠지 복잡해 보이고..

Arrays.asList가 List를 리턴한다. 간단해 보이므로 이걸쓰자.

 

하지만 잘 살펴보지 않으면 여기에 함정이 있다.

다음 코드를 살펴보자.

 

Integer[] arr = new Integer[]{1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(arr);
list.add(6);
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.base/java.util.AbstractList.add(AbstractList.java:153)
	at java.base/java.util.AbstractList.add(AbstractList.java:111)
	at ArrayAsList.main(ArrayAsList.java:10)

흠..List인데 add가 안된다?

 

Arrays.asList 구현을 보자.

public static <T> List<T> asList(T... a) {
	return new ArrayList<>(a);
}

ArrayList리턴인데 머지..?

 

하지만 이건 java.util.ArrayList 가 아니다.(머여그럼)

바로 밑에 코드를 보면 Arrays 안에 private static 으로 구현되어있다. 생성자로 array를 받고 전역변수로 array로 관리한다.

 

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
        ...
 }

 

그리고 add 메소드가 구현이 안되어있다. AbstractList 로 따라가다 보면 다음과 같이 UnsupportedOperationException을 발생시키는걸 볼 수 있다.

public void add(int index, E element) {
	throw new UnsupportedOperationException();
}

Arrays.asList 에서 나오는 결과로는 동적 List를 만들 수 없다. 

 

동적 List로 만들고 싶다면 오브젝트를 생성하여 반복문으로 새로 값을 할당해야 한다.

'Java' 카테고리의 다른 글

[Java] Wrapper 클래스 Cache  (0) 2020.06.18
[Java] Java에서 Map 관련 Iterate(반복문) 방법  (0) 2016.11.10





Java에서 Map 관련하여 반복문을 사용하는 경우가 여러가지가 있다. 가장 많이 쓰이는 몇가지를 살펴보고 장단점을 알아보도록한다. Java의 모든 map들은 Map interface를 사용하므로 다음 경우들은 모든 map에 대하여 사용 가능하다.

예 : HashMap, TreeMap, LinkedMap, Hashtable 등등.. 




1. Entry 에 For-Each Loop 사용

  가장 일반적이고 거의 모든 경우에 사용된다. 반복문 안에 key값과 value값이 전부 필요할때 사용한다.


1
2
3
4
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
cs


  참고 : For-Each Loop는 Java 5이상에서 사용가능하다. 또한 NullPointerExecption을 발생 시킬 수 있으므로 null 체크를 하도록 하자.




2. Key Value 에 For-Each Loop사용

  entry 대신 key값이나 value 값만 필요할 때 사용한다.


1
2
3
4
5
6
7
8
9
10
11
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
 
//iterating over keys only
for (Integer key : map.keySet()) {
    System.out.println("Key = " + key);
}
 
//iterating over values only
for (Integer value : map.values()) {
    System.out.println("Value = " + value);
}
cs


  entrySet을 사용할 때보다 약 10%정도 빠르다.




3. Iterator 사용


- Generic 사용


1
2
3
4
5
6
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry<Integer, Integer> entry = entries.next();
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
cs



- Generic 미사용


1
2
3
4
5
6
7
8
Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry entry = (Map.Entry) entries.next();
    Integer key = (Integer)entry.getKey();
    Integer value = (Integer)entry.getValue();
    System.out.println("Key = " + key + ", Value = " + value);
}
cs

 

 keySet이나 values 에도 똑같이 적용가능하다. 이 방법은 오래된 방법이지만 Java 버전이 낮은 경우에 유일하게 사용가능한 방법이다. 또 한가지 중요한 장점은 반복문을 사용하는 도중에 iterator.remove()를 통해 항목들을 삭제할 수 있는 유일한 방법이다. 만약 삭제 작업을 For-Each 구문에서 사용한다면 "unpredictable results"를 얻게된다(javadoc, Map은 순서를 보장하지 않기 때문에). 성능 측면에서 For-Each와 비슷하다.





4. Key값으로 Value를 찾는 반복문


  코드상으로는 간단해 보이지만 1번 방법에 비해 비효율적이고 성능면에서 안좋은 방법이다. key값을 이용해서 value를 찾는 과정에서 시간이 많이 소모된다.(1번 방법보다 약 20%~200% 성능저하가 있음)


1
2
3
4
5
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
    Integer value = map.get(key);
    System.out.println("Key = " + key + ", Value = " + value);
}
cs



'Java' 카테고리의 다른 글

Arrays.asList는 동적 List가 아니다.  (0) 2020.06.19
[Java] Wrapper 클래스 Cache  (0) 2020.06.18

+ Recent posts