検索

キーワード


【Java】ArrayList, LinkedList, Vector の違いと代表的な8つのメソッド

  • 公開日:2020-07-22 19:34:21
  • 最終更新日:2021-01-25 17:44:34
【Java】ArrayList, LinkedList, Vector の違いと代表的な8つのメソッド

こんにちは、駆け出しプログラマーの若江です!

ここでは初学者として学習を終えた私が、アウトプットの意味も込めてコレクションのListについてご紹介させていただきます。

できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!


関連記事リンク:コレクションの概要 / 拡張for文の紹介 / コレクション(Set)の紹介 / コレクション(Queue, DeQue)の紹介 / コレクション(Map)の紹介 / コレクション(Iterator)の紹介

コレクション:Listインターフェース ~代表的な3つのクラスと8つのメソッド~

ListはCollectionインターフェースを継承したインターフェースです。

複数データを格納できるListインターフェースですが、

このデータ群の中に重複データがあっても、データは問題なく格納される特徴を持っています。

 ※対比して別記事で紹介する「Set」にはこの特徴がありません。

ここではListインターフェースを実装した様々なクラスがあるので、その種類や特徴などを紹介させていただきます。


Listインターフェースを実装した代表的なクラス

ArrayList・LinkedList・Vectorのクラスの特徴、違いを見ていきましょう。

主な機能は同じため、実装したい内容によって使用するクラスを使い分けることになります。


ArrayList

Listインターフェースを実装したクラスの中で一番ポピュラーな可変長配列クラスです。

ArrayListはデータを順序管理しながら格納する特徴を持ちます。

順序でデータ管理を行うため、「〇番目にあるデータ」といったように指定した番号のデータを直接見に行くことができます。

上記特徴を持つためArrayListは、スピーディに格納されたデータへアクセスすることができます

 例) 0番目 a, 1番目 b, 2番目 c, 3番目 d ... → 2番目のデータが見たい → 「c」を表示


ただし順序を割り振ってデータを管理する分、処理工数が増えてデータを追加するスピードが遅くなります。

◆ArrayListのサンプルコード

import java.util.ArrayList;
import java.util.List;
//ArrayListのインスタンスをString型で生成。
List<String> list = new ArrayList<String>();

list.add("a"); // 0番目
list.add("b"); // 1番目
list.add("c"); // 2番目
list.add("d"); // 3番目

System.out.println(list); //結果 a, b, c, d が表示される




LinkedList

ArrayListと同じくListインターフェースを実装していますが、機能の強み弱みは正反対の部分があります。

またDequeインターフェースも同時に実装しており、データ追加がFIFO方法とLIFO方法の両方を可能としています。

 ※FIFO = 先入れ先出しでデータを扱う。LIFO = 後入れ先出しでデータを扱う。


LinkedListは個データの前後に連結情報を与えて管理する特徴を持ちます。

1本の紐のように各データが前後情報でつながってできているコレクションで、

データを探す際に先頭データまたは末尾データから順番に見ていくため、個データへのアクセスに時間がかかります

 イメージ(例): □ データ1 ●, ● データ2 △, △ データ3 ◆,  … → 「データ3」が見たい → 先頭または末尾から順番に検索


しかしデータの追加や削除などはデータそのものの追加/削除をするだけで、

ArrayListのように順序を付ける作業がないため、データ追加/削除などの操作がスピーディに行えます。

また順序管理はしていませんが、データ挿入位置を番号で指定することは可能となっています。

(データ追加は特に指定がなければ末尾へ追加されていきます)

◆LinkedListのサンプルコード

import java.util.LinkedList;
import java.util.List;
// String型のLinkedListインスタンスを生成
LinkedList<String> linked = new LinkedList<String>();

linked.add("データ1");
linked.add("データ2");
linked.add("データ3");

System.out.println(linked); // 結果 データ1, データ2, データ3 が表示される



Vector

Java1.0以前から用意されている、可変長配列の中でも長寿のクラスです。

