1.集合。
1.1傳統(tǒng)容器在進(jìn)行增。刪等破壞性操作時(shí),需要移動(dòng)元素,可能導(dǎo)致性能問(wèn)題,同時(shí)添加。刪除等算法和具體業(yè)務(wù)耦合在一起,增加了程序開(kāi)發(fā)的復(fù)雜度,Java集合框提供了一套性能優(yōu)良,使用方便的接口和類(lèi)。位于Java。util包。
1.2collection:他是Java集合框(collection - frame)中的頂層接口,這個(gè)接口是一個(gè)容器,容器中只能存儲(chǔ)引用數(shù)據(jù)類(lèi)型? ??建議存同一類(lèi)型的引用類(lèi)型,方便后續(xù)遍歷等操作。容器中的元素可以是有序的、可重復(fù)的,稱(chēng)為L(zhǎng)ist接口也可能是無(wú)序的、唯一的,稱(chēng)為Set接口。

1.3集合常用方法:
public?static?void?main(String[] args) {
/**
*增:add/addAll
*刪:clear/remove/removeAll/retainAll
*改:
*查:contains/containsAll/isEmpty/size
?*/
Collection?c1?= new?ArrayList();
//追加
c1.add("apple"); // Object object = new String("apple");
// c1.add(1); ?// Object object = new Integer(1);
c1.add("banana");
System.out.println(c1);
//追加一個(gè)集合
Collection?c2?= new?ArrayList();
c2.add("java");
c2.add("c++");
c1.addAll(c2);
System.out.println(c1);
// clear
//c1.clear();
// c1.remove("apple");
// c1.removeAll(c2);
//c1.retainAll(c2);
//System.out.println(c1);
System.out.println(c1.contains("apple"));
c2.add("js");
System.out.println(c1.containsAll(c2));
// c1.clear();
System.out.println(c1.isEmpty());
//返回集合元素的個(gè)數(shù)
System.out.println(c1.size());
System.out.println(c1.equals(c2));
}
1.4集合的遍歷:Iterable?可遍歷的接口,集合接口繼承于它,集合支持快速遍歷。
/快速遍歷
// for-each
// Object表示元素類(lèi)型
// item表示迭代變量
// c1表示集合
for?(Object item?: c1) {
System.out.println(item.toString());
}
快速遍歷的本質(zhì):Collection繼承Iterable接口,表示集合支持快速遍歷。Iterable接口定義了一個(gè)方法iterator()用于獲取集合的迭代器,是一個(gè)Iterator接口類(lèi)型,iterator()內(nèi)部返回一個(gè)實(shí)現(xiàn)類(lèi)實(shí)現(xiàn)類(lèi)Iterator接口。這個(gè)實(shí)現(xiàn)類(lèi)一定具有hasNext和next方法用于判斷是否有下一個(gè)元素和獲取下一個(gè)元素。快速遍歷就是基于迭代器工作的。
public?static?void?main(String[] args) {
Collection?c1?= new?ArrayList();
c1.add("apple");
c1.add("banana");
c1.add("coco");
//快速遍歷
// for-each
// Object表示元素類(lèi)型
// item表示迭代變量
// c1表示集合
for?(Object item?: c1) {
System.out.println(item.toString());
}
//迭代器遍歷(國(guó)內(nèi))
Iterator?it?= c1.iterator();
while(it.hasNext()) {
Object item?= it.next();
System.out.println(item.toString());
}
//國(guó)外
for(Iterator?it2=c1.iterator();it2.hasNext();) {
Object item?= it2.next();
System.out.println(item.toString());
}
}

