常用的API

String類

所屬包:java.lang.String

  • 字符串是一個特殊的對象
  • 所屬包:java.lang.System
  • String str = "abc";String str1 = new String("abc");有什么區(qū)別
package zimo.demo;
public class StringDemo{
    public static void main(String[] args){
        /*
         *  String類的特點:
         *  字符串對象一旦被初始化就不會被改變
         *
         *  字符串緩沖區(qū)中沒有就建立,字符串緩沖區(qū)中有就直接用,可以共享
         */

        String s = "abc";                    // 創(chuàng)建一個字符串對象,在常量池中創(chuàng)建了"abc"并賦值給s
        String s1 = "abc";                   // 和s是同一個對象
        s = "nba";                          // “abc”和“nba”是不同對象
        
        String s2 = new String("abc");        // 在堆內(nèi)存中創(chuàng)建,創(chuàng)建了兩個對象,一個new 一個字符串對象在堆內(nèi)存中 

        System.out.println(s == s1);        // true
        System.out.println(s == s2);        // false
        System.out.pritnln(s.equals(s1));   // true String中equals進(jìn)行復(fù)寫
    }
}

String構(gòu)造器

package zimo.demo1;
public class StringConstructorDemo{
    public static void main(String[] args){
        stringConstructorDemo();
        stringConstructorDemo1();
    }
    
    public static void stringConstructorDemo(){
        String s = new String(); // 等價String s = "";   不等價 String s = null;
        byte[] arr = {65,98,67,68};
        String s1 = new String(arr);
        System.out.println(s1);     // AbCD
    }
    public static void stringConstructorDemo1(){
        char[] arr = {'z','i','m','o'};
        String s1 = new String(arr);
        String s2 = new String(arr,1,3);
        System.out.println(s1);     // zimo
        System.out.println(s2);     // imo
    }
}

功能分類

  1. 獲?。?
    • int length()獲取字符串中字符的個數(shù)(長度) 數(shù)組長度是屬性,字符串是方法
    • char charAt(int index)根據(jù)位置獲取字符
    • int indexOf(int ch)根據(jù)字符獲取在字符串中d的第一次出現(xiàn)的位置
    • int indexOf(int ch, int fromIndex)從指定位置進(jìn)行ch的查找第一次出現(xiàn)的位置
    • int indexOf(String ch) int indexOf(String ch, int fromIndex)查找字符串的第一次出現(xiàn)的位置
    • int lastindexOf(int ch)..........同理從后往前查找
    • String substring(int beginIndex) String substring(int beginIndex, int endIndex)獲取一部分字符串,也叫子串
  2. 轉(zhuǎn)換:
    • String[] split(String regex)將字符串的切割,通過(正則表達(dá)式)規(guī)則切割(字符串 — > 字符數(shù)組)
    • char[] toCharArray()將字符串變成字符數(shù)組
    • byte[] getBytes()將字符串變成字節(jié)數(shù)組
    • String toUpperCase() String toLowerCase將字符串中的字母轉(zhuǎn)成大小寫
    • String replace(char oldCh, char newCh)將字符串中的內(nèi)容進(jìn)行替換
    • String trim()將字符串頭尾的空格去掉
    • String concat(string str)將字符串進(jìn)行連接
  3. 判斷:
    • boolean equals(Object obj)兩個字符串內(nèi)容是否相同
    • boolean equalsIgnoreCase(String str)忽略大小寫,比較字符串內(nèi)容
    • boolean contains(String str)比較字符串中是否包含
    • boolean startsWith(string str) boolean endsWith(String str)字符串是否以指定字符串開頭/結(jié)尾
  4. 比較:
    • int compareTo(String str)比較字符串大小(ascii碼表順序/字典順序)

intern()方法:判斷字符串池中是否存在,如果存在返回引用,如果不存在,在字符串池中建立一個新的對象

StringBuffer類

所屬包:java.lang.StringBuffer

字符串緩沖區(qū),用于存儲數(shù)據(jù)的容器,最終轉(zhuǎn)成字符串輸出

  • 字符串的組成原理就是通過該類實現(xiàn)的
  • StringBuffer可以對字符串內(nèi)容進(jìn)行增刪
  • StringBuffer是一個容器
  • 很多方法與String相同
  • StringBuffer是可變長度的
  1. 添加操作StringBuffer append(T t)

  2. 插入操作StringBuffer insert(int offset, T t)

  3. 刪除操作StringBuffer delete(int start, int end)包含頭不包含尾

  4. 查找操作StringBuffer charAt(int index)

    查找操作StringBuffer indexOf(String str)

    查找操作StringBuffer lastIndexOf(String str)

  5. 修改操作StringBuffer replace(int start, int end, String str)

    修改操作void charAt(int index, char ch)

  6. 設(shè)置長度void setLength(int newLength)

  7. 反轉(zhuǎn)操作StringBuffer reverse()

