Java集合框架詳解
day08所看的視頻來源
集合的概念
- 概念:對象的容器,定義了對多個對象進行操作的常用方法玛追∷翱危可實現(xiàn)數(shù)組的功能
- 和數(shù)組的區(qū)別:
- 數(shù)組長度固定,集合長度不固定
- 數(shù)組可以存儲基本類型和引用類型痊剖,集合只能存儲引用類型
- 位置:java.util.*;
Collection接口
Collection體系集合
Collection父接口
- 特點:代表一組任意類型的對象韩玩,無需、無下標(biāo)邢笙、不能重復(fù)
- 方法
- boolean add(Object obj) //添加一個對象
- boolean addAll(Collection c) //將一個集合中的所有對象添加到此集合中
- void clear() //清空此集合中的所有對象
- boolean contains(object o) //檢查此集合中是否包含o對象
- boolean equals(Object o) //比較此集合是否與指定對象相等
- boolean isEmpty() //判斷此集合是否為空
- boolean remove(Object o) //在此集合中移除o對象
- int size() //返回此集合中的元素個數(shù)
- Object[] toArray() //將此集合抓換成數(shù)組
package com.jihe.demo01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Collection接口的使用
* 1.添加元素
* 2.刪除元素
* 3.遍歷元素
* 4.判斷
* @author wgy
*/
public class Demo01 {
public static void main(String[] args) {
//創(chuàng)建集合
Collection collection = new ArrayList();
// * 1.添加元素
collection.add("蘋果");
collection.add("西瓜");
collection.add("榴蓮");
System.out.println("元素個數(shù):"+collection.size());
System.out.println(collection);
// // * 2.刪除元素
// collection.remove("榴蓮");
// collection.clear();
// System.out.println("刪除之后:"+collection.size());
// * 3.遍歷元素(重點)
//3.1使用增強for(因為不使用下標(biāo))
System.out.println("------------------------");
for(Object object : collection){
System.out.println(object);
}
System.out.println("------------------------");
//3.2迭代器(迭代器專門用來迭代集合的一種方式)
//hasNext();有沒有下一個元素
//next();獲取下一個元素
//remove();刪除當(dāng)前元素
Iterator it = collection.iterator();
while(it.hasNext()){
String s = (String)it.next();
System.out.println(s);
// it.remove();//刪除元素啸如,不能使用collection.remove(s);
}
// System.out.println("元素個數(shù):"+collection.size());//若刪除后元素個數(shù):0
// * 4.判斷
System.out.println(collection.contains("西瓜"));//true
System.out.println(collection.isEmpty());//false
}
}
List接口與實現(xiàn)類
List子接口
- 特點:有序、有下表氮惯、元素可以重復(fù)
- 方法:
- void add(int index, Objext o) //在index位置插入對象o
- boolean addAll(int index, Collection c) //將一個集合中的元素添加到此集合中的index位置
- Objext get(int index) //返回集合中指定位置的元素
- List subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之間的集合元素
package com.jihe.demo01;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* List子接口的使用
* 特點:1.有序有下標(biāo) 2.可以重復(fù)i
*/
public class Demo03 {
public static void main(String[] args) {
//先創(chuàng)建集合對象
List list = new ArrayList<>();
//1.添加元素
list.add("蘋果");
list.add("小米");
list.add(0,"華為");
System.out.println("元素個數(shù):"+list.size());//元素個數(shù):3
System.out.println(list.toString());//[華為, 蘋果, 小米]
// //2.刪除元素
// list.remove(0);
// System.out.println("刪除之后:"+list.size());//刪除之后:2
// System.out.println(list.toString());//[蘋果, 小米]
//3.遍歷
//3.1使用for遍歷
System.out.println("---------使用for---------");
for(int i=0; i<list.size(); i++){
System.out.println(list.get(i));
}
//3.2使用增強for
System.out.println("---------使用增強for---------");
for(Object object : list){
System.out.println(object);
}
//3.3使用迭代器
Iterator it = list.iterator();
System.out.println("---------使用迭代器---------");
while(it.hasNext()){
System.out.println(it.next());
}
//3.4使用列表迭代器镜遣,和Iterator的區(qū)別姥宝,listIterator可以向前或向后遍歷,添加、刪除憾儒、修改元素
ListIterator lit = list.listIterator();
System.out.println("---------使用列表迭代器從前往后---------");
while(lit.hasNext()){
System.out.println(lit.nextIndex()+":"+lit.next());
}
System.out.println("---------使用列表迭代器從后往前---------");
while(lit.hasPrevious()){
System.out.println(lit.previousIndex()+":"+lit.previous());
}
//4.判斷
System.out.println(list.contains("蘋果"));//true
System.out.println(list.isEmpty());//false
//獲取位置
System.out.println(list.indexOf("華為"));//0
}
}
package com.jihe.demo01;
import java.util.ArrayList;
import java.util.List;
/**
* list的使用
*/
public class Demo04 {
public static void main(String[] args) {
//創(chuàng)建集合
List list = new ArrayList();
//1.添加數(shù)字數(shù)據(jù)(自動裝箱)
list.add(20);//已經(jīng)變成包裝類
list.add(30);
list.add(40);
list.add(50);
list.add(60);
System.out.println("元素個數(shù)"+list.size());//元組個數(shù)5
System.out.println(list.toString());//[20, 30, 40, 50, 60]
//2.刪除操作
list.remove(new Integer(20));//如果想要刪除值為20的就要先new Interger把基本類型轉(zhuǎn)成引用類型
System.out.println("刪除元素:"+list.size());//刪除元素:4
System.out.println(list.toString());//[30, 40, 50, 60]
//3.補充方法subList蝶溶,返回自己和
List sublist = list.subList(1,3);//包含1不包含3
System.out.println(sublist.toString());//[40, 50]
}
}
List實現(xiàn)類
- ArrayList[重點]:
- 數(shù)組結(jié)構(gòu)實現(xiàn)膝蜈,查詢快乙漓、增刪慢
- JDK1.2版本加入的,運行效率快互婿、線程不安全
- Vector:
- 數(shù)組結(jié)構(gòu)實現(xiàn)捣郊,查詢快、增刪慢
- JDK1.0版本的慈参,運行效率慢呛牲、線程安全
- LinkedList:
- 鏈表結(jié)構(gòu)實現(xiàn),增刪快驮配,查詢慢
ArrayList使用
- 特點:有序娘扩、有下表、元素可以重復(fù)
- 使用remove()方法的時候壮锻,想要做到用相同數(shù)值來刪除對象琐旁,就需要重寫方法equals()比較兩者數(shù)值return true,否則比較的是地址無法用相同數(shù)值為條件remove()對象
ArrayList源碼分析
- 源碼分析:
- DEFAULT_CAPACITY = 10; 默認容量
- 注意:如果沒有向集合中添加任何元素時猜绣,容量為0灰殴,添加一個元素之后,容量為10掰邢,擴容原來的1.5倍
- elementData 存放元素的數(shù)組
- size 實際的元素個數(shù)
- add()添加元素
- DEFAULT_CAPACITY = 10; 默認容量
Vector使用(使用頻率不高)
//枚舉器遍歷
Enumeration en = vector.elements();
while(en.hasMoreElements()){
String o = (String)en.nextElement();
sout(o);
}
LinkedList使用
- 鏈表結(jié)構(gòu)實現(xiàn)验懊,增刪快擅羞,查詢慢(雙向鏈表)
package com.jihe.demo01;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
/**
* LinkedList的使用
* 存儲結(jié)構(gòu):雙向鏈表
*/
public class Demo02 {
public static void main(String[] args) {
//創(chuàng)建集合
LinkedList linkedList = new LinkedList<>();
//1.添加元素
Student s1 = new Student("劉德華",20);
Student s2 = new Student("郭富城",22);
Student s3 = new Student("梁朝偉",18);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s3);
System.out.println("元素個數(shù):"+linkedList.size());
System.out.println(linkedList.toString());
// //2.刪除
// linkedList.remove(new Student("劉德華",20));
// System.out.println("刪除之后:"+linkedList.size());
// linkedList.clear();
//3.遍歷
//3.1for遍歷
System.out.println("----------------for--------------");
for(int i=0; i<linkedList.size(); i++){
System.out.println(linkedList.get(i));
}
//3.2增強for
System.out.println("------------增強for--------------");
for (Object object : linkedList){
Student s = (Student)object;
System.out.println(s.toString());
}
//3.3使用迭代器
System.out.println("----------迭代器-----------------");
Iterator it = linkedList.iterator();
while(it.hasNext()){
Student s = (Student)it.next();
System.out.println(s.toString());
}
//3.4使用列表迭代器
System.out.println("---------使用列表迭代器----------");
ListIterator lit = linkedList.listIterator();
while(lit.hasNext()){
Student s = (Student)lit.next();
System.out.println(s.toString());
}
//4.判斷
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
//5.獲取
System.out.println(linkedList.indexOf(s1));
}
}
泛型和工具類
泛型概念
- Java泛型是JDK1.5中引入的一個新特性,其本質(zhì)是參數(shù)化類型义图,把類型作為參數(shù)傳遞
- 常見類型有泛型類、泛型接口召烂、泛型方法
- 語法:
- <T,...> T成為類型占位符碱工,表示一種引用類型
- 好處:
- 提高代碼的重用性
- 防止類型轉(zhuǎn)換異常,提高代碼的安全性
//MyGeneric.java
package com.jihe.demo03;
/**
* 泛型類
* 語法:類名<T>
* T是類型占位符奏夫,表示一種引用類型怕篷,如果編寫多個使用都好隔開
*/
public class MyGeneric<T> {
//使用泛型T
//1.創(chuàng)建變量
T t;
//2.作為方法的參數(shù),不能T t1 = new T();,因為不知道他是不是私有的
public void show(T t){
System.out.println(t);
}
//3.泛型作為方法的返回值
public T getT(){
return t;
}
}
//TestGeneric
package com.jihe.demo03;
public class TestGeneric {
public static void main(String[] args) {
//使用泛型類創(chuàng)建對象
//注意:1.泛型只能使用引用類型 2.不同泛型對象之間不能相互賦值
MyGeneric<String> myGeneric = new MyGeneric<String>();
myGeneric.t="hello";
myGeneric.show("大家好酗昼,加油");//大家好廊谓,加油
String string = myGeneric.getT();
MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>();
myGeneric2.t = 100;
myGeneric2.show(200);//200
Integer integer = myGeneric2.getT();
}
}
泛型接口
//MyInterface.java
package com.jihe.demo03;
/**
* 泛型接口
* 語法:接口名<T>
* 注意:不能泛型靜態(tài)常量
*/
public interface MyInterface<T> {
String name = "張三";
T server(T t);
}
兩種泛型接口實現(xiàn)
//MyInterfaceImpl.java
//先定義泛型類型,如下定義為String型
package com.jihe.demo03;
public class MyInterfaceImpl implements MyInterface<String> {
@Override
public String server(String s) {
System.out.println(s);
return null;
}
}
//MyInterfaceImpl2.java
//使用對象定義泛型類型麻削,也就是實例化的時候蒸痹,泛型類型和對象類型一直,TestGeneric里可以看出
package com.jihe.demo03;
public class MyInterfaceImpl2<T> implements MyInterface<T>{
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
//TestGeneric.java
package com.jihe.demo03;
public class TestGeneric {
public static void main(String[] args) {
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.server("xxxxxx");//因為是String定義呛哟,所以只能傳入String
MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<>();////泛型T傳入Interger類型
impl2.server(1000);
}
}
泛型集合
- 概念:參數(shù)化類型叠荠、類型安全的集合,強制集合元素的類型必須一致
- 特點:編譯時即可檢查扫责,而非運行時拋出異常
- 訪問時榛鼎,不必類型轉(zhuǎn)換(拆箱)
- 不同泛型之間引用不能相互賦值,泛型不存在多態(tài)
package com.jihe.demo03;
import java.util.ArrayList;
public class TestGeneric {
public static void main(String[] args) {
//泛型集合
ArrayList<String> arrayList = new ArrayList<String>();//泛型限定了必須是String才能add
arrayList.add("xxx");
arrayList.add("yyy");
for (String string : arrayList){//因此這里只能是String鳖孤,而不會出現(xiàn)強制類型轉(zhuǎn)換的問題
System.out.println(string);
}
}
}
Set接口與實現(xiàn)類
Set集合概述
- 特點:無序者娱、無下標(biāo)、元素不可重復(fù)
- 方法:全部繼承自Collection中的方法
Set接口的使用
一般都用HashSet
package com.jihe.demo04;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* 測試Set接口的使用
* 特點:1.無序苏揣、沒有下表 2.不能重復(fù)
*/
public class Demo01 {
public static void main(String[] args) {
//創(chuàng)建集合
Set<String> set = new HashSet<>();
//1.添加數(shù)據(jù)
set.add("蘋果");//add不能加兩個一樣的黄鳍,也就是不能重復(fù)
set.add("小米");
set.add("華為");
//2.刪除
set.remove("小米");
//3.遍歷【充電】
//3.1增強for
System.out.println("-----------增強for---------");
for(String string : set){
System.out.println(string);
}
System.out.println("-----------使用迭代器---------");
//3.2使用迭代器
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//4.判斷
System.out.println(set.contains("華為"));
System.out.println(set.isEmpty());
}
}
Set實現(xiàn)類
- HashSet【重點】:
- 基于HashCode實現(xiàn)元素不重復(fù)
- 當(dāng)存入元素的哈希碼(HashCode)相同時,會調(diào)用equals進行確認腿准,如結(jié)果為true际起,則拒絕后者存入
- TreeSet:
- 基于排序順序?qū)崿F(xiàn)元素不重復(fù)
- 實現(xiàn)了SortedSet接口,對集合元素自動排序
- 元素對象的類型必須實習(xí)Comparable接口吐葱,指定排序規(guī)則
- 通過CompareTo(重寫后可以比較對象)方法確定是否為重復(fù)元素
- 可以通過兩種重寫方法如下
//Person.java
package com.jihe.demo04;
import java.util.Objects;
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
//先按姓名比街望,然后按年齡比
public int compareTo(Person o) {
int n1=this.getName().compareTo(o.getName());
int n2=this.age-o.getAge();
return n1==0?n2:n1;//如果n1不為0則是n1,如果為0就是n2
}
}
package com.jihe.demo04;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 使用TreeSet保存數(shù)據(jù)
* 存儲結(jié)構(gòu):紅黑樹
* 要求:要素必須要實現(xiàn)Comparable接口
*/
public class Demo05 {
public static void main(String[] args) {
//創(chuàng)建集合
TreeSet<Person> persons = new TreeSet<>();
//1.添加元素
Person p1=new Person("劉德華",20);
Person p2=new Person("林志玲",22);
Person p3=new Person("梁朝偉",25);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println("元素個數(shù):"+persons.size());
System.out.println(persons.toString());
//直接重寫也可以弟跑,這樣子類里就不用implements Comparable<Person>
TreeSet<Person> persons2 = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1=o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
});
Person p4=new Person("劉德華",20);
Person p5=new Person("林志玲",22);
Person p6=new Person("梁朝偉",25);
persons2.add(p1);
persons2.add(p2);
persons2.add(p3);
System.out.println(persons.toString());
}
}
Map接口與實現(xiàn)類
- 特點:
- 存儲鍵值對
- 鍵不能重復(fù)灾前,值可以重復(fù)
- 無序
//Map方法
package com.jihe.demo05;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Map接口的使用
* - 特點:
* - 存儲鍵值對
* - 鍵不能重復(fù),值可以重復(fù)
* - 無序
* -
*/
public class Demo01 {
public static void main(String[] args) {
//創(chuàng)建Map集合
Map<String,String> map = new HashMap<>();
//1.添加元素孟辑,注意如果key一樣哎甲,value不一樣蔫敲,會吧value替換掉,也就是覆蓋
map.put("cn","中國");
map.put("uk","英國");
map.put("usa","美國");
// map.put("cn","zhongguo");
System.out.println("元素個數(shù):"+map.size());
System.out.println(map.toString());
//3.遍歷
//3.1使用keySet();
System.out.println("-----------使用keySet(),增強for--------");
// Set<String> keyset = map.keySet();
for (String key : map.keySet()) {//map.keySet()獲得的是key集合
System.out.println(key+"----"+map.get(key));//用map.get(key)獲得value
}
//3.2使用entrySet();
System.out.println("-----------使用entrySet(),增強for--------");
// Set<Map.Entry<String,String>> entries = map.entrySet();
for(Map.Entry<String,String> entry : map.entrySet()){//map.entrySet()把key和value一起封裝成一個Entry獲得
System.out.println(entry.getKey()+"------------"+entry.getValue());//調(diào)用getKey()和getValut()獲得
}
//4.判斷
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("泰國"));
}
}
Map集合的實現(xiàn)類
- HashMap【重點】
- JDK1.2版本炭玫,線程不安全奈嘿,運行效率快;允許用null作為key或是value
- 剛創(chuàng)建HashMap之后沒有添加元素table=null吞加,size=0裙犹,目的是節(jié)省空間
- HashMap剛創(chuàng)建時,table是null衔憨,為了節(jié)省空間叶圃,當(dāng)添加第一個元素時候,table容量調(diào)整為16
- 當(dāng)元素個數(shù)大于閾值(16*0.75=12)時践图,會進行擴容掺冠,擴容后為原來的2倍,目的是減少調(diào)整元素的個數(shù)
- jdk1.8當(dāng)每個鏈表長度大于8码党,并且元素個數(shù)大于64時德崭,會調(diào)整為紅黑樹,目的是提高執(zhí)行效率
- jdk1.8當(dāng)鏈表長度小于6時闽瓢,調(diào)整成鏈表
- jdk1.8以前接癌,鏈表是頭插入,jdk1.8以后是尾插入
- Hashtable(基本不用了):
- JDK1.0版本扣讼,線程安全缺猛,運行效率慢;不允許null作為key或是value
- Properties:
- Hashtable的子類椭符,要求key和value都是String荔燎。通常用于配置文件的讀取‘
- TreeMap:
- 實現(xiàn)了SortedMap接口(是Map的子接口),可以對key自動排序
Collections工具類
package com.jihe.demo05;
import java.util.*;
public class Demo02 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(5);
list.add(12);
list.add(30);
list.add(6);
//sort 排序
System.out.println("排序之前"+list.toString());
Collections.sort(list);
System.out.println("排序之后"+list.toString());
//binarySearch 二分查找
int i = Collections.binarySearch(list,6);
System.out.println(i);
//copy 賦值
List<Integer> dest = new ArrayList<>();
for (int k = 0; k < list.size(); k++) {
dest.add(0);
}
Collections.copy(dest,list);//兩個數(shù)組大小要一樣才能copy销钝,所以先for添加0
System.out.println(dest.toString());
//reverse 反轉(zhuǎn)
Collections.reverse(list);
System.out.println("反轉(zhuǎn)之后"+list);
//shuffle 打亂
Collections.shuffle(list);
System.out.println("打亂之后"+list);
//補充有咨,list轉(zhuǎn)成數(shù)組
Integer[] arr = list.toArray(new Integer[0]);
System.out.println(arr.length);//是大的那個的長度,所以0就默認變成list的長度
System.out.println(Arrays.toString(arr));
//數(shù)組轉(zhuǎn)成集合
String[] names = {"張三","李四","王五"};
//轉(zhuǎn)換后的集合是一個受限集合蒸健,不能添加和刪除座享,也就是不能add和remove
List<String> list2 = Arrays.asList(names);
System.out.println(list2);
//把基本類型數(shù)組轉(zhuǎn)換成集合時,需要修改為包裝類
Integer[] nums = {100,200,300,400,500};
List<Integer> list3 = Arrays.asList(nums);
System.out.println(list3);
}
}