遍歷目錄下的所有檔案,同時獲取檔案的型別
集合介紹
陣列:一旦建立物件,分配記憶體空間,不可改變空間大小(無法動態擴容)
Collection:可以動態擴容,從而避免陣列下標越界。缺點:擴容會消耗你的記憶體,所以使用集合比使用陣列記憶體開銷大。
集合體繫結構
ArrayList集合
特徵:本質是一個Object [] 陣列
可以向集合放入元素,也可以從集合中獲取元素,還可以刪除集合中的元素
既然是一個數組,放入元素和獲取元素(根據下標獲取)速度快,刪除首部元素和中間元素效率低
為什麼要使用泛型?
你可以將任意型別的資料放入ArrayList,取出資料必須強制轉換
泛型:能夠在編譯期對放入和取出的物件(元素)做型別檢查
定義泛型:型別不確定,一旦你在某個類上定義了泛型,可以將泛型作為屬性、引數、返回值
使用泛型:必須明確資料型別,資料型別必須在<>
中定義
什麼時候使用ArrayList?
如果你需要頻繁建立元素,頻繁獲取元素,可以使用
優點:建立和查詢(獲取)元素快
什麼時候不能使用ArrayList?
當你頻繁建立和頻繁刪除元素,不要使用ArrayList
缺點:刪除首部元素和中間元素效率低
如何建立一個ArrayList型別的物件
使用new的方式建立
package com.whsxt.day5.arraylist; import java.util.ArrayList; import java.util.List; public class TestArrayList1 { public static void main(String[] args) { System.out.println("start"); //ArrayList list = new ArrayList(); //ArrayList是一個List //new ArrayList 是實實在在的物件,在堆記憶體中建立 // list 在棧記憶體中:用來操作堆記憶體中的ArrayList // list遙控器 new ArrayList()電視機 List list = new ArrayList(); //呼叫ArrayList的add(e)方法,將物件放入ArrayList //第一次呼叫list物件的add(e)方法新增元素,會在ArrayList內部的陣列中分配10個空間的元素 list.add("tom1"); list.add("tom2"); list.add("tom3"); list.add("tom4"); list.add("tom5"); list.add("tom6"); list.add("tom7"); list.add("tom8"); list.add("tom9"); list.add("tom10"); //還有新元素新增到ArrayList中,不會出現“陣列下標越界異常” list.add("tom11"); list.add("tom12"); System.out.println("end"); } } String str1 = "a" + 1 + 2; // a12 String str2 = 'a' + 1 + "2"; // 982 (a的ASCll碼為97)97+1+"2"=982 String str3 = 1 + 2 + "a"; // 3a
小結:
第一次呼叫list物件的add(e)方法新增元素,會在ArrayList內部的陣列中分配10個空間的元素,當陣列空間全部使用完畢,還有新元素新增到ArrayList中,不會出現“陣列下標越界異常”,此時陣列會擴容
ArrayList是一個可以動態擴容的陣列
ArrayList擴容(重點)
當我建立ArrayList物件,裡面的陣列大小0,第一次呼叫add(E)方法,陣列大小為10,當元素全部佔滿陣列大小為10,如果繼續新增元素,陣列大小15
0---->10---->15--->22
int size =15; int newCapacity= (size>>1)+size; 1111>>1 111+1111=22 擴容規律:原始長度>>1 + 原始長度
小結:
在呼叫add(e)方法新增元素之前,先判斷陣列有沒有空間儲存新元素,如果有不會擴容,如果沒有才擴容
每次擴容ArrayList裡面的Object elementData[] 指向都會發生改變
擴容機制:在原始陣列的基礎上重新拷貝一份新陣列,此時新陣列會儲存原始數組裡面的元素
import java.util.ArrayList;
import java.util.List;
public class TestArrayList1 {
public static void main(String[] args) {
System.out.println("start");
//ArrayList list = new ArrayList();
//ArrayList是一個List
//new ArrayList 是實實在在的物件,在堆記憶體中建立
// list 在棧記憶體中:用來操作堆記憶體中的ArrayList
// list遙控器 new ArrayList()電視機
List list = new ArrayList();
//呼叫ArrayList的add(e)方法,將物件放入ArrayList
//第一次呼叫list物件的add(e)方法新增元素,會在ArrayList內部的陣列中分配10個空間的元素
list.add("tom1");
list.add("tom2");
list.add("tom3");
list.add("tom4");
list.add("tom5");
list.add("tom6");
list.add("tom7");
list.add("tom8");
list.add("tom9");
list.add("tom10");
list.add("tom11");
list.add("tom12");
list.add("tom13");
list.add("tom14");
list.add("tom15");
list.add("tom16");
System.out.println("end");
}
}
ArrayList其它方法
get(int index): 根據下標獲取集合中的元素
size():獲取集合實際的大小
remove(int index):根據下標從集合中刪除元素
remove(E): 根據元素內容從集合中刪除元素
contains(): 判斷某個元素在集合中是否存在,true存在,false不存在
import java.util.ArrayList;
import java.util.List;
public class TestArrayList2 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("Tom");
list.add(123);
list.add(3.14);
list.add('M');
list.add(true);
//獲取集合的第一個元素
Object element =list.get(0);
int size =list.size();
System.out.println(element); //5
System.out.println("刪除之前 size="+size);
//刪除集合中第一個元素
list.remove(0);
int size2=list.size(); //4
System.out.println("刪除之後 size="+size2);
//判斷Abc是否在集合中存在 結果false Abc在集合中不存在
boolean result =list.contains("Abc");
System.out.println(result);
}
}
以下程式碼存在的問題:
1、 放入集合的型別在編譯器不能確定,可以放入任意型別
2、 由問題已引入問題2:元素型別不專一
3、 獲取元素必須使用強制型別轉換
4、 強制轉換的程式碼不安全 int obj= (int) list.get(0); 可能會出現執行時型別轉換異常ClassCastException
要求:解決該問題
目的:放入集合的元素型別必須要專一,要麼全部放String、要麼全部放Boolean
能夠提供編譯器的型別檢查,例如我規定了集合中只能放置String,如果你放置了Boolean,會提示編譯失敗
package com.whsxt.day5.arraylist;
import java.util.ArrayList;
import java.util.List;
public class TestArrayList2 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("Tom");
list.add(123);
list.add(3.14);
list.add('M');
list.add(true);
int obj= (int) list.get(0);
System.out.println(obj);
}
}
泛型
SinceJDK1.5,提供編譯期檢查,解決放入集合元素型別不一致的問題,例如:我定義一個ArrayList集合並且規定了只能放置String,如果你放置其他型別就會編譯報錯
泛型:
1、定義泛型(資料型別不確定)
2、使用泛型 (必須明確資料型別)
定義泛型語法:
< >
用於定義泛型, 鑽石運算子,泛型運算子
public class 類名稱<型別>{
}
使用泛型:
import java.util.ArrayList;
import java.util.List;
public class TestArrayList2 {
public static void main(String[] args) {
//建立一個ArrayList物件,支援泛型,規定了ArrayList只能存放String型別的元素(物件)
List<String> list = new ArrayList<>();
list.add("Tom");
//編譯錯誤:不能講int型別的資料放入ArrayList,因為ArrayList在定義的時候使用了泛型,規定了只能存放String型別
//list.add(123);
//使用泛型好處:獲取元素不用強制型別轉換
String name = list.get(0);
System.out.println(name);
//編譯錯誤:獲取元素也能夠提供編譯檢查,由於泛型規定了只能放置String,那麼使用非String型別接收,就會編譯錯誤
//int num = list.get(0);
//小結:定義ArrayList使用泛型,好處能夠在add()方法和get()方法提供編譯期型別檢查
}
}
Java泛型不支援基本型別
import java.util.ArrayList;
import java.util.List;
public class TestArrayList3 {
public static void main(String[] args) {
//泛型:不支援基本型別
//List<double> list = new ArrayList<>();
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(1);
//Java提供了自動裝箱和自動拆箱,放入ArrayList的元素是包裝型別,取出元素可以用基本型別接受
int num = list.get(0);
System.out.println(num);
System.out.println(list);
}
}
自定義泛型
/**
* @author caojie
* 自己定義一個泛型類
* T: Type 型別
* E: Element 元素
* K: Key 鍵
* V: Value 值
* Foo<T>:我定義的型別Foo支援泛型
* 可以將泛型用於屬性,也可以用於引數,該可以用於返回值
*/
public class Foo<T> {
/**
* 定義一個屬性,名稱叫做type,它在編譯期是一個不確定的型別
*/
private T type;
// 編譯錯誤:泛型屬性名稱必須跟定義泛型的型別一致<T> private T type;
// private E element;
/**
* T:表示返回型別是一個泛型
* @return
*/
public T getType() {
return type;
}
/**
* T type 表示引數是一個泛型
* @param type
*/
public void setType(T type) {
this.type = type;
}
}
/**
* @author caojie
* 可以定義多個泛型,但是必須使用逗號分隔
* @param <K>
* @param <V>
*/
public class FooTwo<K,V> {
private K key;
private V value;
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
public class FooThree<T> {
private T [] types;
public T [] getTypes() {
return types;
}
public void setTypes(T [] types) {
this.types = types;
}
}
/**
* @author caojie
* 使用定義的泛型
*/
public class TestFoo {
public static void main(String[] args) {
// 不使用泛型,程式編譯期不能提供型別檢查,執行期就會出現異常
/* Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at com.whsxt.day5.generic.TestFoo.main(TestFoo.java:14) */
// Foo foo = new Foo();
// foo.setType("Tom");
// int num=(int)foo.getType();
// System.out.println(num);
Foo<String> foo = new Foo<>();
foo.setType("Tomson");
String name = foo.getType();
// 使用泛型能夠提供編譯期型別檢查
// int num = foo.getType();
System.out.println(name);
}
}
import java.util.Arrays;
public class TestFooThree {
public static void main(String[] args) {
FooThree<String> foo =new FooThree<>();
String names[] = {"TOm","Jerry","Jason"};
foo.setTypes(names);
String result[] =foo.getTypes();
System.out.println(Arrays.toString(result));
}
}
public class Test2FooThree {
public static void main(String[] args) {
FooThree<Integer> foo = new FooThree<>();
//int arrs[]= {10,20,30};
//Java雖然能支援自動裝箱和自動拆箱,但是無法運用到泛型
//foo.setTypes(arrs);
Integer arrs[]= {110,20,30};
foo.setTypes(arrs);
}
}
使用泛型自定義一個ArrayList
import java.util.Arrays;
/**
* @author caojie
* 自定義的ArrayList,支援泛型
*/
public class ArrayList<E> {
/**
* ArrayList核心是一個數組
*/
private Object elementData [];
/**
* ArrayList大小
*/
private int size;
public ArrayList() {
//呼叫帶引數的構造方法
this(10);
}
/**
* 帶有一個引數的構造方法
* @param capacity 初始容量
*/
public ArrayList(int capacity) {
elementData = new Object[capacity];
}
/**
* 返回集合的大小(實際容量,不是陣列長度)
* @return 集合大小
*/
public int size() {
return size;
}
/**
* 根據下標獲取集合的元素
* @param index 外界傳入的下標
* @return 返回集合的元素
*/
@SuppressWarnings("unchecked")
public E get(int index) {
//條件成立:下標是非法的,無法獲取陣列元素,丟擲陣列下標越界異常
if(index<0 || index>=size) {
throw new ArrayIndexOutOfBoundsException("size:"+size+" index:"+index);
}
return (E) elementData[index];
}
// 定義擴容次數
private int index = 0;
public void add(E element) {
// 新元素加入到ArrayList中,先檢查容量,如果容量不夠了,需要擴容
int length = elementData.length;
// 條件成立:表示elementData陣列容量已經滿了,需要擴容
if(size>=length) {
//新容量= (舊陣列長度>>1)+舊陣列長度
int newCapacity = (length>>1)+length;
elementData =Arrays.copyOf(elementData,newCapacity);
index++;
System.out.println("擴容"+index+"次");
}
//新加入的元素填充到陣列中
elementData[size++]= element;
}
}
測試泛型
package com.whsxt.day5.generic;
public class TestArrayList {
public static void main(String[] args) {
/*
* 使用無參構造方法建立ArrayList物件擴容太頻繁(23次)
* 不要頻繁擴容,也不要永遠不擴容(效能消耗大)
* 理想方案:擴容次數15次以內
* 注意:每當你定義ArrayList的時候,思考一個問題,我的ArrayList大概需要容納多少元素,呼叫對應的有引數構造方法
* */
ArrayList<Integer> list = new ArrayList<>(2000);
for(int i=0;i<100000;i++) {
list.add(i+10);
}
System.out.println(list.size());
}
}