1.5list接口:List?接口中的元素時(shí)有序的、可重復(fù)的。List接口中的元素通過(guò)索引(index)來(lái)確定元素的順序。有序的collection(也稱(chēng)為序列)??梢詫?duì)列表中每個(gè)元素的插入位置進(jìn)行精確地控制。用戶(hù)可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問(wèn)元素,并搜索列表中的元素
list接口常用方法:
public?static?void?main(String[] args) {
/**
*增:add/addAll/add(index,el)/addAll(index,collection)
*刪:clear/remove/removeAll/remove(index)
*改:set(index,el)
*查:get(index)/indexOf/lastIndexOf()
*其他:contains/containsAll/isEmpty/size
?*/
List?list1?= new?ArrayList();
//添加元素
list1.add("apple");
list1.add("banana");
//在指定位置添加元素
list1.add(0, "coco");
System.out.println(list1);
List?list2?= new?ArrayList();
list2.add("java");
list2.add("c++");
list1.addAll(1, list2);
System.out.println(list1);
//刪除
list1.remove(0);
System.out.println(list1);
//修改
list1.set(0, "javax");
System.out.println(list1);
//查
System.out.println(list1.get(0));
list1.add("apple");
list1.add("apple");
System.out.println(list1);
System.out.println(list1.indexOf("apple"));
System.out.println(list1.lastIndexOf("apple"));
}
list接口遍歷:ListIterator 繼承于Iterator,在Iterator的基礎(chǔ)上提供了以正向遍歷集合,也可以以逆序遍歷集合。hasNext/next 以正向遍歷,hasPrevious/previous 以逆序遍歷
public?static?void?main(String[] args) {
List?list1?= new?ArrayList();
list1.add("apple");
list1.add("banana");
list1.add("coco");
//【1】快速遍歷
System.out.println("--for each--");
for?(Object item?: list1) {
System.out.println(item.toString());
}
//【2】普通for
System.out.println("--for--");
for(int?i=0;i<list1.size();i++) {
System.out.println(list1.get(i));
}
//【3】集合迭代器
System.out.println("--iterator--");
Iterator?it?= list1.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println("--list iterator--");
//正向遍歷
ListIterator?it2?= list1.listIterator();
while(it2.hasNext()) {
System.out.println(it2.next());
}
//逆序遍歷
while(it2.hasPrevious()) {
System.out.println(it2.previous());
}
System.out.println("--list iterator with index--");
ListIterator?it3?= list1.listIterator(1);
while(it3.hasNext()) {
System.out.println(it3.next());
}
}

1.6數(shù)據(jù)結(jié)構(gòu):數(shù)據(jù)結(jié)構(gòu)就是數(shù)據(jù)在內(nèi)存中存儲(chǔ)結(jié)構(gòu)。根據(jù)存儲(chǔ)的方式不同,分為線(xiàn)性表、二叉樹(shù)、圖、棧、隊(duì)列等
線(xiàn)表性:線(xiàn)性表數(shù)據(jù)按照一定的邏輯順序存儲(chǔ)在內(nèi)存中。線(xiàn)性表是有序的。線(xiàn)性表根據(jù)內(nèi)存的物理結(jié)構(gòu)分為兩種:數(shù)組和鏈表。
數(shù)組是一種邏輯上有序的線(xiàn)性表,物理上也連續(xù)。

鏈表是一種邏輯上有序的線(xiàn)性表,但物理上不連續(xù)。

數(shù)組和鏈表的區(qū)別
相同點(diǎn)
不同點(diǎn)
數(shù)組在查詢(xún)時(shí)效率高,在添加、刪除元素時(shí)效率低(涉及移動(dòng)元素)
鏈表在查詢(xún)時(shí)效率低(每次從頭開(kāi)始,不能跳躍訪問(wèn)),在添加、刪除元素時(shí)效率高(不涉及移動(dòng)元素)
1.7棧:特性:先進(jìn)后出,后進(jìn)先出

1.8隊(duì)列:特性:先進(jìn)先出

1.9:arraylist/vector:ArrayList是List接口的實(shí)現(xiàn)類(lèi),底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,實(shí)現(xiàn)大小可變的數(shù)組。
ArrayList?線(xiàn)程不安全,jdk1.2
ArrayList?底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,默認(rèn)數(shù)組大小是10,如果添加的元素個(gè)數(shù)超過(guò)默認(rèn)容量,ArrayList會(huì)自動(dòng)拓容,拓容原則:newCapacity = oldCapacity + oldCapacity / 2;
如果未來(lái)確定序列的元素不在增加,通過(guò)調(diào)用trimToSize()調(diào)制容量至合適的空間。
ArrayList作為L(zhǎng)ist接口的實(shí)現(xiàn)類(lèi),常用方法和遍歷方法參考List接口。
Vector?是List接口的實(shí)現(xiàn)類(lèi),底層數(shù)據(jù)結(jié)構(gòu)也是數(shù)組,也是大小可變的數(shù)組。
Vector是線(xiàn)程安全的,jdk1.0
Vector底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,默認(rèn)數(shù)組大小是10,如果添加的元素個(gè)數(shù)超過(guò)默認(rèn)容量,Vector會(huì)自動(dòng)拓容,拓容原則:newCapacity = oldCapacity +capacityIncrement(增長(zhǎng)因子);如果未來(lái)確定序列的元素不在增加,通過(guò)調(diào)用trimToSize()調(diào)制容量至合適的空間。
注意:Vector在實(shí)現(xiàn)List接口的同時(shí),同添加了自身特有的方法xxxElement,未來(lái)使用時(shí)為了程序的可拓展性,一定要按照接口來(lái)操作Vector。
1.10linkedlist:LinkedList是List接口的實(shí)現(xiàn)類(lèi),底層數(shù)據(jù)結(jié)構(gòu)是鏈表。
LinekList常用方法和遍歷方法參照List接口。
LinkedList線(xiàn)程不安全。
除了實(shí)現(xiàn)List接口,還實(shí)現(xiàn)棧接口

