5月11日

コレクションフレームワーク

Set

Setは重複のないコレクション。すでに存在するものをadd()した場合は、falseが返される。

SetSample.java

import java.util.HashSet;
import java.util.Set;

public class SetSample {
	public static void main(String[] args) {
		Set<String> set = new HashSet<String>();
		set.add("東京");
		set.add("ロンドン");
		set.add("パリ");
		for (String item : set) {
			System.out.println(item);
		}
	}
}

SetSample2は、SetインタフェースをCollectionインタフェースに置き換えただけ。
JavaDocでCollectionインタフェースを確認すると、ListやSetで使用したメソッドが定義されていることがわかる。

Eclipseの機能を使用してSetSample3.javaを作成する。

  1. SetSample.javaの上で右クリックしコピーを選択
  2. デフォルトパッケージの上で右クリックし貼り付けを選択
  3. クラス名が CopyOfSetSample になっているので、これを SetSample3 に修正してOKする
  4. これでSetSampleの内容がSetSample3.javaにコピーされる

SetSample.javaと異なる部分を入力してSetSample3.javaを作成する。

import java.util.HashSet;
import java.util.Set;

public class SetSample3 {

	public static void main(String[] args) {
		Set<String> set = new HashSet<String>();
		set.add("東京");
		set.add("ロンドン");
		set.add("パリ");

		if (!set.add("ロンドン")) {
			System.out.println("ロンドンは追加できない");
		}
		if (set.contains("ロンドン")) {
			System.out.println("ロンドンはある");
		}
		for (String item : set) {
			System.out.println(item);
		}
	}
}

テキストにはない例題をやってみる。

  1. ListSample6.javaのmainメソッド内をコピーする
  2. SetSample6.javaのmainメソッドに貼り付ける
  3. ListをSetに変更する
  4. ArrayListをHashMapに変更する
  5. 変数listにカーソルを置きメニューのリファクタリングを選択
  6. 変数名listをset変更すると、すべてのlistがsetに変更される(便利!)

SetSample4.java

import java.util.HashSet;
import java.util.Set;

public class SetSample4 {
	public static void main(String[] args) {
		Set<Man> set = new HashSet<Man>();
		set.add(new Man("孫", 10));
		set.add(new Man("北尾", 15));
		set.add(new Man("三木谷", 20));
		if (!set.add(new Man("孫", 10))) {
			System.out.println("孫は追加できない");
		}
		for (Man man : set) {
			System.out.println(man);
		}
	}
}

これを実行すると、二人目の孫が追加できてしまう。
二人目の孫を追加できないようにコードを修正する。

Man.javaを修正する。

  1. Man.javaを開く
  2. メニューの ソース を選択する
  3. hashCode()およびequeals()の生成 を選択する
  4. ageとnameにチェックが入った状態でOKする

これで、Man.java にhashCode()とequals()のオーバーライドが生成される。

Man.java

public class Man {
	String name;
	int age;
	Man(String name, int age) {
		this.name = name;
		this.age = age;
	}
	void introduce() {
		System.out.println("僕は" + name + " 年は" + age);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Man other = (Man) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return super.toString() + "[name=" + name + ", age=" + age + "]";
	}
}

SetSample4.java を実行すると「孫は追加できない」と表示されるようになる。

Mapの利用

Mapはキーに対応した値を持つ集合。

MapSample.java

import java.util.HashMap;
import java.util.Map;

public class MapSample {

	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("red", "赤");
		map.put("blue", "青");
		map.put("yellow", "黄色");
		String value = map.get("blue");
		System.out.println(value);
	}
}

要素を一覧する

MapSample2を作るまでもないので、MapSample.javaを修正して試す。

import java.util.HashMap;
import java.util.Map;

public class MapSample {

	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("red", "赤");
		map.put("blue", "青");
		map.put("yellow", "黄色");
		//String value = map.get("blue");
		//System.out.println(value);
		for (String key : map.keySet()) {
			String value = map.get(key);
			System.out.println(key + "=" + value);
		}
	}
}

Iteratorを使った走査

