こんにちは。「Javaを復習する初心者」です。
今回はSetインターフェースのtoArrayメソッドを使って、3つのクラスHashSet、LinkedHashSet、TreeSetの出力を確認しました。
出力の順番
結論からまとめてしまうと、出力の順は以下になります。
クラス | 順序 |
---|---|
HashSet | 決まっていない |
LinkedHashSet | 追加順 |
TreeSet | ソート順 |
TreeSetのインスタンスをTreeSet()で生成した場合、格納する要素のクラスはComparable<T>インターフェースを実装している必要があります。オーバーライドされたcompareToメソッドが定める順序に従ってソートされるということです。コンストラクタTreeSet(Comparator<? super E> comparator)を使う方法もあります。
今回はIntegerクラスとStringクラスそれぞれを使用して、出力を確認してました。それぞれ、Comparableインターフェースを実装しています。
Integerの場合
Integerの場合は次のように作りました。
- List<Integer>型変数を1つ用意し、ArrayListのインスタンスを格納する。
- Set<Integer>型変数3つ用意し、以下のクラスのインスタンスを格納する。
- HashSet
- LinkedHashSet
- TreeSet
- 0から999の範囲の乱数を10個、上記のListと3つのSetに格納する。
- 上記3つのSetを配列に変換し、それぞれ配列変数a, b, cに格納する。
- 以下の形式で出力する。ただし、3行目以降は繰り返しカウンタiが0から配列aの長さ未満まで繰り返し出力する。
行数 形式 1行目 書式 “%-13s|%-13s|%-13s|%-13s” 埋め字 “ArrayList”, “HashSet”, “LinkedHashSet”, “TreeSet” 2行目 “——————————————————-“ 3行目以降 書式 “%13d|%13d|%13d|%13d” 埋め字 list.get(i), a[i], b[i], c[i]
以下はソースと実行結果です。
ソース
package practice.test20160809;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
public class SetInteger {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Set<Integer> hashSet = new HashSet<>();
Set<Integer> linkedHashSet = new LinkedHashSet<>();
Set<Integer> treeSet = new TreeSet<>();
// 乱数格納
Random random = new Random();
int randomNum = 0;
for (int i = 0; i < 10; i++) {
randomNum = random.nextInt(1000);
list.add(randomNum);
hashSet.add(randomNum);
linkedHashSet.add(randomNum);
treeSet.add(randomNum);
}
// 配列に変換
Integer[] a = hashSet.toArray(new Integer[0]);
Integer[] b = linkedHashSet.toArray(new Integer[0]);
Integer[] c = treeSet.toArray(new Integer[0]);
// 出力
System.out.printf("%-13s|%-13s|%-13s|%-13s", "ArrayList", "HashSet", "LinkedHashSet", "TreeSet");
System.out.println();
System.out.println("-------------------------------------------------------");
for (int i = 0; i < a.length; i++) {
System.out.printf("%13d|%13d|%13d|%13d", list.get(i), a[i], b[i], c[i]);
System.out.println();
}
}
}
結果
ArrayList |HashSet |LinkedHashSet|TreeSet
-------------------------------------------------------
731| 994| 731| 109
739| 739| 739| 218
994| 531| 994| 333
613| 613| 613| 531
333| 218| 333| 613
531| 731| 531| 731
939| 939| 939| 739
218| 333| 218| 766
766| 109| 766| 939
109| 766| 109| 994
TreeSetは数値の昇順になってます。これはIntegerクラスがComparable<Integer>を実装して、このように並ぶようにしているからです。ArrayListの要素i番目が格納順です。なので、LinkedHashSetの出力と同じ順序です。
Stringの場合
Stringの場合は、Integerのときと大体同じ作りですが、ArrayListは使ってません。文字列なので格納する内容は英語小文字のランダムな並びを作ることにしました。その部分は次のようなフローです。
- 単語の長さrandomLengthを1から10の範囲の乱数で決定する。
- それぞれの文字を’a’ + [0から25までの乱数]で決定する。
以下はソースと実行結果です。
ソース
package practice.test20160809;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
public class SetString {
public static void main(String[] args) {
Set<String> hashSet = new HashSet<>();
Set<String> linkedHashSet = new LinkedHashSet<>();
Set<String> treeSet = new TreeSet<>();
// ランダム文字列格納
Random random = new Random();
for (int i = 0; i < 10; i++) {
// 単語生成
int randomLength = random.nextInt(10) + 1;
StringBuilder sb = new StringBuilder();
for (int j = 0; j < randomLength; j ++) {
char c = (char)('a' + random.nextInt(26));
sb.append(c);
}
String s = sb.toString();
hashSet.add(s);
linkedHashSet.add(s);
treeSet.add(s);
}
// 配列に変換
String[] a = hashSet.toArray(new String[0]);
String[] b = linkedHashSet.toArray(new String[0]);
String[] c = treeSet.toArray(new String[0]);
// 出力
System.out.printf("%-13s|%-13s|%-13s", "HashSet", "LinkedHashSet", "TreeSet");
System.out.println();
System.out.println("-----------------------------------------");
for (int i = 0; i < a.length; i++) {
System.out.printf("%-13s|%-13s|%-13s", a[i], b[i], c[i]);
System.out.println();
}
}
}
結果
HashSet |LinkedHashSet|TreeSet
-----------------------------------------
ediznizl |n |cg
wxdnr |cg |ediznizl
cg |wxdnr |mnmuxikhm
unip |ediznizl |n
v |mnmuxikhm |nmjs
mnmuxikhm |unip |skg
nmjs |v |unip
n |skg |v
skg |zkp |wxdnr
zkp |nmjs |zkp
上記のようにTreeSetは辞書式順序になってます。これもIntegerクラスと同じようにStringクラスがそのように実装しているからです。