1.集合的理解和好處
- 可以動態(tài)保存任意多個對象
- 提供了一系列方便的操作對象的方法:add灌砖、remove、set傀蚌、get等
- 使用集合添加和刪除新元素方便簡潔
2.集合的框架體系
3.Collection接口和常用方法
3.1常用方法
- collection實現(xiàn)子類可以存放多個元素基显,每個元素可以是Object
- 有些Collection的實現(xiàn)類,可以存放重復的元素善炫,有些不可以
- 有些Collection的實現(xiàn)類撩幽,有些是有序的(List),有些不是有序(Set)
- Collection接口沒有直接的實現(xiàn)子類箩艺,是通過它的子接口Set和List來實現(xiàn)的
//Collection 接口常用方法,以實現(xiàn)子類 ArrayList 來演示. CollectionMethod.java
import java.util.ArrayList;
import java.util.List;
public class CollectionMethod {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
// add:添加單個元素
list.add("jack");
list.add(10);//list.add(new Integer(10))
list.add(true);
System.out.println("list=" + list);
// remove:刪除指定元素
//list.remove(0);//刪除第一個元素
list.remove(true);//指定刪除某個元素
System.out.println("list=" + list);
// contains:查找元素是否存在
System.out.println(list.contains("jack"));//T
// size:獲取元素個數(shù)
System.out.println(list.size());//2
// isEmpty:判斷是否為空
System.out.println(list.isEmpty());//F
// clear:清空
list.clear();
System.out.println("list=" + list);
// addAll:添加多個元素
ArrayList list2 = new ArrayList();
list2.add("紅樓夢");
list2.add("三國演義");
list.addAll(list2);
System.out.println("list=" + list);
// containsAll:查找多個元素是否都存在
System.out.println(list.containsAll(list2));//T
// removeAll:刪除多個元素
list.add("聊齋");
list.removeAll(list2);
System.out.println("list=" + list);//[聊齋]
}
}
3.2Collection接口遍歷元素方式
3.2.1 使用Iterator(迭代器)
- Iterator對象稱為迭代器窜醉,主要用于遍歷Collection集合中的元素
- 所有實現(xiàn)了Collection接口的集合類都有一個iterator()方法,用以返回一個實現(xiàn)了Iterator接口的對象艺谆,既可以返回一個迭代器榨惰。
- 演示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionIterator {
@SuppressWarnings({"all"})
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三國演義", "羅貫中", 10.1));
col.add(new Book("小李飛刀", "古龍", 5.1));
col.add(new Book("紅樓夢", "曹雪芹", 34.6));
//遍歷 col 集合
//1. 先得到 col 對應的 迭代器
Iterator iterator = col.iterator();
//2. 使用 while 循環(huán)遍歷
while (iterator.hasNext()) {//判斷是否還有數(shù)據(jù)
//返回下一個元素,類型是 Object
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
//快捷鍵静汤,快速生成 while => itit
//顯示所有的快捷鍵的的快捷鍵 ctrl + j
//3. 當退出 while 循環(huán)后 , 這時 iterator 迭代器琅催,指向最后的元素
// iterator.next();//NoSuchElementException
//4. 如果希望再次遍歷,需要重置我們的迭代器
iterator = col.iterator();
System.out.println("===第二次遍歷===");
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
}
}
class Book {略}
3.2.2 for循環(huán)增強
增強for循環(huán)虫给,可以代替iterator迭代器藤抡,特點:增強for就是簡化版的iterator,本質是一樣的抹估,只能用于遍歷集合或數(shù)組缠黍。
基本語法:
for(元素類型 元素名:集合名或數(shù)組名){
訪問元素
}
演示:
public class ListExercise {
public static void main(String[] args) {
List list = new ArrayList();
for (int i = 0; i < 12; i++) {
list.add("hello"+i);
}
list.add(2,"zmm");
list.get(5);
list.remove(6);
list.set(7,"zmm_1");
System.out.println("*********使用增強for遍歷集合********");
for (Object o :list) {
System.out.println(o);
}
}
}
4.List接口和常用方法
4.1 List接口的基本介紹
- List集合類中元素有序(即添加順序和取出順序一致),且可重復
- List集合中的每個元素都有其對應的順序索引棋蚌,即支持索引
- 常用的實現(xiàn)類ArrayList嫁佳、LinkedList挨队、Vector
4.2 List接口的常用方法
4.3 List的三種遍歷方式
- 使用iterator
- 使用增強for
- 使用普通for
5.ArrayLIst底層結構
5.1 ArrayList的注意事項:
- ArrayList可以加入一個或多個null
- ArrayList是由數(shù)組來實現(xiàn)數(shù)據(jù)存儲的
- ArrayList基本等同于Vector,在多線程情況下蒿往,不建議使用ArrayList
5.2 ArrayList的底層操作機制
- 當創(chuàng)建ArrayList對象時盛垦,如果使用的是無參構造器,則初始elementData容量為0瓤漏,第一次添加腾夯,則擴容elementData為10,如需再次擴容蔬充,則擴容elementsData為1.5倍
- 如果使用的是指定大小的構造器蝶俱,則初始elementData容量為指定大小,如果需要擴容饥漫。則直接擴容elementData為1.5倍
6.Vector底層結構
6.1 Vector介紹
- 底層也是一個對象數(shù)組
- Vector是線程同步的榨呆,即線程安全,在開發(fā)中庸队,需要線程同步安全時积蜻,考慮使用Vector
6.2 ArrayList和Vector的比較
底層結構都是可變數(shù)組,線程安全ArrayLIst不安全彻消,但是效率高竿拆;Vector安全,但是效率不高宾尚。在擴容倍數(shù)方面丙笋,ArrayLIst如果使用的是有參構造器,需要擴容的時候直接擴充原來的1.5倍煌贴,如果使用的是無參構造器御板,則第一次擴容為10,第二次開始按1.5倍擴充崔步。Vector如果是無參稳吮,默認10,滿后按2倍擴容井濒;如果指定大小灶似,則每次按3倍擴容。
7.LinkedList底層結構
7.1 LinkedList的基本介紹
- LinkedList底層實現(xiàn)了雙向鏈表和雙端隊列特點
- 可以添加任意元素(元素可以重復)瑞你,包括null
- 線程不安全酪惭,沒有實現(xiàn)同步
- LinkedList中維護了兩個屬性first和last分別指向首節(jié)點和尾節(jié)點
- 每個節(jié)點(Node對象),里面又維護了prev者甲、next春感、item三個屬性,其中通過prev指向前一個,通過next指向后一個節(jié)點鲫懒。最終實現(xiàn)雙向鏈表嫩实。
- LinkedList的元素添加和刪除不是通過數(shù)組完成的,相對來說效率較高
package com.zmm.list_;
/**
* @author zmm
* 雙向鏈表的簡單演示
*/
public class LinkedList01 {
public static void main(String[] args) {
Node zmm = new Node("zmm");
Node z1 = new Node("z1");
Node z2 = new Node("z2");
zmm.next=z1;
z1.next=z2;
z2.pre=z1;
z1.pre=zmm;
Node first=zmm;
Node last=z2;
//雙向鏈表循環(huán)
while(true){
if(first==null){
break;
}
System.out.println(first);
first=first.next;
}
System.out.println("--------------------------");
//向鏈表插入節(jié)點
Node mmz = new Node("mmz");
mmz.next=z2;
mmz.pre=z1;
z1.next=mmz;
z2.pre=mmz;
first=zmm;
while(true){
if(first==null){
break;
}
System.out.println(first);
first=first.next;
}
System.out.println("--------------------------");
//向鏈表刪除節(jié)點
z1.next=z2;
z2.pre=z1;
mmz.next=null;
mmz.pre=null;
first=zmm;
while(true){
if(first==null){
break;
}
System.out.println(first);
first=first.next;
}
}
}
class Node{
public Object item;
public Node next;
public Node pre;
public Node(Object name){
this.item=name;
}
@Override
public String toString() {
return "Node name="+item;
}
}
7.2 ArrayList和LInkedList的比較
ArrayLIst的底層結構是可變數(shù)組窥岩,LInkedLIst是雙向鏈表甲献;在增刪效率上,ArrayList較低颂翼,LinkedList較高晃洒;改查效率的話,ArrayList較高朦乏,LinkedList較低球及。
如何選擇ArrayList和LinkedList:
如果改查的操作較多,使用ArrayList
如果刪增的操作較多呻疹,使用LinkedList
一般來說大部分業(yè)務是查詢吃引,因此大部分情況下會選擇ArrayList
8.Set接口和常用方法
8.1 Set接口基本介紹
1.無序(添加和取出順序不一致),沒有索引
2.不允許重復元素诲宇,所以最多包含一個null
8.2 Set接口的常用方法
Set接口也是Collection的子接口际歼,因此,常用方法和Collection接口一樣
8.3 Set接口的遍歷方式
- 可以使用迭代器-iterator
- 增強for
- 不能使用索引的方式來獲取
9.Set接口實現(xiàn)類-HashSet
- HashSet實現(xiàn)了Set接口
- HashSet實際上是HashMap姑蓝,HaspMap底層是(數(shù)組+鏈表)
- 可以存放null值,但是只能有一個null
- HashSet不保證元素是有序的吕粗,取決于hash后纺荧,在確定索引的結果(即,不保證存放元素的順序和取出的順序一致)
- 不能有重復的元素或對象
9.1 HashSet底層機制說明
結論:
- HashSet底層是HashMap
- 先獲取元素的哈希值(hashCode方法)
- 對哈希值進行運算颅筋,得出一個索引值即為要存放在哈希表中的位置號
- 如果該位置上沒有其他元素宙暇,則直接存放,如果該位置上已經有其他元素议泵,則需要進行equals(自定義)判斷占贫,如果相等,則不再添加先口,如果不相等型奥,則以鏈表的方式添加。
10. Set接口實現(xiàn)類-LinkedHashSet
- LinkedHashSet是HashSet的子類
- LinkedHashSet底層是一個LinkedHashMap碉京,底層維護了一個數(shù)組+雙向鏈表
- LinkedHashSet根據(jù)元素的hashCode值來決定元素的存儲位置厢汹,同時使用鏈表維護元素的次序,這使得元素看起來是以插入順序保存的
- LinkedHashSet不允許添加重復元素
11. Map接口和常用方法
11.1 Map接口實現(xiàn)類的特點
- Map與Collection并列存在谐宙。用于保存具有映射關系的數(shù)據(jù):Key-Value
- Map中的key和value可以是任何引用類型的數(shù)據(jù)
- Map中的key不允許重復
- Map中的value可以重復
- Map的key可以為null烫葬,value也可以為null,注意key為null,只能有一個搭综,value為null垢箕,可以多個
- 常用String類作為Map的key
- Key和value之間存在單向一對一關系,即通過指定的key總能找到對應的value
11.2Map接口常用方法
- put:添加
- remove:根據(jù)鍵刪除映射關系
- get:根據(jù)鍵獲取值
- size:獲取元素個數(shù)
- isEmpty:判斷個數(shù)是否為0
- clear:清除
- containsKey:查找鍵是否存在
11.3Map接口遍歷方法
- containsKey:查找鍵是否存在
- KeySet:獲取所有的鍵
- entrySet:獲取所有關系k-v
- values:獲取所有的值
package com.zmm.map_;
import java.util.*;
/**
* @author zmm
*/
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("鄧超", "孫儷");
map.put("王寶強", "馬蓉");
map.put("宋喆", "馬蓉");
map.put("劉令博", null);
map.put(null, "劉亦菲");
map.put("鹿晗", "關曉彤");
//第一組: 先取出 所有的 Key , 通過 Key 取出對應的 Value
Set keySet = map.keySet();
//(1) 增強 for
System.out.println("-----第一種方式-------");
for(Object key:keySet){
System.out.println(key+"-"+map.get(key));
}
//(2) 迭代器
System.out.println("----第二種方式--------");
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next+"-"+map.get(next));
}
//第二組: 把所有的 values 取出
Collection values = map.values();
System.out.println("---取出所有的 value 增強 for----");
for(Object value:values){
System.out.println(value);
}
//(2) 迭代器
System.out.println("---取出所有的 value 迭代器----");
Iterator iterator1 = values.iterator();
while (iterator1.hasNext()) {
Object value = iterator1.next();
System.out.println(value);
}
//第三組: 通過 EntrySet 來獲取 k-v
Set entrySet = map.entrySet();
//(1) 增強 for
System.out.println("----使用 EntrySet 的 for 增強(第 3 種)----");
for(Object entry:entrySet){
Map.Entry m=(Map.Entry)entry;
System.out.println(m.getKey()+"-"+m.getValue());
}
//(2) 迭代器
System.out.println("----使用 EntrySet 的 迭代器(第 4 種)----");
Iterator iterator2 = entrySet.iterator();
while (iterator2.hasNext()) {
Object entry = iterator2.next();
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
}
}