悪あがきプログラマー

悪あがきを続けていきたい技術と書評なブログです。トレタでiOSエンジニアやってます。

String配列から指定要素を削除する。

java.util.Arrays#asList(T... a)

最初に思いついたのがこんなコード
loopを書きたくなくて、java.util.Arrays#asList(T... a)した。

public static void main(String[] args) {
	String[] strs = new String[] { "a", "b", "c", "d", "e" };

	List<String> list = Arrays.asList(strs);
	list.remove("c");
	String[] temp = (String[]) list.toArray(new String[list.size()]);
	for (String str : temp) {
		System.out.println(str);
	}
}

一瞬、うまくいきそうに見えるけど、
実行時エラーになってしまう。

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.remove(AbstractList.java:144)
	at java.util.AbstractList$Itr.remove(AbstractList.java:360)
	at java.util.AbstractCollection.remove(AbstractCollection.java:252)
	at Test.main(Test.java:13)

原因は、java.util.AbstractList#removeが実装されていないから。

    /**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public E remove(int index) {
	throw new UnsupportedOperationException();
    }


でも、配列を定義してloopで回して、、
はちょっとだるいのでやりたくない。
どうするか?
こうすれば良い。

public static void main(String[] args) {
	String[] strs = new String[] { "a", "b", "c", "d", "e" };

	List<String> list = new ArrayList<String>(Arrays.asList(strs)); // 新インスタンスを生成
	list.remove("c");
	String[] temp = (String[]) list.toArray(new String[list.size()]);
	for (String str : temp) {
		System.out.println(str);
	}
}

実行結果

a
b
d
e

java.util.Arrays#asList(T... a)はサイズが決まってしまうので、

指定された配列を基にする固定サイズのリストを返します。

取得したリストをコンストラクタに渡して、新たにリストを生成している。
こうすることで、removeやaddなどの操作が可能となる。

また、java.util.Arrays#asList(T... a)しただけだと、リストの皮をかぶった配列、って感じなので、
返却されたリストをいじると、元の配列の中身も変更される。
これを避けるには、先程の様に新たなリストを生成する必要がある。