Java コレクション
コレクションと配列は、Java コンテナと呼ばれる複数のデータを格納する構造です。
このときのストレージとは主にメモリ レベルのストレージを指し、永続的なストレージ (txt、jpg、avi) は含まれません。
Java コレクションは、コレクションとマップの 2 つのシステムに分けることができます。
1. コレクション インターフェイス: 一連のオブジェクトにアクセスするためのメソッドのコレクションを定義する単一のデータ列
List: 順序付けされた反復可能な要素を含むコレクション --> 動的配列
ArratList、LinkedList、Vector
Set: 順序付けされていない反復不可能な要素を含むコレクション --> 数学における Sets
HashSet、LinkedHashSet、および TreeSet
2. マップ インターフェイス: 2 列データ、マッピング関係「キーと値」を持つセットを保存 --> 高校関数、1 つのキーを 2 つの値に対応させることはできません。Pythonの辞書
ハッシュマップ、LinkedHashMap、ツリーマップ、ハッシュテーブル、プロパティ
Collection インターフェースの API (すべてコード内でコメント化されています)
package Collection;
import java.awt.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import org.junit.Test;
public class CollectionTest {
@Test
// 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类重写equals。否则Obj里面比的是地址
public void test1(){
Collection coll = new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
//size():获取添加的元素的个数
System.out.println(coll.size());
//addAll() 将coll1中的元素添加到coll中
Collection coll1 = new ArrayList();
coll1.add("CC");
coll1.add(456);
coll.addAll(coll1);
System.out.println(coll);
// clear() 清空集合元素
coll.clear();
// isEmpty() 判断当前集合是否为空
System.out.println(coll.isEmpty());
// contains 当前集合中是否包含xx.调用的是equals
// 在判断时会调用OBJ对象所在类的equals方法
System.out.println(coll.contains("CC"));
// containsAll(Collection coll1) 判断形参coll1中的所有元素是否都在当前集合中
Collection coll2 = Arrays.asList(123,456);
System.out.println(coll.containsAll(coll2));
}
@Test
public void test2(){
Collection coll = new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
//remove 返回的是布尔值,移除了就返回true
coll.remove("AA"); //可以用一个boolean的值去接收他
System.out.println(coll);
// removeAll(Collention coll1) 从当前元素中移出cool1中所有元素
Collection coll1 = Arrays.asList(123,4567);
coll.removeAll(coll1);
System.out.println(coll);
}
@Test
public void test3(){
Collection coll = new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
// // 获取当前集合与coll1的交集,并返回给当前集合
// Collection coll1 = Arrays.asList(123,456,789);
// coll.retainAll(coll1);
// System.out.println(coll);
// equlas
Collection coll2 = new ArrayList();
coll2.add("AA");
coll2.add("BB");
coll2.add(123);
coll2.add(new Date());
System.out.println(coll.equals(coll2)); //顺序也要一样噢
}
@Test
public void test4(){
Collection coll = new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
//hashCode() 返回当前对象的哈希值
System.out.println(coll.hashCode());
// 集合---->数组,toArray()
Object[] arr = coll.toArray();
for(int i = 0;i < arr.length ; i++){
System.out.println(arr[i]);
// 扩展:数组-->集合,调用Arrays类的静态方法asList()
// List<String> list = Arrays.asList(new String[]{"AA","BB","CC"});
// System.out.println(list);
//
}
}
}
イテレータインターフェイスはコレクション要素を横断します
package Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import org.junit.Test;
public class IteratorTest {
@Test
public void test(){
Collection coll = new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
Iterator iterator = coll.iterator();
//方式一:不推荐
for (int i = 0;i < coll.size();i++){
System.out.println(iterator.next());
}
// 方式二:推荐
while(iterator.hasNext()){ //还有没有下一个
//next指针下移,将下移后的值返回
System.out.println(iterator.next());
}
// // 错误方法,他每调一次while 就有一个新的迭代器
// while(coll.iterator().hasNext()){
// System.out.println(coll.iterator().next());//死循环
// }
}
// remove方法,在遍历中删除集合中的元素,不同于集合直接调用remove
@Test
public void test2(){
Collection coll = new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
Iterator iterator = coll.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
if("AA".equals(obj)){
iterator.remove(); //删除集合中AA字符串
}
}
iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
JDK5.0 では、コレクションと配列を走査するための foreach ループが追加されました。
package Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import org.junit.Test;
public class ForTest {
@Test
public void test(){
Collection coll = new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
// for(集合中元素类型 局部遍历 : 集合对象)
// 内部仍然调用迭代器
for (Object obj : coll){
System.out.println(obj);
}
}
@Test
public void test2(){
int[] arr = new int[]{1,2,3,4};
for(int i : arr){
System.out.println(i);
}
}
@Test
public void test3(){
String[] arr = new String[]{"MM","MM","MM"};
// 方式一 普通for循环 数组内部都会被改变
for(int i = 0;i < arr.length;i++){
arr[i] = "GG";
}
// 方式二:增强for循环,数组内部最后还是不会变,是形参变了
// for(String s : arr){
// s = "GG";
// }
//
for(String s : arr){
System.out.println(s);
}
}
}
リストインターフェース
ArrayList、LinkedList、Vector の類似点と相違点は何ですか?
3 つのクラスはすべて List インターフェイスであり、データの保存、順序付けされた反復可能な配列の保存という同じ特性を備えています。
- List の主要な実装クラスとして、ArrayList はスレッドセーフで効率的であり、最下層はストレージに Object[] elementData を使用します。
- LinkedList の最下層は二重リンク リストを使用します。これは、頻繁な挿入と削除に対して ArrayList よりも効率的です。
- Vector は List の古い実装クラスであり、スレッドセーフで非効率的です。最下層は Object[] elementData を使用して格納します
配列リスト
jdk7 の場合、
ArrayList List = new ArrayList(); //最下層は長さ 10 の Object[] 配列を作成 List.add
(123); //elementData[0] = new Integer(123);
この追加の場合、基になるアレイの容量が不十分な場合は、容量が拡張され、
元のサイズの 1.5 倍に拡張され、元のアレイのデータを新しいアレイにコピーする必要があります。
開発ではパラメータを指定したコンストラクターを使用することをお勧めします。 ArrayList List = new ArrayList(int Capacity)
jdk8 での ArrayList の変更点 ArrayList
List = new ArrayList();//基になる Object[] elementData は { } に初期化され、長さ 10 の配列は作成されません。List.add(123); は長さの配列のみを作成します
。 elementData[0]に10、123を加算し
、以降の加算・展開操作はjdk7と同じです
概要: jdk7 での ArrayList オブジェクトの作成は、シングルトンの飢えた中国スタイルに似ています。jdk8 での ArrayList オブジェクトの作成は、シングルトンの遅延スタイルに似ています。配列の作成が遅れるため、メモリが節約されます。
リンクリスト
LinkedList list = new LinkedList;//
ノードの最初と最後のリストの内部宣言 type.add(123);//123 をノードにカプセル化し、ノード オブジェクトを作成
ベクター
最下層は、長さ 10 の Object[] 配列を作成します。拡張に関しては、拡張は元の 2 倍になります。
リストAPI
インターフェイスの設定
セット ---- 順序付けされておらず、反復不可能
- HashSet: Set インターフェイスの主要な実装クラスとして、スレッドセーフではなく、null 値を格納できます。
- LinkedSet: HashSet のサブクラスとして、その内部データをトラバースするときに、追加されたデータに従ってトラバースできます。
- TreeSet: 追加された要素の指定した属性で並べ替えることができます
無秩序: ランダム性とは異なります。格納されるデータは、基になる配列の配列インデックスの順序で追加されるのではなく、データのハッシュ値に従って決定されます。
非反復性:追加した要素をequalsメソッドで判定した場合、trueを返すことができない、つまり同じ要素を追加することができない。
要素を追加するプロセス (HashSet を例として取り上げます)
要素 a を HashSet に追加し、まず要素 a の hashcode() メソッドを呼び出し、要素 a のハッシュ値を計算し、このハッシュ値を使用して HashSet の下部にある格納場所を計算し、この位置に他の要素があるかどうかを判断します。他の要素がない場合
は直接配置します。
この位置に別の要素 b がある場合 (またはリンクされたリストに格納されている場合)、a と b のハッシュ値を比較します。
ハッシュ値が要素 a が同じでない場合は、要素 a を追加します。
ハッシュ値が同じである場合は、要素 a が配置されているクラスの equals メソッドを呼び出す必要があります。追加が成功した場合は true が返されます。ケース 2 と
3 の場合、要素a と既存のデータはリンク リストの形式で保存されます。
jdk7.0: 要素 a は元の配列に配置され、元の配列を指します
。 jdk8.0: 元の要素は配列内にあり、要素 a を指します。
Set コンテナに格納されているクラスの場合、ハッシュコードとイコールを書き換える必要があります
Alt + shift + s を直接押して生成するのが最善です
LinkedHashSet がデータを追加している間、各データは 2 つの参照も維持し、このデータの前後のデータを記録します。
利点: 頻繁なトラバーサル操作の場合、LinkHashSet は HashSet より効率的です。
ツリーセット
TreeSet に追加されるデータは同じクラスのオブジェクトである必要があります
2 種類のソート: 自然ソート、カスタムソート
自然な並べ替えでは、2 つのオブジェクトが同じかどうかを比較するための標準:compareTo() メソッドは等しくなくなりました。
カスタム並べ替え: TreeSet を構築するときにパラメーターがあり、パラメーターは比較メソッドの Compare() メソッドです。
マップインターフェース
Map: 二重列データ、キーと値のペアの保存は高校の関数に似ています: y = f(x)
|----------HashMap Map の主要な実装クラスとして、スレッドセーフです。そして非常に効率的です。null のキーと値を保存できる
--------------------------------------LinkedHashMap: マップ要素を走査するときに、次の順序で走査できることを確認します。それらは追加されます。
理由: 元の HashMap の基礎構造に基づいて、前後の要素を指すポインターのペアが追加されます。
頻繁なトラバーサル操作の場合、このタイプの実行効率は HashMap よりも高くなります
|---------- TreeMap: ソートされたトラバーサルを実現するために、追加されたキーと値に従ってソートされることが保証されます。このとき、キーの自然な並べ替えとカスタム 並べ替えを考慮してください。最下層は、スレッドセーフ
で非効率な古い実装クラスとして red-black Tree |------Hashtable を使用します。null キーと値を保存できません
-------------------------- プロパティ: 構成ファイルの処理によく使用されます。キーと値は両方とも文字列型です
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
public class MapTest {
@Test
public void test(){
Map map = new HashMap();
map.put(null, null);
System.out.println(map);
}
}
HashMap の最下層
配列 + リンク リスト (jdk7 より前)
配列 + リンク リスト + 赤黒ツリー (jdk8.0)
マップ構造の理解
マップ内のキーは順序付けされておらず、反復不可能です。すべての値を保存するには Set を使用します --> キーが属するクラスは、equals と hashCode をオーバーライドする必要があります (hashMap を例にします)。マップ内の値は次のとおりです
。順序なしで反復可能です。コレクションを使用すると、すべての値が保存されます -> 値が属するクラスは、equals をオーバーライドする必要があります
。キーと値のペア: キー - 値は、マップ内のエントリ オブジェクトを構成します
: 順序がなく反復不可能です。セットを使用して、すべてのエントリを保存します。
HashMap の基本的な実装原理 (説明するために jdk7 を例として取り上げます)
HashMap map = new HashMap();
最下層は、長さ 16 の 1 次元配列 Enter[] テーブルを作成します
...
map.put(key1, value1);
まず、key1 が配置されているクラスの hashcode() が呼び出され、ハッシュ値が計算されます。 key1 のハッシュ値です。このハッシュ値は何らかの計算を受けます。後で、Entry 配列内の保存場所が取得されます。この場所のデータが空の場合、この時点で key1 - value1 が正常に追加されます (ケース 1)。この場所が空でない場合は
、 、(リンクされたリストの形式で 1 つまたは複数のデータがあることを意味します)、key1 とそのハッシュ値を比較し、
key1 とそのハッシュ値が異なる場合、key1 - value1 は正常に追加されます - ケース 2
の場合key1 のハッシュ値がすでに存在します データの 1 つが同じである場合、key1 が配置されているクラスの equals メソッドを比較します。equals が
false を返した場合、key1 - value1 は正常に追加されます (ケース 3)
。equals が true を返した場合、value1 を使用して同じキーの値を置き換えます。
ケース 2 とケース 3 については、連続追加処理でkey1 - value1 のデータが連結リスト形式で格納されるため、拡張が問題となりますが、デフォルトの拡張方法では、元の容量の 2 倍に拡張し、そのデータを置き換えます。元の容量、データの複製
jdk8 と Jdk7 のいくつかの違い
new HashMap() が使用される場合、長さ 16 の配列は作成されません。jdk
の基礎となる配列は、エントリ配列ではなく、ノード タイプの配列です。put
() メソッドが初めて呼び出されるとき、次の配列が作成されます。長さ 16 が作成されます
jdk7.0 の基底構造は のみ、配列 + リンク リスト jdk8.0 の基底構造は配列 + リンク リスト + 赤黒ツリーです 配列のリンク
リストのデータ要素数がインデックスは 8 より大きく、現在の配列の長さは > 64、
すべての配列はインデックス位置にあります 赤黒ツリー ストレージに変更します
ソースコード
LinkedHashMap (理解するだけ)
要素の追加前後の順序を記録できるため、
トラバーサル操作が多い場合はLinkedHashMapの使用を検討できます。
Map インターフェースで定義されたメソッド
一般的に使用される方法:
追加: put
削除: 削除
変更: put
クエリ:
長さを取得: size()
トラバース: keySet/values()/enterSet
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
public class MapTest {
@Test
public void test(){
Map map = new HashMap();
map.put(null, null);
System.out.println(map);
}
@Test
public void test2(){
Map map = new HashMap();
map.put("aA",1);
map.put("bA",2);
map.put("cA",3);
// 遍历所有的key
Set set = map.keySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
// 遍历所有的values,是Collection 可以直接用它的方法
Collection coll = map.values();
for(Object obj : coll){
System.out.println(obj);
}
// 遍历所有的key - value
Set entrySet = map.entrySet();
Iterator iterator2 = entrySet.iterator();
while(iterator2.hasNext()){
// System.out.println(iterator2.next());
Object obj = iterator2.next();
Map.Entry entry = (Map.Entry) obj;
System.out.println(entry.getKey() + "------>" + entry.getValue());//也能这样
System.out.println(obj.);
}
}
}
TreeMap にキーと値を追加します。キーは同じタイプのオブジェクトである必要があります。
キーをソートする必要があるため、自然ソート、カスタマイズされたソート
プロパティ
キーと値はすべて文字列型です
package Collection;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Properties;
import org.junit.Test;
public class PropertiesTest {
@Test
public void test() throws Exception{
Properties pro = new Properties();
FileInputStream fis = new FileInputStream("jdbc.properties");
pro.load(fis); //加载对应流文件
String name = pro.getProperty("name");
System.out.println(name);
}
}
jdbc.propertiesは次のとおりです
コレクションツールクラス
Collectionsは、CollectionとMapを操作するためのツールクラスです。
コレクションとコレクションの違い