30天搞定Java--day25

每日一考和複習

每日一考

  1. Map存儲數據的特點是什麼?並指明key,value,entry存儲數據的特點
1.雙列數據,key-value類型
2.key不可重複,無序,存放在Set中
  value可重複,存放在Collection中
  entry存儲key-value,無序,不可重複,存放在Set中
  1. 描述HashMap的底層實現原理(jdk 8版)
1.開始創建回聲明一個空的Node數組,插入第一個元素時會初始化容量爲16
2.當一條鏈路大於8並且數組總容量大於64時會把鏈路調整爲紅黑樹,總容量小於64會擴容一倍,重新插入值
3.當容量大於臨界值且新插入的位置有元素的情況下,會擴容一倍
  1. Map中常用實現類有哪些?各自有什麼特點?
1.HashMap,線程不安全,效率比較高
2.LinkedMap,可以按照插入的順序迭代
3.Properties,常用作配置文件,key和value都是字符串
4.TreeMap,遍歷時輸出內容排序
  1. 如何遍歷Map中的key-value對,代碼實現
Set entrySet = map.entrySet();
Iterator iterator1 = entrySet.iterator();
while (iterator1.hasNext()) {
    Object obj = iterator1.next();
    //entrySet集合中的元素都是entry
    Map.Entry entry = (Map.Entry) obj;
    System.out.println(entry.getKey() + "---->" + entry.getValue());
}
  1. Collection和Collections的區別?
Collection是一個接口,繼承了iterable接口,包含一些List、Set的通用方法
Collections是一個工具類,包含集合和Map的一些常用方法

複習
day24的學習內容

泛型

爲什麼要有泛型

  • 集合容器類在設計階段/聲明階段不能確定這個容器到底實際存的是什麼類型的對象,所以在JDK1.5之前只能把元素類型設計爲Object,JDK1.5之後使用泛型來解決
  • 把元素的類型設計成一個參數,這個類型參數叫做泛型
  • 所謂泛型,就是允許在定義類、接口時通過一個標識表示類中某個屬性的類型或者是某個方法的返回值及參數類型。這個類型參數將在使用時(例如,繼承或實現這個接口,用這個類型聲明變量、創建對象時)確定(即傳入實際的類型參數,也稱爲類型實參)

在集合中使用泛型

① 集合接口或集合類在jdk5.0時都修改爲帶泛型的結構
② 在實例化集合類時,可以指明具體的泛型類型
③ 指明完以後,在集合類或接口中凡是定義類或接口時,內部結構(比如:方法、構造器、屬性等)使用到類的泛型的位置,都指定爲實例化的泛型類型
比如:add(E e) —>實例化以後:add(Integer e)
④ 注意點:泛型的類型必須是類,不能是基本數據類型。需要用到基本數據類型的位置,拿包裝類替換
⑤ 如果實例化時,沒有指明泛型的類型。默認類型爲java.lang.Object類型

ArrayList<Integer> list = new ArrayList<Integer>();

list.add(78);
list.add(87);
list.add(99);
list.add(65);
//編譯時,就會進行類型檢查,保證數據的安全
list.add("Tom");

//方式一:
for(Integer score : list){
    //避免了強轉操作
    int stuScore = score;

    System.out.println(stuScore);
}
//方式二:
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
    int stuScore = iterator.next();
    System.out.println(stuScore);
}
//jdk7新特性:類型推斷
Map<String, Integer> map = new HashMap<>();

//泛型的嵌套
Set<Map.Entry<String, Integer>> entry = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();

自定義泛型結構

  • 自定義泛型類
    如果定義了泛型類,實例化沒有指明類的泛型,則認爲此泛型類型爲Object類型
    要求:如果定義了類是帶泛型的,建議在實例化時要指明類的泛型
public class Order<T> {

    String orderName;
    int orderId;

    //類的內部結構就可以使用類的泛型

    T orderT;

    public Order() {
        //編譯不通過
        T[] arr = new T[10];
        //編譯通過
        T[] arr = (T[]) new Object[10];
    }

    public Order(String orderName, int orderId, T orderT) {
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }
}
class Person<T> {
    // 使用T類型定義變量
    private T info;

    // 使用T類型定義一般方法
    public T getInfo() {
        return info;
    }

