1. 程式人生 > 其它 >遍歷目錄下的所有檔案,同時獲取檔案的型別

遍歷目錄下的所有檔案,同時獲取檔案的型別

集合介紹

  陣列:一旦建立物件,分配記憶體空間,不可改變空間大小(無法動態擴容)

  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());
	}
}