基本的な機能はArrayListと同じため、現在では特別な理由がない限りArrayListを利用することが一般的となっています。

何かの理由でVectorを利用する場合は以下の特徴を押さえておきましょう。

・マルチスレッド環境での同期化にも整合性を保つことができる機能がデフォルトで用意されている。

 スレッドの動作を止めて情報を取得(同期化)します。

 複数のスレッドから操作があっても対応できる点で優れていますが、

 単体スレッドの操作であっても複数スレッドと同じく同期化するため動作スピードが遅くなります。

 ただし、ArrayListでもjava.util.Collections(Collections.synchronizedList()メソッド)を使うことで同期の機能を実現できます。

・格納するデータに対して容量が足りなくなると現在の容量100%分のスペースを確保します。

 ※ArrayListは50%分のスペースを確保します。


Vectorの書き方はArrayListなどと同じです。

import java.util.List;
import java.util.Vector;
Vector<String> v = new Vector<String>();
v.add("a");
v.add("b");
v.add("c");

System.out.println(v); //結果: a, b, c が表示される



可変長配列の代表的なメソッド8つ

ここでは上記クラスでよく利用するメソッドを紹介します。

大きく分けるとコレクション操作には「追加」「削除」「検索」の3つがあります。

「追加」「削除」「検索」操作をベースに以下8つが代表的なメソッドです。

 ※ここではサンプルコードのimportを割愛しています。


    add    :リストの末尾にデータを追加します。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");

// aが追加され、次いでbが末尾に追加される
System.out.println(list); //結果: a, b と表示


 ◆格納するデータの順序を指定した場合の例

List<String> array = new ArrayList<String>();
array.add("a");
array.add("c");
array.add(1, "b"); // 1番目( a と c の間)に b を追加

System.out.println(array);//結果:a, b, c が表示される


   clear   :リスト内の全てのデータを削除します。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list); //結果: a, b, c が表示される

list.clear();
System.out.println(list); //結果: 空になる


contains:指定したデータがリスト内にあった場合 true を返します。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list); //結果: a, b, c がリスト内にあることを確認

if(list.contains("a")) {
	System.out.println("true"); //結果: a が含まれているので true を表示
}
if(list.contains("d")) {
	System.out.println("true"); //結果: d が含まれていないのでスルー
}


isEmpty :リストにデータがない場合にtrueを返します。

List<String> list = new ArrayList<String>();
//リストが空なので a b c を追加
if(list.isEmpty()) {
	list.add("a");
	list.add("b");
	list.add("c");
}
//リストに a b c が入っているのでスルー
if(list.isEmpty()) {
	list.add("d");
	list.add("e");
	list.add("f");
}
			
System.out.println(list); //結果: a, b, c が表示される


remove :リスト内に指定したデータがあればそのリストから1つ削除します。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
System.out.println(list); //結果: a, b, c, d が入っていることを確認

list.remove("d");
System.out.println(list); //結果: d が削除されて a, b, c が表示される


 ◆removeは番号(順序)でもデータを指定削除できます。

List<String> array = new ArrayList<String>();
array.add("a");
array.add("b");
array.add("c");
array.add("d");
System.out.println(array);//結果: a, b, c, d が入っていることを確認

array.remove(2); // 2番目のデータを削除( 0番目=a, 1番目=b, 2番目=c, 3番目=d )
System.out.println(array);//結果: c が削除されて a, b, d が表示される

 ※リストに格納されたデータ個数以上の順序を指定すると、実行時に例外(IndexOutOfBoundsException)がスローされます。


 ◆重複したデータに対してremoveを行った場合は先頭に近いデータから1つ優先的に削除されます。

List<String> array = new ArrayList<String>();
array.add("a");
array.add("b");
array.add("c");
array.add("b"); //重複データ
System.out.println(array);//結果: a, b, c ,b が入っていることを確認