    public void setInfo(T info) {
        this.info = info;
    }

    // 使用T類型定義構造器
    public Person() {
    }

    public Person(T info) {
        this.info = info;
    }
}

靜態方法中不能使用類的泛型
異常類不能是泛型的

//泛型不同的引用不能相互賦值
ArrayList<String> list1 = null;
ArrayList<Integer> list2 = new ArrayList<Integer>();

//報錯
list1 = list2;

  • 泛型方法
    泛型方法:在方法中出現了泛型的結構,泛型參數與類的泛型參數沒有任何關係
    換句話說,泛型方法所屬的類是不是泛型類都沒有關係
    泛型方法,可以聲明爲靜態的。原因:泛型參數是在調用方法時確定的。並非在實例化類時確定
public static <E> List<E> copyFromArrayToList(E[] arr) {

    ArrayList<E> list = new ArrayList<>();

    for (E e : arr) {
        list.add(e);
    }
    return list;
}

泛型在繼承上的體現

父類有泛型,子類可以選擇保留泛型也可以選擇指定泛型類型:

  • 子類不保留父類的泛型:按需實現
    ①沒有類型 擦除
    ②具體類型
  • 子類保留父類的泛型:泛型子類
    ①全部保留
    ②部分保留

子類除了指定或保留父類的泛型,還可以增加自己的泛型

class Father<T1, T2> {
}
// 子類不保留父類的泛型
// 1)沒有類型 擦除
class Son1 extends Father {// 等價於class Son extends Father<Object,Object>{
}
// 2)具體類型
class Son2 extends Father<Integer, String> {
}
// 子類保留父類的泛型
// 1)全部保留
class Son3<T1, T2> extends Father<T1, T2> {
}
// 2)部分保留
class Son4<T2> extends Father<Integer, T2> {
}

如果B是A的一個子類型(子類或者子接口),而G是具有泛型聲明的類或接口,G<B>並不是G<A>的子類型
比如:String是Object的子類,但是List<String >並不是List<Object>的子類

public void testGenericAndSubClass() {
    Person[] persons = null;
    Man[] mans = null;
	// 而 Person[] 是 Man[] 的父類.
    persons = mans;
    Person p = mans[0];
	// 在泛型的集合上
    List<Person> personList = null;
    List<Man> manList = null;
	// personList = manList;(報錯) 
}

通配符的使用

通配符:?

類A是類B的父類,G<A>和G<B>是沒有關係的,二者共同的父類是:G<?>

List<Object> list1 = null;
List<String> list2 = null;

List<?> list = null;

//編譯通過
list = list1;
list = list2;

List<String> list3 = new ArrayList<>();
list3.add("AA");
list3.add("BB");
list3.add("CC");
list = list3;
//添加(寫入):對於List<?>就不能向其內部添加數據,除了添加null之外
//報錯
list.add("DD");

list.add(null);

//獲取(讀取):允許讀取數據,讀取的數據類型爲Object。
Object o = list.get(0);
System.out.println(o);
}
  • 有限制條件的通配符的使用

? extends A:
G<? extends A> 可以作爲G<A>和G<B>的父類,其中B是A的子類

? super A:
G<? super A> 可以作爲G<A>和G<B>的父類,其中B是A的父類

//Student是Person的子類
List<? extends Person> list1 = null;
List<? super Person> list2 = null;

List<Student> list3 = new ArrayList<Student>();
List<Person> list4 = new ArrayList<Person>();
List<Object> list5 = new ArrayList<Object>();

list1 = list3;
list1 = list4;
//報錯
//list1 = list5;

//報錯
//list2 = list3;
list2 = list4;
list2 = list5;

//讀取數據:
list1 = list3;
Person p = list1.get(0);
//編譯不通過
//Student s = list1.get(0);

list2 = list4;
Object obj = list2.get(0);
////編譯不通過
//Person obj = list2.get(0);

//寫入數據:
//編譯不通過
//list1.add(new Student());

//編譯通過
list2.add(new Person());
list2.add(new Student());

IO流

File類