StringBuilder類

所屬包:java.lang.StringBuilder

兼容于StringBuffer 1.5后才出來的,用于單線程使用的等價類,由于它的執(zhí)行不同步,所以速度更快(驗證鎖)

不同點:

  • StringBuffer是線程同步的。通常用于多線程
  • StringBuilder是線程不同步的。通常用于單線程,提高效率

JDK的升級:

  • 簡化書寫
  • 提高效率
  • 增加安全

基本數(shù)據(jù)類型對象包裝類

  • 將基本數(shù)據(jù)類型封裝成對象的好處在于可以在對象中定義更多的功能方法操作該數(shù)據(jù)
  • 常用操作之一:用于基本數(shù)據(jù)類型與字符串之間的轉(zhuǎn)換

byte : Byte short : Short int : Integer long : Long

float : Float double : Double char : Character boolean : Boolean

class IntegerDemo{
    public static void main(String[] args){
        // String轉(zhuǎn)int
        Integer x = new Integer("123")x;
        Integer xx = new Integer(123);      // x != xx    x.equals(b): true
        int x1 = x.intValue();
        int x2 = Integer.parseInt("123");
        
        // 十進(jìn)制轉(zhuǎn)其他進(jìn)制
        Integer.toBinaryString(60);
        Integer.toOctalString(60);
        Integer.toHexString(60);
        Integer.toString(60,3);     // 三進(jìn)制
        // 其他進(jìn)制轉(zhuǎn)十進(jìn)制
        Integer.parseInt("3c",16);  // 十六轉(zhuǎn)十 
    }
}

1.5版本后進(jìn)行新特性的升級

class IntegerDemo{
    public static void main(String[] args){
        // 新特性:自動裝箱  簡化書寫
        Integer x = 4;
        x = x + 5;      // x = new Integer(x.intValue() + 6);  x.intValue()自動拆箱
        
        // 注意:當(dāng)自動拆箱時遇到對象null時,會拋出異常
        x = null;
        x = x + 10;     // err:NullPointException
        
        //jdk 1.5后,自動裝箱,如果裝箱是一個字節(jié),那么數(shù)據(jù)會被共享,不會開辟新空間
        Integer a = 127;
        Integer b = 127; 
        Integer a1 = 128;
        Integer b1 = 128; 
        boolean flag = (a == b);        // true
        flag = (a1 == b1);              // false
    }
}

集合類

所屬包:java.util

集合只用于存儲對象,集合長度是可變的,集合可以存儲不同類型,不能存儲基本數(shù)據(jù)類型(數(shù)組是存儲變量,長度固定,存儲類型相同,存儲基本數(shù)據(jù)類型)

集合因為內(nèi)部的數(shù)據(jù)結(jié)構(gòu)不同,有多種具體容器。不斷向上抽取形成了集合框架

集合框架.png

框架的頂層Collection接口

Collection常見方法:

  • 添加:boolean add(Object obj) boolean addAll(Collection<?> c)添加元素

  • 刪除:boolean remove(Object obj) boolean remove(Collection<?> c) 刪除元素

  • 清空:boolean clear()清空集合

  • 查找:boolean contains(Object obj) boolean containsAll(Collection<?> c)是否包含內(nèi)容

  • 判空:boolean isEmpty()判斷是否為空

  • 長度:int size()獲取長度

  • 迭代:Iterator iterator()獲取內(nèi)容 Iterator接口就是對所有Collection容器進(jìn)行元素取出的公共接口

  • 其他:boolean retainAll(Collection c)取交集

    其他:Object[] toArray()將集合裝成數(shù)組

集合框架的構(gòu)成及分析

集合框架構(gòu)成及分類.png
  • Collection

-- List:有序(存入和取出的順序一致),元素都有索引(角標(biāo)),元素可以重復(fù)。

--Set:元素不能重復(fù),無序。

List接口特有常見方法

\color{blue}{有一個共性特點就是都可以操作角標(biāo)},list集合的元素,數(shù)據(jù)可以重復(fù)

  • 添加元素:

    void add(int index, E element)

    void add(int index, Collection c)

  • 刪除元素:

    E remove(int index)

  • 修改元素:

    E set(int index, E element)

  • 獲取元素:

    E get(int index)

    int indexOf(E element)

    int lastIndexOf(E element)

    List subList(int fromIndex, int toIndex)

class ListDemo{
    public static void main(String[] args){
        List list = new ArrayList();
        show(list);
    }
    