array.remove("b"); // 先頭に近い方の b (重複文字が)優先的に削除される。
System.out.println(array);//結果: b が削除されて a, c, b と表示される


    size    :リスト内のデータ個数を返します。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list.size()); //結果: 3 (a, b, cの3つ)が表示される


iterator :リスト内のデータを1つずつ取り出すといった、for文のような動作をします。

      今までのように単なるSystem.out.println()で中身を表示させるではなく、

         中身を1つずつ取り出してSystem.out.println()で表示させます。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

// hasNextメソッドは次のデータが存在する場合にtrueを返す
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
	String str = iterator.next(); // nextメソッドは次のデータを取得する
	System.out.println(str); //結果: aが取り出され、次いで b, c と順次データが取り出されていく
}

 ※hasNext と next は Iteratorインターフェースが持つメソッドです。

 ※拡張for文でも上記の動作を実現することができます。これは拡張for文が暗黙的にIteratorを使用しているためです。


toArray :リストを配列へ変換します。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
			
// list.size で配列の大きさを決めて、String型の配列 array を生成
String[] array = new String[list.size()];
			
// listを配列に変換
list.toArray(array);

// Arrays.toString で文字列へ変換して、配列 array の中身を表示
System.out.println(Arrays.toString(array));

 ※配列からリストへの変換も可能です。その際は asListメソッドを使用します。

以下のように配列インスタンス生成と同時にリストを配列へ変換する、簡略化した書き方もできます。

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

String[] array = list.toArray(new String[] {}); // 配列インスタンス生成と同時にリストを配列へ変換
System.out.println(Arrays.toString(array));



コレクションの比較

最後にリスト同士の比較方法を紹介します。

リスト同士の比較には Objectsクラスの equalsメソッドを使用することができます。

 ※比較演算子( == )は中身の比較を行いませんのでその違いに注意してください。


Objectsクラスを使ったリストの中身の比較方法

ObjectsクラスはObjectクラスを継承したクラスでJava1.7より追加されました。

Objectsクラスに実装されているequalsメソッドはObject同士の中身を比較することができます。

また、Objectの中身がnullでも許容する特徴を持っています。(NullPointerExceptionが発生しません)

そのため比較対象の双方が null を保有していた場合、trueを返します。


上記を踏まえて実際に Objects#equals を使ったリスト同士の比較方法を見てみましょう。

import java.util.Objects;
import java.util.List;
import java.util.ArrayList;
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");

List<String> list1 = new ArrayList<String>();
list1.add("a");
list1.add("b");
list1.add("c");

List<String> list2 = new ArrayList<String>();
list2.add("a");
list2.add("b");
list2.add("c");

List<String> list3 = new ArrayList<String>();
list3 = null;

List<String> list4 = new ArrayList<String>();
list4 = null;

System.out.println(Objects.equals(list, list1));  // a, b, c, d と a, b, c の比較でfalseを表示
System.out.println(Objects.equals(list1, list2)); // a, b, c と a, b, c の比較でtrueを表示
System.out.println(Objects.equals(list1, list3)); // a, b, c と null の比較でfalseを表示
System.out.println(Objects.equals(list3, list4)); // null と null の比較でtureを表示


リストの中のデータ同士をnullも含んで比較していることがわかりますね。

ちなみにデータの順序も比較対象となるので、「a, b, c」と「a, c, b」はfalseを返すことに注意しましょう。


関連記事リンク

コレクションの概要 / 拡張for文の紹介 / コレクション(Set)の紹介 / コレクション(Queue, DeQue)の紹介 / コレクション(Map)の紹介 / コレクション(Iterator)の紹介



【著者】

若江

30代で異業種となるIT業界へ転職した駆け出しのプログラマです。これまで主に Java や Ruby、HTML/CSS を使って学習を目的としたショップサイトや掲示板サイトの作成を行いました。プログラマとしての経験が浅いからこそ、未経験者の目線に近い形で基礎の紹介をしていきたいと思います。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様