push入棧操作/ pop出棧操作
public?class?Test01 {
public?static?void?main(String[] args) {
LinkedList?list?= new?LinkedList();
list.push("apple");
list.push("banana");
list.push("coco");
System.out.println(list.pop());
System.out.println(list.pop());
System.out.println(list.pop());
// java.util.NoSuchElementException
System.out.println(list.pop());
}
}

add/remove/element()可能會(huì)出現(xiàn)NoSuchElementException異常
public?static?void?main(String[] args) {
LinkedList?queue?= new?LinkedList();
//入隊(duì)
/**
*隊(duì)列頭 ??????????? 隊(duì)列尾
?*<----- ?????????<-----
?* [apple, banana, coco]
?*/
queue.add("apple");
queue.add("banana");
queue.add("coco");
System.out.println(queue);
//出隊(duì)
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue);
// java.util.NoSuchElementException
System.out.println(queue.remove());
//獲取表頭元素
System.out.println(queue.element());
}
offer/poll/peek可能會(huì)返回特殊值(null)
public?static?void?main(String[] args) {
LinkedList?queue?= new?LinkedList();
//入隊(duì)
/**
*隊(duì)列頭 ??????????? 隊(duì)列尾
?*<----- ?????????<-----
?* [apple, banana, coco]
?*/
queue.offer("apple");
queue.offer("banana");
queue.offer("coco");
//出隊(duì)列
//System.out.println(queue.poll());
//System.out.println(queue.poll());
//System.out.println(queue.poll());
System.out.println(queue);
//System.out.println(queue.poll());
//獲取表頭元素
System.out.println(queue.peek());
}
雙向隊(duì)列(Deque)接口

