Javaのコレクション「Set」とは?便利な使い方も紹介!
Setとは?
Setとは、重複不可能なデータです。
Twitterのいいねみたいな、1投稿に1回しかいいねできない感じです。
実は内部的にはMapを使用しており、とても性質が似ています。
Setの種類
実はSetとはあくまで入れ物のようなもの(インターフェース)なだけで、
実際に動作する実物は以下の3種類あります。
HashSet
中身の順番は保持されません。
そのため、順番を保持しないといけないデータには、使用できません。
LinkedHashSet
追加した順番に保持されます。
TreeSet
キーによって、自動的に並び替えされます。
数字順・アルファベット順等の場合、
勝手に並び替えてくれるので便利です。
宣言する型について
一般的に下記のような宣言を見ることが多いかと思います。
Set<String, String> 変数名 = new HashSet<>();
このように、Setの中に実物を入れていることが多いと思います。
ただ同じ型に入れることももちろん可能です。
HashSet<String, String> 変数名 = new HashSet<>();
どう違うのかと言うと、使える機能が違います。
細かくいえば他にも違いはありますが、基本的にはSetのインターフェースに格納し、
必要に応じてインターフェースに無い機能を使いたい時だけHashSet等を使用するイメージで大丈夫だと思います。
そのため以下は全てSetに格納しております。
基本的な使い方
前提として、Setの中身のことは「要素」と呼びます。
初期化する
Setオブジェクトを初期化(生成)します。
基本的に引数は指定しなくてもいいですが、「初期容量」と「負荷係数」を指定できます。
指定しない場合、デフォルトで初期容量が16、負荷係数が0.75となります。
何かというと、オブジェクト生成時にまず、初期容量分の保存領域を確保します。
そして要素を追加していく中で、初期容量の負荷係数個に到達すると、保存領域を拡張します。
上記例でいうと、16個の領域があって、係数が0.75ということは、12個の要素を追加するときに、拡張します。
その後も負荷係数に達するたびに拡張し続けていきます。
この要領を拡張するという動作が非常に重たい動作になるので、できる限り最適に設定していきたいので、
最初からある程度量が分かっているのであれば、指定してあげるとパフォーマンスがよくなります。
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
// デフォルトの初期容量16とデフォルトの負荷係数0.75のインスタンスを生成
Set<String> twitterGood1 = new HashSet<>();
// 初期容量10とデフォルトの負荷係数0.75のインスタンスを生成
Set<String> twitterGood2 = new HashSet<>(10);
// 初期容量5と負荷係数1.0のインスタンスを生成
Set<String> twitterGood3 = new HashSet<>(5, 1.0f);
}
}
要素を追加する
シンプルに要素を追加していきます。
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
// インスタンスを生成
Set<String> twitterGood = new HashSet<>();
// 追加 [@sato]
twitterGood.add("@sato");
// 追加 [@sato, @suzuki]
twitterGood.add("@suzuki");
// 追加 [@sato, @suzuki, @tanaka]
twitterGood.add("@tanaka");
}
}
要素を削除する
要素が存在する時だけ、その要素を削除します。
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
// インスタンスを生成
Set<String> twitterGood = new HashSet<>();
// 追加 [@sato]
twitterGood.add("@sato");
// 追加 [@sato, @suzuki]
twitterGood.add("@suzuki");
// 追加 [@sato, @suzuki, @tanaka]
twitterGood.add("@tanaka");
// 一致する要素があれば削除
// [@suzuki, @tanaka]
twitterGood.remove("@sato");
}
}
要素の数を取得する
Set内の要素の数を取得します。
取得できる数は人間が数える数字と同じなので、
1個、2個と数えるやり方と同じです。
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
// インスタンスを生成
Set<String> twitterGood = new HashSet<>();
// 中身の数を取得 > 0
twitterGood.size();
// 追加 [@sato]
twitterGood.add("@sato");
// 中身の数を取得 > 1
twitterGood.size();
// 追加 [@sato, @suzuki]
twitterGood.add("@suzuki");
// 中身の数を取得 > 2
twitterGood.size();
}
}
要素があるか判定する
Setに要素があるかどうかを判定します。
ただし完全一致しないと存在しないと判定されます。
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
// インスタンスを生成
Set<String> twitterGood = new HashSet<>();
// 追加 [@sato]
twitterGood.add("@sato");
// 追加 [@sato, @suzuki]
twitterGood.add("@suzuki");
// 追加 [@sato, @suzuki, @tanaka]
twitterGood.add("@tanaka");
// 存在するかを判定
if (twitterGood.contains("@sato")) {
// 今回は存在するのでtrue
}
// 存在しないかを判定
if (!twitterGood.contains("sato")) {
// 今回は完全一致しないのでtrue
}
}
}
便利な使い方
並び替え(ソート)する
上記で紹介した通り、並び替えを行うのであれば、TreeSetを使用します。
自動的に並び替えが行われます。
デフォルトは昇順のため、逆順に指定することで、降順に並び替えもできます。
ただ、自動のため少し特殊な並び替えは自分で実装しないといけません。
そういう場合は判定したうえで、LinkedHashSetに順に追加するのが楽でしょう。
import java.util.Collections;
import java.util.TreeSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
// インスタンスを生成
Set<String> twitterGood = new TreeSet<>();
// 追加 [@suzuki]
twitterGood.add("@suzuki");
// 追加 [@sato, @suzuki]
twitterGood.add("@sato");
// 追加 [@sato, @suzuki, @tanaka]
twitterGood.add("@tanaka");
// インスタンスを生成
Set<String> twitterGoodReverse = new TreeSet<>(Collections.reverseOrder());
// 追加 [@suzuki]
twitterGoodReverse.add("@suzuki");
// 追加 [@suzuki, @sato]
twitterGoodReverse.add("@sato");
// 追加 [@tanaka, @suzuki, @sato]
twitterGoodReverse.add("@tanaka");
}
}
要素すべてを出力する
実は1つを取得する機能が存在していないので、ループで取得します。
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
// インスタンスを生成
Set<String> twitterGood = new HashSet<>();
// 追加 [@suzuki]
twitterGood.add("@suzuki");
// 追加 [@sato, @sato]
twitterGood.add("@sato");
// 追加 [@sato, @suzuki, @tanaka]
twitterGood.add("@tanaka");
// ループですべて出力
for (String good : twitterGood) {
// 順に出力 > @sato, @suzuki, @tanaka
System.out.println(good);
}
}
}
まとめ
Javaのコレクションの「Set」の紹介でした。
Setに限らずにJavaのコレクションを使いこなせれば、
楽に処理を実装できますし、わかりやすく書けますので、WinWinです。
使いこなせれば世界が変わるといっても過言ではないと思います!
以上、ここまで見ていただきありがとうございます。
皆さまの快適な開発ライフに、ほんの少しでもお役に立てれば幸いです。