    public static void show(List list){
        // 添加元素
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        
        // 插入元素
        list.add(1, "add9");            // abc1 abc9 abc2 abc3
        
        // 刪除元素
        System.out.println("remove:" + list.remove(2));     // abc1 abc9 abc3
        
        // 修改元素
        System.out.println("set:" + list.set(1,"abc8"));    // abc1 abc8 abc3
        
        // 獲取元素
        System.out.println("get:" + list.get(1,"abc8"));    // abc8
        System.out.println("subList:" + list.subList(1,2)); // abc8
    }
}

list集合是可以完成列表的增刪改查

// 迭代器使用
{
    List list = new ArrayList();
    // 添加元素
    list.add("abc1");
    list.add("abc2");
    list.add("abc3");
    
    // 添加元素:err 并發(fā)操作異常
    {
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();     // java.util.ConcurrentModificationException
                                      // 在迭代過程中,不要使用集合對象操作元素,容易出現(xiàn)異常,可以使用Iterator子類接口實現(xiàn)
            if(obj.equals("abc2")){
                list.add("abc9");
            }
        }
    }
    --------------------------------------------------------------------------------------------------------
    // 通過子類迭代器接口:只有l(wèi)ist集合具備該迭代功能
    {
        ListIterator it = list.ListIterator();  // 獲取列表迭代器對象
        while(it.hasNext()){
            Object obj = it.next(); 
            if(obj.equals("abc2")){
                it.add("abc9");
            }
        }
        
        while(it.hasPrevious()){
            System.out.println(it.previous());
        }
    }
    
}
  • List:

    可變數(shù)組原理:創(chuàng)建一個新數(shù)組,將原來的拷貝到新數(shù)組中

    -- Vector:內(nèi)部是數(shù)組數(shù)據(jù)結(jié)構(gòu),它是同步的,可增長的對象數(shù)組,可以通過整數(shù)索引訪問

                增刪,查詢都很慢(1.0出現(xiàn),1.2收編到集合框架)(自動擴(kuò)容:100%的增長)
    

    -- ArrayList:內(nèi)部是數(shù)組數(shù)據(jù)結(jié)構(gòu),它是不同步的,大小可變數(shù)組,替代了Vector,

                查詢速度快(如果是多線程,要么加鎖,要么其他方式實現(xiàn),vector摒棄了)(自動擴(kuò)容:50%增長)
    

    -- LinkedList:內(nèi)部是鏈表結(jié)構(gòu),不同步的

                增刪元素效率快
    

一般list集合除了vector是同步的,其他的都是不同步的,出于效率考慮

  • LinkedList:

    添加元素:

    • addFirst() addLast()
    • offerFirst() offerLast()(1.6)

    獲取但不移除:

    • getFirst() getLast():鏈表為空,拋出異常NoSuchElementException,鏈表為空
    • peekFirst() peekLast():鏈表為空返回null,不拋出異常(1.6)

    獲取并移除:

    • removeFirst() removeLast():鏈表為空,拋出異常NoSuchElementException,鏈表為空
    • poolFirst() poolLast():鏈表為空返回null,不拋出異常(1.6)
/**
 *  請使用LinkedList來模擬一個堆?;蛘哧犃袛?shù)據(jù)結(jié)構(gòu)
 *  堆棧:先進(jìn)后出     FILO    First In Last Out
 *  隊列:先進(jìn)先出     FIFO    First In First Out
 */
// 描述容器:提供對象完成兩種結(jié)構(gòu)

// 隊列
class MyQueue{
    private LinkedList link;
    public MyQueue(){
        link = new LinkedList();
    }
    /**
    *   隊列添加元素功能
    */
    public void myAdd(Object obj){
        link.addLast(obj);
    }
    
    /**
    *   隊列獲取一個元素
    */
    public Object myGet(Object obj){
        return link.removeFirst();
    }
    
    /**
    *   隊列獲取一個元素
    */
    public Object myIsEmpty(Object obj){
        return link.isEmpty();
    }
}

// 堆棧
class MyStackHeap{
    private LinkedList link;
    public MyStackHeap(){
        link = new LinkedList();
    }
    /**
    *   堆棧添加元素功能
    */
    public void myAdd(Object obj){
        link.addLast(obj);
    }
    
    /**
    *   堆棧獲取一個元素
    */
    public Object myGet(Object obj){
        return link.removeLast();
    }
     
    /**
    *   堆棧獲取一個元素
    */
    public Object myIsEmpty(Object obj){
        return link.isEmpty();
    }
}

public class LinkedTest{
    public static void main(String[] args){
        
    }
}

Set接口集合

接口:public interface Set<E> extends Collection<E>