/**
*以雙向隊(duì)列形式操作LinkedList
?*/
public?class?Test04 {
public?static?void?main(String[] args) {
LinkedList?queue?= new?LinkedList();
//入隊(duì)
/**
?*<----- ?????????<-----
?* [apple, banana, coco]
?* ---->??????????----->
?*/
queue.addFirst("apple");
queue.addFirst("banana");
queue.addFirst("coco");
System.out.println(queue);
System.out.println(queue.removeLast());
System.out.println(queue.removeFirst());
System.out.println(queue.removeFirst());
System.out.println(queue);
//獲取頭元素
System.out.println(queue.getFirst());
}
}
iterator和listitrator:Iterator在迭代過(guò)程中不允許向集合中添加元素
public?static?void?main(String[] args) {
ArrayList?list?= new?ArrayList();
list.add("apple");
list.add("banana");
list.add("coco");
Iterator?it?= list.iterator();
while(it.hasNext()) {
String item?= (String) it.next();
if(item.equals("banana")) {
list.add("test");
}
}
System.out.println(list);
}
當(dāng)通過(guò)Iterator集合迭代器遍歷集合過(guò)程中,不能再向集合匯總添加元素,否則出現(xiàn)ConcurrentModificationException并發(fā)修改異常。ListIterator允許程序員按任一方向遍歷列表、迭代期間修改列表,并獲得迭代器在列表中的當(dāng)前位置
public?class?Test01 {
public?static?void?main(String[] args) {
ArrayList?list?= new?ArrayList();
list.add("apple");
list.add("banana");
list.add("coco");
ListIterator?it?= list.listIterator();
while(it.hasNext()) {
String item?= (String) it.next();
if(item.equals("banana")) {
it.add("test");
}
}
System.out.println(list);
}
}
2.泛型:泛型允許開(kāi)發(fā)者在強(qiáng)類(lèi)型程序設(shè)計(jì)語(yǔ)言(java)編寫(xiě)代碼時(shí)定義一些可變部分,這些部分在使用前必須作出指明。泛型就是將類(lèi)型參數(shù)化
ArrayList<E> ?list表示聲明了一個(gè)列表list,列表的元素是E類(lèi)型
ArrayList<String> list = new ArrayList<String>();
聲明了一個(gè)列表list,列表的元素只能是String類(lèi)型。
泛型在編譯器起作用,運(yùn)行時(shí)jvm察覺(jué)不到泛型的存在。
2.1泛型的擦除:泛型在運(yùn)行時(shí)已經(jīng)被擦除了。
public?static?void?main(String[] args) {
ArrayList<String> list?= new?ArrayList<String>();
list.add("apple");
System.out.println(list?instanceof?ArrayList);
System.out.println(list?instanceof?ArrayList<String>);
}
Cannot perform instanceof check against parameterized type ArrayList<String>. Use the form ArrayList<?> instead since further generic type information will be erased at runtime
2.2泛型的應(yīng)用:1.泛型類(lèi):當(dāng)一個(gè)類(lèi)中屬性的數(shù)據(jù)類(lèi)型不確定時(shí),具體是什么類(lèi)型由使用者來(lái)確定時(shí),使用泛型。泛型類(lèi)的形式”
public?class 類(lèi)名<T>?{
}
定義一個(gè)泛型類(lèi)
public?class?FanClass<T> {
private?T t;
public?T getT() {
return?t;
}
public?void?setT(T t) {
this.t?= t;
}
public?FanClass(T t) {
super();
this.t?= t;
}
public?FanClass() {
super();
}
}
public?class?Test01 {
public?static?void?main(String[] args) {
FanClass<String> fan?= new?FanClass<String>();
fan.setT("apple");
FanClass<Integer> fan2?= new?FanClass<Integer>();
fan2.setT(1);
}
}
2.泛型的方法:當(dāng)一個(gè)方法的參數(shù)類(lèi)型不確定時(shí),具體是什么類(lèi)型由使用者來(lái)確定,可以考慮使用泛型方法。形式:
public?<T>?void?xxx(T?a) {
System.out.println(a);
}
public?class?Student {
/*public void showInfo(int?a) {
System.out.println(a);
}
public void showInfo(float a) {
System.out.println(a);
}
public void showInfo(String a) {
System.out.println(a);
}*/
public?<T> void?showInfo(T?a) {
System.out.println(a);
}
}
public?static?void?main(String[] args) {
Student stu?= new?Student();
stu.showInfo(1);
stu.showInfo("apple");
stu.showInfo(1.0f);
}
泛型方法在調(diào)用時(shí)確定(指明)類(lèi)型。
泛型方法在一定程度上優(yōu)化了方法重載。
泛型方法可以定義多個(gè)泛型類(lèi)型
//可以定義多個(gè)泛型的類(lèi)型
public?<A,B> void?showInfo(A?a,B b) {
System.out.println(a);
System.out.println(b);
}
多個(gè)泛型類(lèi)型進(jìn)一步優(yōu)化了方法重載。
多個(gè)同類(lèi)型的泛型
//多個(gè)同類(lèi)型的泛型
/*public <A> void print(A a) {
System.out.println(a);
}
public <A> void print(A a,A b) {
System.out.println(a);
System.out.println(b);
}*/
public?<A> void?print(A...a) {
System.out.println(a);
}
A… a 表示方法可以接受多個(gè)參數(shù)。當(dāng)調(diào)用方法傳遞多個(gè)參數(shù)時(shí),多個(gè)參數(shù)被放到a數(shù)組中,a是什么類(lèi)型的數(shù)組由開(kāi)發(fā)者調(diào)用處傳參決定。
stu.print(1);
stu.print(1,2);
stu.print("apple");
stu.print("apple","banana");
print(A...a) 方法稱(chēng)為可變參數(shù)的泛型形式。
3.泛型接口:如果接口中的方法的參數(shù)(形參、返回值)不確定時(shí),可以考慮使用泛型接口。形式
public interface FanInterface<T>?{
public void showInfo(T t);
}
[1]實(shí)現(xiàn)類(lèi)能確定泛型接口的類(lèi)型
public?class?ImplClass implements?FanInterface<String>{
@Override
public?void?showInfo(String?t) {
// TODO?Auto-generated method stub
}
}
[2]實(shí)現(xiàn)類(lèi)不能確定泛型接口的類(lèi)型->繼續(xù)泛。
public?class?ImplClass2<T> implements?FanInterface<T>{
@Override
public?void?showInfo(T t) {
}
}
4.泛型的上限和下限:泛型的上限ArrayList(? extends Pet) list 聲明了一個(gè)容器,容器中的元素類(lèi)型一定要繼承于Pet,我們稱(chēng)這種形式叫做泛型的上限。泛型的下限ArrayList(? super Pet) list 聲明了一個(gè)容器,容器中的元素類(lèi)型一定要是Pet的父類(lèi),我們稱(chēng)這個(gè)形式為泛型的下限。
3.set接口:Set接口表示一個(gè)唯一、無(wú)序的容器(和添加順序無(wú)關(guān))
3.1set接口提供的方法
public?static?void?main(String[] args) {
/**
*增:add/addAll
*刪:clear/remove/removeAll/retainAll
*改:
*查:contains/containsAll
*遍歷:iterator
*其他:size/isEmpty
?*/
Set<Integer> set?= new?HashSet<Integer>();
// [1]添加
//無(wú)序
set.add(10);
set.add(3);
set.add(20);
set.add(0);
//不能添加重復(fù)元素
boolean?r?= set.add(1);
System.out.println(set);
//【2】刪除
// set.remove(1);
// set.clear();
// System.out.println(set);
//【3】查看是否包含
System.out.println(set.contains(1));
//【4】其他
System.out.println(set.size());
System.out.println(set.isEmpty());
}
3.2set接口的遍歷:
public?static?void?main(String[] args) {
Set<String> set?= new?HashSet<String>();
set.add("banana");
set.add("apple");
set.add("coco");
//快速遍歷
for?(String item?: set) {
System.out.println(item);
}
//迭代器
Iterator<String> it?= set.iterator();
while(it.hasNext()) {
String item?= it.next();
System.out.println(item);
}
}
Set接口的實(shí)現(xiàn)類(lèi)常見(jiàn)的有HashSet、LinkedHashSet、TreeSet
3.2hashset:
ashSet是Set接口的實(shí)現(xiàn)類(lèi),底層數(shù)據(jù)結(jié)構(gòu)是哈希表。
HashSet是線(xiàn)程不安全的(不保證同步)
哈希表工作原理:

3.3添加自定義對(duì)象:
根據(jù)哈希表的工作原理,請(qǐng)存儲(chǔ)一個(gè)自定義對(duì)象到HashSet中。
package?cn.sxt03.hashset;
public?class?Student {
private?String id;
private?String name;
private?int?age;
// …
@Override
public?int?hashCode() {
final?int?prime?= 31;
int?result?= 1;
result?= prime?* result?+ age;
result?= prime?* result?+ ((id?== null) ? 0 : id.hashCode());
result?= prime?* result?+ ((name?== null) ? 0 : name.hashCode());
return?result;
}
@Override
public?boolean?equals(Object obj) {
if?(this?== obj)
return?true;
if?(obj?== null)
return?false;
if?(getClass() != obj.getClass())
return?false;
Student other?= (Student) obj;
if?(age?!= other.age)
return?false;
if?(id?== null) {
if?(other.id?!= null)
return?false;
} else?if?(!id.equals(other.id))
return?false;
if?(name?== null) {
if?(other.name?!= null)
return?false;
} else?if?(!name.equals(other.name))
return?false;
return?true;
}
@Override
public?String toString() {
return?"Student [id="?+ id?+ ", name="?+ name?+ ", age="?+ age?+ "]";
}
}
總結(jié)
[1]如果向HashSet中存儲(chǔ)元素時(shí),元素一定要實(shí)現(xiàn)hashCode方法和equals方法。
[2]?優(yōu)點(diǎn):添加、刪除、查詢(xún)效率高;缺點(diǎn):無(wú)序
4.linkedhashset:LinkedHashSet是Set接口的實(shí)現(xiàn)類(lèi),底層數(shù)據(jù)結(jié)構(gòu)哈希表+鏈表哈希表用于散列元素;鏈表用于維持添加順序。如果要添加自定義對(duì)象元素,也需要重寫(xiě)hashCode和equals方法。
5.treeset:TreeSet 是Set接口的實(shí)現(xiàn)類(lèi),底層數(shù)據(jù)結(jié)構(gòu)是二叉樹(shù)。TreeSet?存儲(chǔ)的數(shù)據(jù)按照一定的規(guī)則存儲(chǔ)。存儲(chǔ)規(guī)則讓數(shù)據(jù)表現(xiàn)出自然順序。
5.1treeset的工作原理:

