私の学校での最初のプログラミングクラスの割り当てのほとんどでは、配列を使用する必要がありました。私は今フルタイムで働いており、私が取り組んだプロジェクトでアレイを使用したことはありません。既存のプロジェクトでさえ、どこでも配列の使用を見たことはありません。私の意見では、リストは使いやすく標準です。教授が課題でアレイを使用するよう生徒に指示するのはなぜですか?学生が基本を理解するためだけですか?
ほとんどの大学がJavaを教えているため、この質問はJavaに固有のものです。
私の学校での最初のプログラミングクラスの割り当てのほとんどでは、配列を使用する必要がありました。私は今フルタイムで働いており、私が取り組んだプロジェクトでアレイを使用したことはありません。既存のプロジェクトでさえ、どこでも配列の使用を見たことはありません。私の意見では、リストは使いやすく標準です。教授が課題でアレイを使用するよう生徒に指示するのはなぜですか?学生が基本を理解するためだけですか?
ほとんどの大学がJavaを教えているため、この質問はJavaに固有のものです。
回答:
彼らはおそらく、コンピューターがどのように機能するかを最も正確に表すデータ構造から始めたいと考えていたので、操作しやすくするリストのような高レベルの抽象化を導入し始める前に、基礎に精通しています。そうしないと、特定の構造またはアルゴリズムが一部の操作では低速/高速であり、他の操作では高速ではない理由を理解する方法がありません。リンクされたリストから実際にコンピューターのメモリが作成された場合、世界はまったく異なる場所になります。
同じ理由で、大学での最初のプログラミングクラスはCで、残りのクラスはすべてC ++、Java、その他の言語でした。Cが何らかの形で優れていたり簡単であったりするのではなく、C(および配列)が何も隠さないということです。
上記の答えは素晴らしいですが、私は別のことを考えています。Javaのmain()
方法では、学生は基本的な配列に非常に早く、多くの場合は授業の初日とすぐに遭遇します。どうして?
public static void main(String[] args)
Hello Worldを書くために最初に対処しなければならないことは、それ以降です。(最初にBlueJのようなIDEのティーチングを使用するコースを見てきました。これにより、ポイントアンドクリックして任意のメソッドを実行できますが、それらは脇に置いておきます...)これらのキーワードは少しの間、遅かれ早かれほとんどの教師がそれらを説明したいと思うでしょう。実際、古典的な初心者レベルのテスト問題は、基本的なHello Worldプログラムの各キーワードの意味を生徒に尋ねることです。そして、メインメソッドシグネチャの一部として何を見つけますか?配列(その理由の一部は、歴史的です。Java1.0にはArrayListは存在しませんでした)。配列は、その基本的な知識セットの一部です。リストはありません。
とはいえ、特にオブジェクトとその使用方法が説明された後、クラスがコースの少し後にArrayListを導入することは珍しくありません。JavaのAPコンピューターサイエンスカリキュラムでさえArrayListを含んでいます(以前は知っていましたが、Googleはそれがまだあることを示しているようです)が、ArrayListがListおよびその他のCollections Frameworkを実装しているという事実を無視しています。
最後に、大学のCSプログラムは、学生に優れたJava開発者になる方法を教えるのではなく、CSとプログラミングの概念を探る手段としてJavaを使用するという私の経験です。いくつかのプログラムは専門の開発者を駆り立てることに焦点を当てているかもしれませんが、他のプログラムは理論に焦点を当てているかもしれませんが、いずれの場合も、ほとんどの大学のカリキュラムでは教えられない実際の専門的な仕事でJavaを使用する方法について学ぶべきことがたくさんあります。これは、Effective Javaのようなデザインパターンや技術から、Spring、Hibernate、JUnitなどのフレームワーク、またはJSPやJDBCなどのより一般的なものにまで及びます。その哲学を念頭に置いて、より一般的に使用されるArrayListよりも配列を強調することは、もう少し理にかなっています。
初年度のプログラミングクラスが配列を使用する理由の1つはレガシーです。これは、動的リストを含む標準ライブラリの使用を開始する前に教授が最初に学習した方法です。プリミティブデータ型の使用もより一般的に適用可能です:配列はほとんどすべてのコンピューターに存在します太陽の下での言語(および少数のアセンブリ命令で実装できます)。私がプログラミングを初めて学んだとき、リンクリストを実装することが課題の1つでした。
最初の原則から始めて、「それが基本構造です。この言語(またはそのライブラリ)は、すべてを実行する高レベルのデータ構造を提供しますが、x、y、およびzを提供します」と言う方がはるかに簡単です「つまり、これがこれらの高レベルのデータ構造です。今、ここに隠れているものがあります。」LinkedListとArrayList(またはHashSetとTreeSet)を使用するかどうかを推論することは、通常2年目または3年目のアルゴリズムコースです。リストとマップは同じインターフェースを持ち、同じ結果をもたらしますが、どのサイズのアプリケーションでも動作が劇的に異なる場合があります。プログラミング101を終了すると、プログラミング102が同じ言語を使用するという保証はありません。配列の概念から始める場合、単に「
入門コースで「リスト」よりも「配列」を好むもう1つの理由は、配列が基本的に理解しやすいことです:20の配列bytes
は20バイト(さらに、実装に応じて配列の終わりまたは長さを示すカップルが必要です) )。
「リスト」は完全に異なる魚のケトルであり、基本的に異なるパフォーマンス特性を備えたさまざまな方法(ArrayList、LinkedList、おそらくおそらく忘れてしまったカップル)で実装できます。さまざまなListクラスが何をしているのかを理解しなければ、List foo = new ArrayList()
vs List foo = new LinkedList()
. をいつ使用すべきかについて有意義な議論をすることはできません。生徒にList実装を使用させようとすると、誰かが他の実装の代わりにArrayListを使用している理由を尋ねます。また、「ArrayList」には「Array」という単語が含まれており、その1つに支えられているため、「array」から「ArrayList」への大きなロジックジャンプではありません。
一般に信じられていることとは反対に、特に静的サイズのリストを扱う場合は、リストに対して配列を使用するのが理にかなっている状況があります。ここにカップルがあります:
foo[n]
逆参照し、いくつかの舞台裏は算術ポインタん、しばらくはfoo.get(n)
間接参照を持って、メソッド呼び出しを行い、第二間接参照を行い、その後、多分ポインタ演算を行います(ArrayListを使用している場合、LinkedListsはListのすべての要素を繰り返し処理する必要がある可能性があります)。int[] foo = new int[]{1, 2, 3, 4, 5}
vs. 別のStackOverflow質問の提案perm
がint[256]
順列を保持している場合、配列を使用して簡単にそれを反転させることint[] inv = new int[256]; for (int i=0; i<256; i++) inv[perm[i]]=i;
ができますArrayList<>
。
ArrayList
特定のサイズのデフォルトで初期化されたリストを作成するコンストラクタを簡単に指定できます。
get
し、set
インライン化されません。
get
とset
でライニングすることができ、のようなものはmyList.set(23,myList.get(23)+1)
どこにも近いほど効率的となりますmyArray[23]+=1
。さらに、ボクシングを必要としないタイプであっても、JITterがfor (i=0; i<1000; i++) myList2.set(i+2000,myList2.get(i+3000));
パフォーマンスが近くにあるものに同等のものを提供できる場合、私は非常に驚きSystem.arrayCopy(myArray1,3000,myArray2,2000,1000);
ます。しかし、Javaはそうではありません。
Javaでは、あらゆるタイプの変数を配列に格納できます。対照的に、ArrayList
参照の保存のみを許可します。一つは、このように有用に議論しないことがありArrayList
、自動ボクシングは参照型にプリミティブを変換する方法、および自動アンボクシングする方法を最初に覆うことなく時々プリミティブへの参照タイプを変換します。
for (int i=10; i<=10000; i*=10)
{
ArrayList<Integer> l = new ArrayList<Integer>();
l.add(i);
l.add(i);
l.add(l.get(0));
System.out.print("i=" + i);
System.out.print(" #0==i:" + (l.get(0)==i));
System.out.print(" #1==i:" + (l.get(1)==i));
System.out.print(" #2==i:" + (l.get(2)==i));
System.out.print(" #0=#1:" + (l.get(0)==l.get(1)));
System.out.print(" #1=#2:" + (l.get(1)==l.get(2)));
System.out.println(" #0=#2:" + (l.get(0)==l.get(2)));
}
コードがでint[3]
なくを使用していた場合、ArrayList
驚くことはありません。3つの要素はすべてi
、互いに等しいか等しいかを比較します。ArrayList
ただし、を使用すると、リストの3つの要素すべてが常にに等しくi
、最初と3番目の要素は常に互いに等しく比較されますが、最初の2つの要素は1、10 i
、または100 の場合にのみ互いに等しくなりますが、 (ほとんどの実装で)i
1000または10000の場合ではありません。
Integer
クラスにはネストされたクラスがIntegerCache
ありInteger
、通常-128..127に及ぶ値の範囲に対して事前に初期化されたオブジェクトを保持します。その範囲外の値をボックス化するには、新しいオブジェクトを作成する必要がありますが、キャッシュされた範囲内の値をボックス化すると、に保存されている事前初期化オブジェクトの1つへの参照が返されIntegerCache.cache
ます。優れたJavaプログラマーはInteger
、同じ値をカプセル化する2つのタイプの変数が等しいかどうかを認識している必要がありますが、そのアイデアを早めに導入すると、生徒は恐怖から逃げ出す可能性があります。
==
。自動ボックス化解除がスローされる可能性を考えると、私はそれを完全に拒否する傾向がありますが、その動作==
は特に恐ろしいです。また、==
演算子は16777217==16777216f
[reports true]のような場合にひどく振る舞い、暗黙の変換long v=Math.Round(123456789), w=Math.Round(123456789012345)
は予期しないものになりがちです[これらの式が何をもたらすか推測できますか?]
IntegerCache
、確かにパフォーマンスを向上できる場合がありますが、それは頻繁にちょっとした動作をするだけの間違ったコードを頻繁に引き起こす可能性があります。いくつかの方法で、ボクシングが2つの整数キャッシュからオブジェクトを準ランダムに返し、キャッシュアイテムを新しいものに準ランダムに置き換えるモードがあればよいのに、値-128..127のボックス化動作に依存するコードは非常に長い間成功する見込みはありません。
ArrayList
内部的に配列を使用するという事実のため、最初に配列を使用する方法を教えることは理にかなっていると思います。ArrayList
クラスは、呼び出されたメンバ変数有しelementData
ているObject
配列。
JDK ArrayList
ソースコードから:
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData;
要素を追加、更新、取得、または削除するArrayList
と、この内部配列を使用してこれらの操作を実行します。ユーザーIxrecが既に指摘しているように、これArrayList
は単なる高レベルの抽象化であり、通常は作業が簡単です。
Java
-通常使用する場合にアレイを教える理由を尋ねていましたArrayList
。Javaにはポインターがありません。間違いなく、私はC / C ++はJavaよりも学生を始めるのに適した言語であると考えています。プログラミングの多くのトピックは、C / C ++の知識があればよりよく理解できます。
あなたが言うように、そのリストは実際に作業しやすいと仮定します-それは本当に重要ではありません。学習は、「簡単から難しい」というよりも「基本から複雑」に関するものです。ファンダメンタルズが重要でなければ、コンピューターサイエンスは学術分野にはなりません。既存のフレームワーク/ライブラリを使用して、オンラインチュートリアルからアプリを一緒にクリックする方法を学ぶことができます。(もちろん、誰かがそれらのライブラリを書く必要があります...そしてArrayList
、そもそも誰かが実装しなければなりません....)
ArrayList
は別の配列と「liveItems」カウントを使用することでより適切に処理できます。ただし、配列を操作し、集計する以外に一緒にカウントする便利な方法はありません。
アカデミック教育で最も重要なことは、正しい用語を使用して自分のやることを説明することを教えることだからです。
リストはその配列以外のものです。またjava.util.List
、Javaはインターフェースであるため使用できません。通常java.util.ArrayList
、List実装であるwhichはリストではなく、動的配列のオブジェクトラッパーを使用します。したがって、「リスト」を使用すると言いますが、配列を使用します。
その用語のカオスをスキップし、配列を使用して生徒に配列とは何かを学ぶことは非常に合理的です。Javaで配列を使用する場合、少なくとも配列を使用します。
正直なところ、Javaでプログラミングを教えるのが良い考えではない理由も論点です。プログラミングの基本概念を正しく学ぶことは困難です。
文字通り配列を見たことがなく、まったく使用したことがありませんか?リストに加えて、常にそれらを使用します。通常、Javaは使用しませんが、明らかな類似性を引き出す他の多くの言語を使用します。
配列とリストの間では、一方がより軽量で、さらにポイントが多くなりますが、もう一方はより多くの機能を持ちます。プログラミングの一般的なルールとして、基本的にそれらの線に沿って分割される2つの類似したタイプがある場合、実際に手の込んだものが必要でない限り、軽量のものを選択する必要があります。これは、オーバーヘッドを削減することに加えて、実際にはプログラムと特にそのコードの混乱と状態の量を把握するのに役立ちます。テスト中に問題が発生した場合、見る場所が少なくなります。さらに重要なのは、配列とリストの場合、人々はあなたが実際にそれを使って何をしようとしているかの限られた範囲についてのより良いアイデアを得ます。
そしてええ、学術的な観点から、学生に基本を教えることの追加の理由があります。ただし、これはもう少し深くなります。配列とリストは、より軽量な型の基礎となるインスタンスの上に構築され、頻繁に単にラップされるだけの、より大きな型の良い例です。リストに基本的な配列がない場合でも、リストのように外向きに動作します。リストとは何かを誰かに教えることの一部は、配列とは何かを教えることです。
これは、C ++のような言語では手に負えなくなる可能性があります。C++では、基本的に配列を削除することはできませんが、高レベル言語では、ほとんどリストになります。与えられた状況で彼らがあなたのニーズに完全に合っているなら、なぜあなたは何か他のものを使う必要があるでしょうか?
T[]
は、ゲートからすぐに、任意の順序でアイテムを受け入れる準備ができていますが、変更するにはアイテムを順番にArrayList<T>
追加する必要があります。A T[]
は任意の範囲のアイテムを同じサイズの別の範囲にT[]
比較的迅速にコピーできますが、ArrayList<T>
1つのリストから個別にアイテムを読み取り、他のリストに保存する必要があります。