元素不可以重復(fù),是無序的,與Collection方法一致

  • HashSet(哈希表):內(nèi)部數(shù)據(jù)結(jié)構(gòu)是哈希表,是不同步的
    • LinkedHashSet:哈希表和鏈表實現(xiàn),有迭代順序的集合,怎么存進(jìn)去怎么取出來
  • TreeSet:可以對Set集合中的元素進(jìn)行排序
  • HashSet:集合數(shù)據(jù)結(jié)構(gòu)是哈希表,所以存儲元素的時候,使用的元素的hashCode來確定位置,如果位置相同,再通過元素的equals來確定是否相同
    • 判斷標(biāo)準(zhǔn)對象是否相同:hashCode()、equals()
    • 讓元素自身具備比較功能,就需要覆蓋Object類,重寫hashCode、equals方法
public class SetDemo{
    public static void main(String[] args){
        hashSetDemo();
    }
    public void hashSetDemo(){
        HashSet hs = new HashSet();
        hs.add("hhh");
        hs.add("aaa");
        hs.add("xxx");
        hs.add("xxx");          // 沒進(jìn)去,數(shù)據(jù)唯一
        Iterator it = it.iterator();
        while(it.hasNext()){
            System.out.println(it.next());  // 無法保證數(shù)據(jù)順序
        }
    }
}

哈希表確定元素是否相同:

  1. 判斷的是兩個元素的哈希值是否相同,如果相同,再判斷兩個對象的內(nèi)容是否相同
  2. 判斷哈希值相同,其實判斷的是對象的hashCode的方法。判斷內(nèi)容相同,用的是equals方法
  3. 注意:如果哈希值不同,是不需要判斷equals

哈希沖突:

  1. 順延:順著往下存儲
  2. 串聯(lián):在同一個位置往外掛一塊地址
class Person{
    String name;
    int age;
    
    @Override
    public boolean equals(Object obj){
        if(this == obj)         // 同一個對象
            return true;
        if(!(obj instanceof Person))        // 健壯性判斷
            throws new ClassCaseException("類型錯誤!");
        return this.name == obj.name && this.age == obj.age;
    }
    
    @Override
    public int hashCode(){
        return name.hashCode() + age * 37;
    }
}
  • TreeSet:保證元素的唯一性

    • 1.判斷標(biāo)準(zhǔn)對象是否相同:compareTo() 0:相同 > 0、< 0:不同

      讓元素自身具備比較功能,就需要實現(xiàn)Comparable接口,覆蓋compareTo方法

    • 2.判斷標(biāo)準(zhǔn)對象是否相同:實現(xiàn)比較器new Comparetor()

      讓集合具備比較功能,定義類實現(xiàn)Comparator接口,覆蓋compare方法,實現(xiàn)了該方法以該方法為主

  • 元素自身具備比較功能

/**
 *  以Person對象的年齡進(jìn)行排序
 */
class Person implements Comparable{
    String name;
    int age;
    
    @Override
    public int compareTo(Object obj){
        Person p = (Person)obj;
        if(!(p instanceof Person)){
            throws new ClassCaseException("類型錯誤!");
        }
        /*
        if(this.age < p.age){
            return 1;
        }else if(this.age > p.age){
            return -1;
        }else{
            return this.name.compareTo(p.name);
        }
        */
        // 按年齡排
        int tmp = this.age - p.age;
        return tmp == 0 ? this.name.compareTo(p.name) : tmp;
        // 按姓名拍
        int tmp = this.name.compareTo(p.name);
        return tmp == 0 ? this.age - p.age : tmp;
    }
}
  • 如果不要按照對象中具備的自然順序進(jìn)行排序,如果對象中不具備自然順序怎么辦?

    - 使用TreeSet集合第二種排序方式:\color{blue}{讓集合自身具備比較功能}

package zimo.demo;
import java.util.Comparator;
import zimo.xx.Person;

/** 
 *  創(chuàng)建一個根據(jù)Person類的name進(jìn)行排序的比較器
 */
public class ComparatorByName implements Comparator {
    @Override
    public int compare(Object o1, Object o2){
        Person p1 = (Person)o1;
        Person p2 = (Person)o2;
        
        int tmp = p1.getName().compareTo(p2.getName());
        return tmp == 0 ? p1.getAge : tmp;
    }
}

public class TreeSetComparatorDemo{
    public static void main(String[] args){
        TreeSet ts = new TreeSet(new ComparatorByName());
        ts.add(new Person("zimo", 20));
        ts.add(new Person("llx", 13));
        ts.add(new Person("zhangsan", 31));
    }
}
  • 后綴名就是該集合所屬的體系
  • 前綴名就是該集合的數(shù)據(jù)結(jié)構(gòu)
  • array:數(shù)組數(shù)據(jù)結(jié)構(gòu),查詢快,有角標(biāo)
  • link:鏈表數(shù)據(jù)結(jié)構(gòu),增刪快,有add、get、remove + (first、last)方法
  • hash:哈希表結(jié)構(gòu),唯一性,元素需要覆蓋hashCode和equals方法
  • tree:二叉樹結(jié)構(gòu),想實現(xiàn)排序,就想到兩個接口,Comparable(對象實現(xiàn)接口),Comparator(比較器)
  • \color{blue}{通常這些集合容器都是不同步的}