Iteratorインタフェースを使って要素の走査をすることもできる。

IteratorSample.java

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorSample {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("東京");
		list.add("ロンドン");
		list.add("パリ");
		Iterator<String> iter = list.iterator();
		while (iter.hasNext()) {
			String item = iter.next();
			System.out.println(item);
		}
	}
}

配列とListの変換

配列からListへの変換はArraysクラスのstaticメソッドasList()を使用する。
Listから配列への変換はListインタフェースのtoArray()メソッドを使用する。

ArraySample.java

import java.util.Arrays;
import java.util.List;

public class ArraySample {
	public static void main(String[] args) {
		String[] array = new String[] {"東京", "ロンドン", "パリ"};
		// 配列→リスト
		List<String> list = Arrays.asList(array);
		System.out.println("list");
		for (String s : list) {
			System.out.println(s);
		}
		// List→配列
		String[] array2 = list.toArray(new String[0]);
		System.out.println("array");
		for (String s : array2) {
			System.out.println(s);
		}
	}
}

ソートとComparator

Collectionsクラスのsort()メソッドを使って文字列をソートする例。

SortSample.java

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SortSample {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("いいい");
		list.add("ううう");
		list.add("あああ");
		Collections.sort(list);
		for (int i = 0; i < list.size(); i++) {
			String item = list.get(i);
			System.out.println(i + ":" + item);
		}
	}
}

ソート順序をカスタマイズする

ソート順序をカスタマイズするには java.util.Comparator インタフェースを実装したクラスを作成し、sort()メソッドの第2引数に渡す。

SortSample2.java

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortSample2 {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("いい");
		list.add("う");
		list.add("あああ");
		class MyComparator implements Comparator<String> {
			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
		}
		Collections.sort(list, new MyComparator());
		for (int i = 0; i < list.size(); i++) {
			String item = list.get(i);
			System.out.println(i + ":" + item);
		}
	}
}

無名クラスを使ったコードを追加する。

24行目で新しい要素を追加。
25~30行は、Collections.sort()メソッドの呼び出しで無名クラスのComparatorを第2引数に渡した例。
31~34行で結果の出力。

SortSample2.java

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortSample2 {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("いい");
		list.add("う");
		list.add("あああ");
		class MyComparator implements Comparator<String> {
			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
		}
		Collections.sort(list, new MyComparator());
		for (int i = 0; i < list.size(); i++) {
			String item = list.get(i);
			System.out.println(i + ":" + item);
		}

		list.add("ええ");
		Collections.sort(list, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
		});
		for (int i = 0; i < list.size(); i++) {
			String item = list.get(i);
			System.out.println(i + ":" + item);
		}
	}
}

引数が1個のsort()メソッドに渡すListは、Comparableインタフェースを実装しているクラスを格納しておかなければいけない。
Comparableインタフェースを実装していないManを格納したListを渡すコードを書いてみる。

SortSample2.java

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class SortSample2 {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("いい");
		list.add("う");
		list.add("あああ");
		class MyComparator implements Comparator<String> {
			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
		}
		Collections.sort(list, new MyComparator());
		for (int i = 0; i < list.size(); i++) {
			String item = list.get(i);
			System.out.println(i + ":" + item);
		}

		list.add("ええ");
		Collections.sort(list, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
		});
		for (int i = 0; i < list.size(); i++) {
			String item = list.get(i);
			System.out.println(i + ":" + item);
		}

		List<Man> list2 = new ArrayList<Man>();
		Collections.sort(list2);
	}
}

Collections.sort(list2);の部分でコンパイルエラーになる。
Manクラスをimplements Comparable し、compareTo()メソッドを追加するとエラーが解消する。

Man.java


public class Man implements Comparable<Man>{
	String name;
	int age;
	Man(String name, int age) {
		this.name = name;
		this.age = age;
	}
	void introduce() {
		System.out.println("僕は" + name + " 年は" + age);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Man other = (Man) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return super.toString() + "[name=" + name + ", age=" + age + "]";
	}
	@Override
	public int compareTo(Man o) {
		return 0;
	}
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です