添加一個(gè)新元素t的存儲(chǔ)的步驟
[1]?如果集合無(wú)元素,t直接加入;如果集合有元素,t和根節(jié)點(diǎn)比較;
[2] 如果t小于根節(jié)點(diǎn);把t放到根節(jié)點(diǎn)的左子樹(shù)上;重復(fù)1-3步驟
[3] t大于根節(jié)點(diǎn);把t放到根節(jié)點(diǎn)的右子樹(shù)上;重復(fù)1-3步驟
輸出時(shí)按照一定的規(guī)則:左子樹(shù)->根節(jié)點(diǎn)->右子樹(shù)
根據(jù)TreeSet的工作原理,向TreeSet添加自定義元素?
向TreeSet中添加元素時(shí),一定要提供比較策略,否則會(huì)出現(xiàn)ClassCastException。
?
比較策略分兩種:內(nèi)部比較器和外部比較器
內(nèi)部比較器:當(dāng)一個(gè)自定義對(duì)象實(shí)現(xiàn)Comparable并實(shí)現(xiàn)compareTo方法時(shí),通過(guò)指定具體的比較策略,此時(shí)稱(chēng)為內(nèi)部比較器。
package?cn.sxt05.treeset;
public?class?Student implements?Comparable<Student>{
private?String id;
private?String name;
private?int?age;
// 。。。
@Override
public?String toString() {
return?"Student [id="?+ id?+ ", name="?+ name?+ ", age="?+ age?+ "]";
}
@Override
public?int?compareTo(Student o) {
if(this.getAge()<o.getAge()) {
return?-1;
}else?if(this.getAge() == o.getAge()) {
return?0;
}else?{
return?1;
}
}
}
比較策略的幾種情況:1比較策略一般當(dāng)前對(duì)象寫(xiě)在前面,待比較對(duì)象也在后面,比較結(jié)果默認(rèn)升序
return??this.getAge() - o.getAge() ;
2 多種比較因素:
@Override
public?int?compareTo(Student o) {
/*if(this.getAge()<o.getAge()) {
return -1;
}else if(this.getAge() == o.getAge()) {
return 0;
}else {
return 1;
}*/
// return ?this.getAge() - o.getAge() ;
if(this.getAge()<o.getAge()) {
return?-1;
}else?if(this.getAge() == o.getAge()) {
return?this.getName().compareTo(o.getName());
}else?{
return?1;
}
}
外部比較器:當(dāng)實(shí)際開(kāi)發(fā)過(guò)程中不知道添加元素的源代碼、無(wú)權(quán)修改別人的代碼,此時(shí)可以使用外部比較器。Comparator?位于java.util包中,定義了compare(o1,o2)用于提供外部比較策略。TreeSet接受一個(gè)指定比較策略的構(gòu)造方法,這些比較策略的實(shí)現(xiàn)類(lèi)必須實(shí)現(xiàn)Comparator接口。
需求:按照字符串的長(zhǎng)度比較
public?class?Test01 {
public?static?void?main(String[] args) {
LenComparator lenComparator?= new?LenComparator();
TreeSet<String> set2?= new?TreeSet<String>(lenComparator);
set2.add("banana");
set2.add("coco");
set2.add("apple");
set2.add("apple");
System.out.println(set2);
}
}
class?LenComparator implements?Comparator<String>{
@Override
public?int?compare(String o1, String o2) {
return?o1.length() - o2.length();
}
}
使用匿名內(nèi)部類(lèi)優(yōu)化
public?class?Test02 {
public?static?void?main(String[] args) {
TreeSet<String> set2?= new?TreeSet<String>(new?Comparator<String>() {
@Override
public?int?compare(String o1, String o2) {
return?o1.length() - o2.length();
}
});
set2.add("banana");
set2.add("coco");
set2.add("apple");
set2.add("apple");
System.out.println(set2);
}
}
5.map接口:Map接口稱(chēng)為鍵值對(duì)集合或者映射集合,其中的元素(entry)是以鍵值對(duì)(key-value)的形式存在。Map?容器接口中提供了增、刪、改、查的方式對(duì)集合進(jìn)行操作。Map接口中都是通過(guò)key來(lái)操作鍵值對(duì),一般key是已知。通過(guò)key獲取value。
5.1map的常用方法:
public?static?void?main(String[] args) {
/**
*增:put/putAll
*刪:clear/remove
*改:put
*查:get/containsKey/containsValue
*其他:isEmpty/size
?*/
Map<String, String> map?= new?HashMap<String,String>();
//【1】put
map.put("A", "apple");
map.put("B", "banana");
map.put("C", "coco");
//【2】刪除
// map.clear();
// smap.remove("A");
//【3】修改
//map.put("A", "apple x");
//【4】查看
String val?= map.get("A");
System.out.println(map.containsKey("D"));
System.out.println(map);
}
5.2map的接口遍歷:
通過(guò)keySet() 返回map中鍵的set集合。
public?static?void?main(String[] args) {
Map<String, String> map?= new?HashMap<String,String>();
map.put("B", "banana");
map.put("A", "apple");
map.put("C", "coco");
// map無(wú)序
//可以根據(jù)key的自然順序 讓map有序 ?=> 一般用string作為key
System.out.println(map);
//遍歷
Set<String> keys?= map.keySet();
for?(String key?: keys) {
System.out.println(key+"=>"+map.get(key));
}
Iterator<String> it?= keys.iterator();
while(it.hasNext()) {
String key?= it.next();
System.out.println(key+"=>"+map.get(key));
}
}
map中以鍵值對(duì)作為元素,鍵值對(duì)在map中稱(chēng)為entry,entrySet返回鍵值對(duì)的set集合。
public?static?void?main(String[] args) {
Map<String, String> map?= new?HashMap<String,String>();
map.put("B", "banana");
map.put("A", "apple");
map.put("C", "coco");
// map無(wú)序
//可以根據(jù)key的自然順序 讓map有序 ?=> 一般用string作為key
System.out.println(map);
// entrySet
Set<Entry<String, String>> entrySet?= map.entrySet();
for?(Entry<String, String> entry?: entrySet) {
System.out.println(entry.getKey()+"=>"+entry.getValue());
}
Iterator<Entry<String, String>> it2?= entrySet.iterator();
while(it2.hasNext()) {
Entry<String, String> entry?= it2.next();
System.out.println(entry.getKey()+"=>"+entry.getValue());
}
}
Map接口的實(shí)現(xiàn)類(lèi)HashMap、LinkedHashMap、TreeMap
5.2hashmap:HashMap?是Map的實(shí)現(xiàn)類(lèi),key以HashSet存儲(chǔ)。
public?static?void?main(String[] args) {
/*
HashMap<String, Object> map = new HashMap<String,Object>();
ArrayList<String> list1 = new ArrayList<String>();
list1.add("alex");
list1.add("alice");
list1.add("allen");
map.put("A", list1);
ArrayList<String> list2 = new ArrayList<String>();
list2.add("ben");
list2.add("bill");
map.put("B", list2);
System.out.println(map);
*/
HashMap<Student, Object> map?= new?HashMap<Student,Object>();
ArrayList<String> list1?= new?ArrayList<String>();
list1.add("alex");
list1.add("alice");
list1.add("allen");
Student?s1?= new?Student("001", "大狗", 20);
map.put(s1, list1);
ArrayList<String> list2?= new?ArrayList<String>();
list2.add("ben");
list2.add("bill");
Student?s2?= new?Student("001", "大狗", 20);
//修改
map.put(s2, list2);
System.out.println(map);
}
總結(jié):
[1] 向HashMap中存儲(chǔ)元素時(shí),key一定要實(shí)現(xiàn)hashCode和equals
[2]?一般建議使用String作為Map接口的key
5.3linkedhashmap:LinkedHashMap是Map接口的實(shí)現(xiàn)類(lèi),key以LinkedHashSet存儲(chǔ)。
哈希表散列key,鏈表維持key的添加順序。
public?static?void?main(String[] args) {
/*LinkedHashMap<String, Object> map = new LinkedHashMap<String,Object>();
ArrayList<String> list2 = new ArrayList<String>();
list2.add("ben");
list2.add("bill");
map.put("B", list2);
ArrayList<String> list1 = new ArrayList<String>();
list1.add("alex");
list1.add("alice");
list1.add("allen");
map.put("A", list1);
System.out.println(map);*/
HashMap<Student, Object> map?= new?HashMap<Student,Object>();
ArrayList<String> list1?= new?ArrayList<String>();
list1.add("alex");
list1.add("alice");
list1.add("allen");
Student s1?= new?Student("001", "大狗", 20);
map.put(s1, list1);
ArrayList<String> list2?= new?ArrayList<String>();
list2.add("ben");
list2.add("bill");
Student s2?= new?Student("001", "大狗", 20);
//修改
map.put(s2, list2);
System.out.println(map);
}
5.4treemap:TreeMap是Map的實(shí)現(xiàn)類(lèi),key以TreeSet存儲(chǔ)。
public?static?void?main(String[] args) {
/*TreeMap<String, Object> map = new TreeMap<String,Object>(new Comparator<String>() {
@Override
public int?compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
ArrayList<String> list2 = new ArrayList<String>();
list2.add("ben");
list2.add("bill");
map.put("Aa", list2);
ArrayList<String> list1 = new ArrayList<String>();
list1.add("alex");
list1.add("alice");
list1.add("allen");
map.put("B", list1);
System.out.println(map);*/
TreeMap<Student, Object> map?= new?TreeMap<Student,Object>(new?Comparator<Student>() {
@Override
public?int?compare(Student o1, Student o2) {
return?o1.getAge() - o2.getAge();
}
});
ArrayList<String> list1?= new?ArrayList<String>();
list1.add("alex");
list1.add("alice");
list1.add("allen");
Student s1?= new?Student("001", "大狗", 20);
map.put(s1, list1);
ArrayList<String> list2?= new?ArrayList<String>();
list2.add("ben");
list2.add("bill");
Student s2?= new?Student("001", "2狗", 20);
//修改
map.put(s2, list2);
System.out.println(map);
}
0.總結(jié)