Map接口集合

一次添加一對元素。Collection集合一次添加一個元素,Map也稱雙列集合,Collection集合稱為單列集合

接口:public interface Map<K,V>,Map集合存儲的是鍵值對,Map集合中必須保證鍵的唯一性

常用方法:

  1. 添加:

    V put(K key, V value),返回前一個和key關(guān)聯(lián)的值,沒有返回null

  2. 刪除:

    void clean(),清空map集合

    V remove(K key),根據(jù)指定的key刪除這個鍵值對,返回刪除的value

  3. 判斷:

    boolean containsKey(Object key),判斷集合鍵(key)是否存在

    boolean containsValue(Object value),判斷集合值(value)是否存在

    boolean isEmpty(),判斷集合是否為空

  4. 獲?。?/p>

    value get(key),集合通過鍵(key)取值(value),如果沒有該鍵返回null,通過判斷null來確定是否存在該鍵

    int size(),返回集合鍵值對個數(shù)

package zimo.map.demo;
import java.util.Map;
public class MapDemo{
    public static void main(String[] args){
        Map<Integer, String> map = new HashMap<Integer, String>();
        method(map)
    }
    public static void method(Map<Integer, String> map){
        // 添加元素  存相同鍵,值會被覆蓋,返回舊值
        System.out.println(map.put(1, "zimo"));     // null
        System.out.println(map.put(1, "haha"));     // zimo
        System.out.println(map.put(2, "xixi"));     // zimo
        
        // 刪除
        System.out.println(map.remove(1));          // zimo
        
        // 判斷
        System.out.println(map.containsKey(2));     // true
        
        // 獲取
        System.out.println(map.get(2));            // xixi 
        
        // 取出map中所有元素:通過keyset方法獲取map中所有的鍵所在的set集合,
        //                 再通過set迭代器獲取到每一個鍵,在對每一個鍵取其對應(yīng)值
        // 方法一:
        Set<Integer> keySet = map.keySet();
        Iterator<Integer> it = keySet.iterator();
        while(it.hasNext()){
            Integer key = it.next();
            String value = map.get(key);
            System.out.println(key);
        }
        
        // 取出map中所有元素:通過Map轉(zhuǎn)成Set就可以迭代,通過entrySet將鍵和值的關(guān)系作為對象存儲到了set集合中,
        //                 而這個映射關(guān)系的類型就是Map.Entry類型
        // 方法二:
        Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
        Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
        while(it.hasNext()){
            Map.Entry<Integer, String> en = it.next();
            System.out.println(en.getKey() + ":" + en.getValue());
        }
        
        Collection<String> values = map.values();
        Iterator<String> it1 = values.iterator();
        while(it1.hasNext()){
            System.out.println(it1.next());
        }
    }
}
Map容器取值方法一解析.png
  • Map常用的子類:

    -- Hashtable:內(nèi)部結(jié)構(gòu)是哈希表,是同步的,不允許null鍵和null值(1.0存在)

    -- Properties:用來存儲鍵值對型配置文件的信息,可以和IO技術(shù)相結(jié)合

    -- HashMap:內(nèi)部結(jié)構(gòu)是哈希表,不是同步的(允許使用null鍵和值)

    -- TreeMap:內(nèi)部結(jié)構(gòu)是二叉樹,不是同步的,可以對Map集合中的鍵進(jìn)行排序

// HashMap存儲自定義類型
package zimo.hashmap.demo;
public class HashMapDemo{
    public static void main(String[] args){
        // 將學(xué)啥對象和學(xué)生的歸屬地通過鍵值存儲到map集合中
        HashMap<Student, String> hm = new HashMap<Student, String>();
        hm.put(new Student("lisi", 38), "北京");
        hm.put(new Student("zimo", 18), "廈門");
        hm.put(new Student("waci", 25), "廣東");

        Set<Map.Entry<Student, String>> entrySet = hm.entrySet();
        Iterator<Map.Entry<Student, String>> it = entrySet.iterator();
        while(it.hasNext()){
            Map.Entry<Integer, String> en = it.next();
            System.out.println(en.getKey().getName + ":" + en.getKey().getAge() + "..." + en.getValue());
        }
    }
}

public class Student extends Person{
    public Student(){
        super();
    }
    public Student(String name, int age){
        super(name,age);
    }
}

public class Person implements Comparable<Person>{
    String name;
    int age;
    
