質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

Q&A

解決済

1回答

928閲覧

ArrayListの動き方がわかりません。

kaguyabito

総合スコア3

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

0グッド

1クリップ

投稿2024/01/06 16:14

編集2024/01/07 02:04

疑問解決
初めての質問のため、至らない部分があるかと存じますが、ご了承ください。

1次元リストから要素を2つずつ取り出して2次元リストを作る場合を想定します。

前提

Java初心者です。

QiitaというサイトでArrayListのnewとclear()の違いに関する記事を拝見していたのですが
配列の格納のされ方がよくわからず、関係のないところで気になってしまい
自分で確認できないか試してみたんですが、足跡は追えてもなぜそういう動きをするのかがわからないため質問させていただきます。
以下記事に掲載されていたソースコードです。

import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class TestArraylist { public static void main(String args[]) { // 出力用の2次元リスト List<ArrayList<String>> sampleLists = new ArrayList<>(); // sampleListsに要素を追加するための一時的なリスト ArrayList<String> listA = new ArrayList<>(); // 適当なサンプル List<String> listB = Arrays.asList("AA", "BB", "CC", "DD", "EE", "FF"); // 要素数が2のリストを作ってsampleListsに追加する for (int i = 0; i < listB.size(); i++) { if (i % 2 == 0) { listA.add(listB.get(i)); continue; } sampleLists.add(listA); listA.add(listB.get(i)); // new前の確認 System.out.println(sampleLists); // 一時的なリストをnewする listA = new ArrayList<>(); // new後の確認 System.out.println(sampleLists); } } }

出展:https://qiita.com/RoG/items/850390f97702144471cf

listAにlistBの”AA”を格納した後に、ifブロックを抜けsampleListにlistAの"AA"を格納したのち
listAにlistBの"BB"を格納しているのですが、その結果、sampleListになにも格納していないにも関わらず、listAに格納したはずの"BB"がsampleListにも格納されていました。
なぜなのでしょう。

試したこと

足跡がわかるように通ったところにa,b,c,dと出力するようにしたのですが
仕組みがわかりませんでした。


上記省略

for

1 System.out.println("a"); 2 if (i % 2 == 0) { 3 listA.add(listB.get(i)); 4 System.out.println("b"); 5 continue; 6 } 7 System.out.println("d"); 8 System.out.println(sampleLists); 9 10 sampleLists.add(listA); 11 12 System.out.println(sampleLists); 13 System.out.println(listA); 14 15 listA.add(listB.get(i)); 16 // new前の確認 17 System.out.println(sampleLists); 18 System.out.println(listA); 19 System.out.println("c"); 20 21 // 一時的なリストをnewする 22 listA = new ArrayList<>(); 23 // new後の確認 24 System.out.println(sampleLists); 25 System.out.println(listA); 26 } 27 } 28}


出力結果

a

1b 2a 3d 4[] 5[[AA]] 6[AA] 7[[AA, BB]] 8[AA, BB] 9c 10[[AA, BB]] 11[] 12a 13b 14a 15d 16[[AA, BB]] 17[[AA, BB], [CC]] 18[CC] 19[[AA, BB], [CC, DD]] 20[CC, DD] 21c 22[[AA, BB], [CC, DD]] 23[] 24a 25b 26a 27d 28[[AA, BB], [CC, DD]] 29[[AA, BB], [CC, DD], [EE]] 30[EE] 31[[AA, BB], [CC, DD], [EE, FF]] 32[EE, FF] 33c 34[[AA, BB], [CC, DD], [EE, FF]] 35[]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2024/01/06 17:21

コードやパソコンの画面に表示されたモノ(結果やエラー等)はファイル・其々毎にコードのマークダウン( ``` だけの行で前後を囲む)を用いてください。 普通の文章内に書くと一部の記号等が修飾等に使われて表示されなかったりします。 質問の編集時にもプレビューがあると思います。どのような表示になるか確認してみてください。
y_waiwai

2024/01/06 22:29

このままではコードが読めないので、質問を編集し、</>(コードの挿入)ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
kaguyabito

2024/01/07 02:08

ご指摘ありがとうございます。</>(コードの挿入)ボタンを押し、出てくる’’’の枠の中にコードを貼り付けました。
guest

回答1

0

listAにlistBの”AA”を格納した後に、ifブロックを抜けsampleListにlistAの"AA"を格納したのちlistAにlistBの"BB"を格納しているのですが、その結果、sampleListになにも格納していないにも関わらず、listAに格納したはずの"BB"がsampleListにも格納されていました

listA は ArrayList<String> ですが sampleLists は List<ArrayList<String>> です。従って

sampleListにlistAの"AA"を格納

と言われている

sampleLists.add(listA);

というのは "AA" では無く listA そのものが対象です。(listA の "AA" を入れるなら listA.add(listB.get(i)) と同様に listA から get するはずです。)
listA はオブジェクトですので sampleLists に入るのは listA への参照であり、それは「sampleLists の要素を通して listA が見える」という感じです。
ですから listA を操作した後で sampleLists の内容を表示すると、その時の listA の内容が出てくることになります。
逆にいうと、listA を入れた sampleLists の要素のリストに add したりする(sampleLists.get(0).add("zzz");)と listA にも変化が現れるいうことです。

オブジェクト間参照イメージ
青い矢印は全て参照です。
List<ArrayList<String>> sampleLists = new ArrayList<>();
ArrayList<String> listA = new ArrayList<>();
listA.add(listB.get(i)); (i=0)
sampleLists.add(listA);
listA.add(listB.get(i)); (i=1)
に当たります。
この後に listA に別のオブジェクト(の参照)を入れても (listA = new ArrayList<>();) ② が他を向くだけで sampleLists の指すオブジェクトは変わりません。

投稿2024/01/06 17:33

編集2024/01/06 19:33
jimbe

総合スコア13168

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kaguyabito

2024/01/07 02:21

sampleListにlistAの「参照」を入れていたのですね! 納得いたしました。 とても分かりやすいご説明ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問