0.0:collection集合具有增:add,addall;刪:remove,removeall,clear,retainall;查:size,isempty,containsall,equals,iterator。它有兩種接口,一種是list接口,一種是set接口。list接口屬于元素可重復(fù),有序的,內(nèi)含增:add,addall;刪:remove;改:set;查:get,lastindexof,sublist。set接口元素唯一,無(wú)序。
list:
1.arraylist:底層數(shù)據(jù)結(jié)構(gòu)為數(shù)組。優(yōu)點(diǎn):遍歷元素和隨機(jī)訪問(wèn)元素的效率比較高;缺點(diǎn):添加和刪除需要大量移動(dòng)元素效率低,按照內(nèi)容查詢(xún)效率低。
2.linkedlist:底層數(shù)據(jù)結(jié)構(gòu)為鏈表,優(yōu)點(diǎn):摻入刪除元素的效率比較高;缺點(diǎn):? ?遍歷訪問(wèn)元素效率較為低下。
3.vector:底層數(shù)據(jù)結(jié)構(gòu)為數(shù)組。
set:
1.hashset:底層數(shù)據(jù)結(jié)構(gòu)為hash表,無(wú)序,存儲(chǔ)到hashset中的元素必須實(shí)現(xiàn)hashcode和equals來(lái)實(shí)現(xiàn)元素的散列和去重。
2.linkedhashset:底層數(shù)據(jù)結(jié)構(gòu)為哈希表加鏈表,插入順序,存儲(chǔ)到linkedhashset中的元素必須實(shí)現(xiàn)hashcode和equals來(lái)實(shí)現(xiàn)元素的散列和去重,linkedhashset通過(guò)鏈表來(lái)維持插入順序。
treeset:底層二叉樹(shù),升序,存儲(chǔ)在treeset中的元素必須comparable接口下的comparato用于比較排序并且可以去重,當(dāng)comparable接口不能滿(mǎn)足需求時(shí),可以通過(guò)comparator接口實(shí)現(xiàn)比較排序并去重。