    Person(){super();}
    Person(String name, int age){
        super();
        this.name = name;
        this.age = age;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
    public void setName(String name){
        this.name = name;
    }
    public int getAge(int age){
        this.age = age;
    }
    public int compareTo(Person p){
        int tmp = this.age - p.age;
        return tmp == 0 ? this.name.compateTo(p.name) : tmp;
    }
    @Override 
    public boolean equals(Object obj){
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass)
            return false;
        Person other = (Person)obj;
        if(age != other.age)
            return false;
        if(name == null){
            if(other.name != null)
                return false;
        }else if(!name.equals(other.name))
            return false;
        return true;
    }
    @Override 
    public int hashCode(){
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
    }
}

泛型

JDK1.5以后出現(xiàn)的安全機(jī)制

  • 好處:
    1. 將運(yùn)行時期的問題ClassCastException轉(zhuǎn)到了編譯時期
    2. 避免了強(qiáng)制轉(zhuǎn)換的麻煩
  • <>:啥時候用?
    • 當(dāng)操作的引用數(shù)據(jù)類型不確定的時候,就使用<>。將要操作的引用數(shù)據(jù)類型傳入
    • <>就是一個用于接受具體引用數(shù)據(jù)類型的參數(shù)范圍
package zimo.generic.demo;
import java.util.ArrayList;
public class GenericDemo{
    public static void main(String[] args){
        ArrayList a1 = new ArrayList();
        ArrayList<String> a2 = new ArrayList<String>();
        a1.add("hhh");
        a1.add("xxx");
        a1.add(45);     // 編譯成功
        a2.add("222");
        a2.add(45);     // err:編譯失敗
        
        Iterator it = a1.iterator();
        Iterator<String> it2 = a2.iterator();
        while(it.next()){
            System.out.println((String)it.next);    // err 45無法強(qiáng)轉(zhuǎn)成String
            System.out.println(it.next);
        }
    }
}
  • 泛型技術(shù)是給編譯器使用的技術(shù),用于編譯時期,確保了類型的安全。
  • 運(yùn)行時會將泛型去掉,生成的class文件是不帶泛型的,這個稱為泛型的擦除

為什么擦除?

  • 為了兼容運(yùn)行的類加載器

泛型的補(bǔ)償

  • 在運(yùn)行時,通過獲取元素的類型進(jìn)行轉(zhuǎn)換動作。不用開發(fā)人員進(jìn)行強(qiáng)制類型轉(zhuǎn)換了
  • Class clazz = "aa".getClass(); clazz.getName();

自定義泛型類

定義泛型要在修飾符后,返回值前聲明定義

package zimo.generic.define.demo;
// 1.5后使用泛型來接收類中要操作的引用數(shù)據(jù)類型
public class Tool<T>{
    private T t;
    public T getT(){
        return t;
    }
    public void setT(T t){
        this.t = t;
    }
    // 將泛型定義在方法上
    public <W> void show(W str){
        System.out.println("show:" + str.toString());
    }
    // 無法打印
    public void show1(T str){
        System.out.println("show:" + str.toString());
    }
    // 靜態(tài)不需要對象,靜態(tài)方法不能訪問類上定義的泛型。如果靜態(tài)方法使用泛型,只能定義在方法上
    //public static void show1(T str){
    public static <Z> void show2(Z str){
        System.out.println("show2:" + str.toString());
    }
    
    public static void main(String[] args){
        Tool<Student> tool = new Tool<Student>();
        tool.setT(new Student());
        tool.setT(new Worker());            // err
        
        tool.show(new Integer(5));          // ok
        tool.show1(new Integer(2));         // err
        Tool.show2("hhh");                 // ok
        Tool.show2(new Integer(8));         // ok
    }
}


泛型接口

  • 泛型的通配符:
    • " ? "未知類型
  • 可以對類型進(jìn)行限定:
    • <? extends E>:接收E類型或者E的子類型對象,上限?。ù鎯r用的多)
    • <? super E>:接收E類型或者E的父類型對象,下限?。ㄈ〕霾僮鲿r用的多)
package zimo.define.demo;
public class GenericDefineDemo{
    public static void main(String[] args){
        ArrayList<String>a1 = new ArrayList<String>();
        ArrayList<Integer>a2 = new ArrayList<Integer>();
        a1.add("abc");
        a2.add(45);
        printCollection(a1);
        printCollection(a2);
    }
}
// 泛型接口,將泛型定義在接口上
interface Inter<T>{
    public void show(T t);
}

class InterImpl implements Inter<String>{
    public void show(String str){
        System.out.println("str : " + str);
    }
}

class InterImpl1<Q> implements Inter<Q>{
    public void show(Q q){
        System.out.println("show : " + q);
    }
}

// 迭代打印集合中元素,僅限于不明確類型,并不對類型進(jìn)行操作的時候
// <?> === <? extends Object>
public static void printCollection(Collection<?> all){
    Iterator<?> it = a1.iterator();
    while (it.hasNext()){
        //? aa = it.next();
        //System.out.println(aa);
        System.out.println(it.next());
    }
}