File類的使用

  1. File類的一個對象,代表一個文件或一個文件目錄(俗稱:文件夾)
  2. File類聲明在java.io包下
  3. File類中涉及到關於文件或文件目錄的創建、刪除、重命名、修改時間、文件大小等方法,並未涉及到寫入或讀取文件內容的操作。如果需要讀取或寫入文件內容,必須使用IO流來完成
  4. 後續File類的對象常會作爲參數傳遞到流的構造器中,指明讀取或寫入的"終點"

創建File類的實例

相對路徑:相較於某個路徑下,指明的路徑。
絕對路徑:包含盤符在內的文件或文件目錄的路徑
路徑分隔符:① windows:\\ ② unix:/

//File類的三種構造器
//File(String filePath)
//File(String parentPath,String childPath)
//File(File parentFile,String childPath)
        
//構造器1
File file1 = new File("hello.txt");//相對於當前module
File file2 = new File("D:\\workspace_idea\\test\\he.txt");

System.out.println(file1);
System.out.println(file2);

//構造器2:
File file3 = new File("D:\\workspace_idea", "Java");
System.out.println(file3);

//構造器3:
File file4 = new File(file3, "hi.txt");
System.out.println(file4);

常用方法

public String getAbsolutePath():獲取絕對路徑
public String getPath():獲取路徑
public String getName():獲取名稱
public String getParent():獲取上層文件目錄路徑。若無,返回null
public long length():獲取文件長度(即:字節數)。不能獲取目錄的長度。
public long lastModified():獲取最後一次的修改時間,毫秒值

File file1 = new File("hello.txt");

System.out.println(file1.getAbsolutePath());
System.out.println(file1.getPath());
System.out.println(file1.getName());
System.out.println(file1.getParent());
System.out.println(file1.length());
System.out.println(new Date(file1.lastModified()));

如下的兩個方法適用於文件目錄:
public String[] list() :獲取指定目錄下的所有文件或者文件目錄的名稱數組
public File[] listFiles() :獲取指定目錄下的所有文件或者文件目錄的File數組

File file = new File("D:\\workspace_idea\\Java");

String[] list = file.list();
for (String s : list) {
    System.out.println(s);
}

System.out.println();

File[] files = file.listFiles();
for (File f : files) {
    System.out.println(f);
}

public boolean renameTo(File dest):把文件重命名爲指定的文件路徑
比如:file1.renameTo(file2)爲例:
要想保證返回true,需要file1在硬盤中是存在的,且file2不能在硬盤中存在

File file1 = new File("hello.txt");
File file2 = new File("D:\\i\\hi.txt");

boolean renameTo = file2.renameTo(file1);

public boolean isDirectory():判斷是否是文件目錄
public boolean isFile():判斷是否是文件
public boolean exists():判斷是否存在
public boolean canRead():判斷是否可讀
public boolean canWrite():判斷是否可寫
public boolean isHidden():判斷是否隱藏

File file1 = new File("hello.txt");
file1 = new File("hello1.txt");

System.out.println(file1.isDirectory());
System.out.println(file1.isFile());
System.out.println(file1.exists());
System.out.println(file1.canRead());
System.out.println(file1.canWrite());
System.out.println(file1.isHidden());

創建硬盤中對應的文件或文件目錄
public boolean createNewFile() :創建文件。若文件存在,則不創建,返回false
public boolean mkdir() :創建文件目錄。如果此文件目錄存在,就不創建了。如果此文件目錄的上層目錄不存在,也不創建。
public boolean mkdirs() :創建文件目錄。如果此文件目錄存在,就不創建了。如果上層文件目錄不存在,一併創建

刪除磁盤中的文件或文件目錄
public boolean delete():刪除文件或者文件夾
刪除注意事項:Java中的刪除不走回收站

//文件目錄的創建
File file1 = new File("d:\\i\\i1\\i3");

boolean mkdir = file1.mkdir();
if (mkdir) {
    System.out.println("創建成功1");
}

File file2 = new File("d:\\i\\i1\\i4");

boolean mkdir1 = file2.mkdirs();
if (mkdir1) {
    System.out.println("創建成功2");
}
//要想刪除成功,io4文件目錄下不能有子目錄或文件
File file3 = new File("D:\\i\\i1\\i4");
file3 = new File("D:\\i\\i1");
System.out.println(file3.delete());
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章