// 迭代打印集合中元素
public static <T> void printCollection1(Collection<T> all){
    Iterator<T> it = a1.iterator();
    while (it.hasNext()){
        T aa = it.next();       
        System.out.println(aa);
        //System.out.println(it.next());
    }
}

public static <T> T printCollection2(Collection<T> all){
    Iterator<T> it = a1.iterator();
    return it.next();       // T能代表一個指定類型,并能去操作
}

// 限制只接收Person的子類集合Sutdent、Worker
public static void printCollection3(Collection<? extends Person> p){
    Iterator<? extends Person> it = p.iterator();
    while (it.hasNext()){
        Person pp = it.next();      
        System.out.println(pp);
        //System.out.println(it.next());
    }
}
// 限制只接收Student的父類集合Sutdent、Person
public static void printCollection3(Collection<? super Sutdent> p){
    Iterator<? super Sutdent> it = p.iterator();
    while (it.hasNext()){
        System.out.println(it.next());
    }
}

集合使用技巧

  • 是否需要唯一性:
    1. 需要:set集合
      • 是否指定順序:
        1. 指定順序:TreeSet
        2. 不需要:HashSet
        3. 和存儲時一致的順序(有序):LinkedHashSet
    2. 不需要:List集合
      • 是否頻繁增刪:
        1. 需要:LinkedList
        2. 不需要:ArrayList

每個容器的結(jié)構(gòu)和所屬體系:\color{red}{看名字前綴數(shù)據(jù)結(jié)構(gòu),后綴名是容器框架}

容器工具類(Utilities)

Collections(操作集合)

集合框架的工具類,里面的方法是靜態(tài)的

Collections.sort(list);          // 對list集合進(jìn)行重復(fù)元素的排序
Collections.swap(list, i, j);    // 交換list中的i和j值
Collections.swap(list, ComparatorByLength);   // 通過長度排序
Collections.binarySearch(list, "aa");        // 二分查找,有序的list查找“aa”
Collections.max(list);          // 找出list中最大值
Collections.reverseOrder();     // 將自然排序的元素逆轉(zhuǎn)
Collections.reverseOrder(new ComparatorByLength());      // 按長度逆轉(zhuǎn)
Collections.replaceAll(list, "aa", "bb");               //索引list中的aa替換成bb
Collections.fill(list, "aa");   // 將list中所有的元素替換成aa
Collections.shuffle(list);      // 隨機(jī)打亂list
Collections.synchronizedList(list);     // 返回一個線程安全的list,同步list
Collections.synchronizedMap(Map);       // 返回一個線程安全的Map,同步Map
Collections.synchronizedSet(Set);       // 返回一個線程安全的Set,同步Set
Collections.synchronizedCollection(Collection);     // 返回一個線程安全的Collection,同步Collection
......

當(dāng)多線程遇上ArrayList,給非同步集合加鎖

// 加鎖原理
List list = new ArrayList();
//返回一個同步的list
list = MyCollections.synList(list);     

class MyCollections{
    
    public static List synList(List list){
        return new MyList(list);
    }
    
    private class MyList implements List{
        private List list;
        private static final Object lock = new Object();
        MyList(List list){
            this.list = list;
        }
        public boolean add(Object obj){
            synchronized(lock){
                return list.add(obj);
            }
        }
        public boolean remove(Object obj){
            synchronized(lock){
                return list.remove(obj);
            }
        }
    }    
}

Arrays

集合框架的工具類,里面的方法是靜態(tài)的

Arrays.binarySearch();      // 二分查找
Arrays.copyOf();            // 拷貝
Arrays.equals(a,b);         // 比較兩個對象是否相等(相同順序,相同值)
Arrays.fill();              // 指定替換
Arrays.sort();              // 排序
Arrays.toString();          // 轉(zhuǎn)換成字符串
Arrays.asList("aa","BB");    // 將數(shù)組轉(zhuǎn)成list集合

toString()的經(jīng)典實現(xiàn)

public static String myToString(int[] arr){
    int iMax = arr.length -1;
    if(iMax == -1)
        return "[]";
    StringBuilder str = new StringBuilder();
    str.append('[');
    for(int i = 0; ; i++){      // 中間省略條件判斷,提高了效率
        str.append(arr[i]);
        if(i == iMax)
            return str.append(']').toString();
        str.append(",")
    }
}

asList():將數(shù)組轉(zhuǎn)成集合

  • 可以使用集合的方法操作數(shù)組中的元素
  • \color{blue}{數(shù)組的長度是固定的,所以對于集合的增刪方法是不可以使用的,否則發(fā)生UnsupportedOperationException}
  • 如果數(shù)組中的元素是對象,那么轉(zhuǎn)成集合時,直接將數(shù)組中的元素作為集合中的元素進(jìn)行集合存儲
  • 如果數(shù)組中的元素是基本類型數(shù)值,那么會將該數(shù)組作為集合中的元素進(jìn)行存儲
String[] arr = {"abc", "hhh", "xxx"};   // String對象
List<String> list = Arrays.asList(arr);
list.contains("xxx");       // true
list.add("aaa");            // err:數(shù)組的長度是固定的 (add,remove)不能使用

int[] arr1 = {11,22,33,44};
List list = Arrays.asList(arr1);    // [[i@hashcode]
list.size();        // 1 將arr數(shù)組存進(jìn)去,數(shù)組對象arr1是引用類型,其中的值是數(shù)據(jù)類型無法直接存儲

// 數(shù)組轉(zhuǎn)集合
List<int[]> list = Arrays.asList(arr1); // {11,22,33,44}

toArray():集合轉(zhuǎn)成數(shù)組

  • Collection接口中的toArray方法
  • 集合轉(zhuǎn)數(shù)組:可以對集合中的元素操作方法進(jìn)行限定。不允許對其進(jìn)行增刪

toArray方法需要傳入一個指定類型的數(shù)組

  • 長度:
    1. 如果長度小于集合的size,那么該方法會創(chuàng)建一個同類型并和集合相同的size的數(shù)組
    2. 如果長度大于集合的size,那么該方法就會使用指定的數(shù)組,存儲集合中的元素,多余的位置默認(rèn)null
public class ToArray{
    public static void main(String[] args){
        List<String> list = new ArrayList<String>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        String[] arr = list.toArray(new String[list.size()]);
        System.out.println(Array.toString(arr));
    }
}

JDK1.5新特性

ForEach語句

  • 格式:for(類型 變量 : Collection集合|數(shù)組){}
public static void main(String[] args){
    List<String> list = new ArrayList<String>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    // 傳統(tǒng)遍歷方式
    Iterator<String> it = list.iterator();
    while(it.hasNext()){
        System.out.println(it.next());
    }
    // 1.5版本后 foreach 簡化縮寫
    // 遍歷集合
    for(String s : list){
        System.out.println(s);
    }
    // 遍歷數(shù)組
    int[] arr = {1,2,3,4,5,6};
    for(int i : arr){
        System.out.println(i);
    }
}

傳統(tǒng)for循環(huán)VS高級for(for-each)

  • 傳統(tǒng)for循環(huán)可以完成對語句執(zhí)行很多次,因為可以定義控制循環(huán)的增量和條件
  • 高級for是一種簡化形式,它必須有被遍歷的目標(biāo)。該目標(biāo)要么是數(shù)組,要么是Collection單例集合
  • 對于數(shù)組的遍歷如果僅僅是獲取數(shù)組中的元素,可以使用高級for,如果要對數(shù)組的角標(biāo)進(jìn)行操作,建議使用傳統(tǒng)for

可以使用高級for遍歷map集合嘛?

  • 不能直接使用,但是可以將map轉(zhuǎn)成單列set集合就可以使用了
public static void main(String[] args){
    Map<Integer, String> map = new HashMap<Integer, String>();
    map.put(1, "aaaaa");
    map.put(2, "bbbbb");
    map.put(3, "ccccc");
    map.put(4, "ddddd");
    for(Integer key : map.keySet()){
        String value = map.get(key);
        System.out.println(key + ":" + value);
    }
    
    for(Map.Entry<Integer, String> entry : map.entrySet()){
        Integer key = entry.getKey();
        String value = entry.getValue();
        System.out.println(key + ":" + value);
    }
}

函數(shù)的可變參數(shù):

  • 實際上就是一個數(shù)組,但是接收的是數(shù)組的元素,自動封裝成數(shù)組,簡化調(diào)用者書寫
  • 注意事項:可變參數(shù)類型,必須定義在參數(shù)列表的結(jié)尾
public static int add(int[] arr){
    int sum = 0;
    for(int i = 0; i < arr.length; i++){
        sum += arr[i];
    }
    return sum;
}
public static int addNew(int... arr){
    int sum = 0;
    for(int i : arr){
        sum += i;
    }
    return sum;
}
public static void main(String[] args){
    int[] a = {1,3,5,7,9};
    int sum = add(a);
    addNew();
    int sum1 = addNew(1,3,5,7,9);
}

靜態(tài)導(dǎo)包方式

import java.util.Collections;       // 方式一

// 靜態(tài)導(dǎo)入,其實導(dǎo)入的是類中的靜態(tài)成員
import static java.util.Collections.max;        // 方式二

public static void main(String[] args){
    List<String> list = new ArrayList<String>();
    Collection.sort(list);      // 方式一
    max(list);    // 方式二
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容