1.集合哼勇。
1.1傳統(tǒng)容器在進(jìn)行增都伪。刪等破壞性操作時(shí),需要移動(dòng)元素积担,可能導(dǎo)致性能問題陨晶,同時(shí)添加。刪除等算法和具體業(yè)務(wù)耦合在一起帝璧,增加了程序開發(fā)的復(fù)雜度先誉,Java集合框提供了一套性能優(yōu)良,使用方便的接口和類的烁。位于Java褐耳。util包。
1.2collection:他是Java集合框(collection - frame)中的頂層接口渴庆,這個(gè)接口是一個(gè)容器铃芦,容器中只能存儲(chǔ)引用數(shù)據(jù)類型? ??建議存同一類型的引用類型雅镊,方便后續(xù)遍歷等操作。容器中的元素可以是有序的刃滓、可重復(fù)的仁烹,稱為L(zhǎng)ist接口也可能是無序的、唯一的注盈,稱為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表示元素類型
// item表示迭代變量
// c1表示集合
for?(Object item?: c1) {
System.out.println(item.toString());
}
快速遍歷的本質(zhì):Collection繼承Iterable接口,表示集合支持快速遍歷胧砰。Iterable接口定義了一個(gè)方法iterator()用于獲取集合的迭代器鳍鸵,是一個(gè)Iterator接口類型,iterator()內(nèi)部返回一個(gè)實(shí)現(xiàn)類實(shí)現(xiàn)類Iterator接口尉间。這個(gè)實(shí)現(xiàn)類一定具有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表示元素類型
// 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接口中的元素通過索引(index)來確定元素的順序眠副。有序的collection(也稱為序列)画切。可以對(duì)列表中每個(gè)元素的插入位置進(jìn)行精確地控制囱怕。用戶可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問元素霍弹,并搜索列表中的元素
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ǔ)的方式不同耍缴,分為線性表、二叉樹挽霉、圖防嗡、棧、隊(duì)列等
線表性:線性表數(shù)據(jù)按照一定的邏輯順序存儲(chǔ)在內(nèi)存中炼吴。線性表是有序的本鸣。線性表根據(jù)內(nèi)存的物理結(jié)構(gòu)分為兩種:數(shù)組和鏈表。
數(shù)組是一種邏輯上有序的線性表硅蹦,物理上也連續(xù)荣德。
鏈表是一種邏輯上有序的線性表闷煤,但物理上不連續(xù)。
數(shù)組和鏈表的區(qū)別
相同點(diǎn)
不同點(diǎn)
數(shù)組在查詢時(shí)效率高涮瞻,在添加鲤拿、刪除元素時(shí)效率低(涉及移動(dòng)元素)
鏈表在查詢時(shí)效率低(每次從頭開始,不能跳躍訪問)署咽,在添加近顷、刪除元素時(shí)效率高(不涉及移動(dòng)元素)
1.7棧:特性:先進(jìn)后出,后進(jìn)先出
1.8隊(duì)列:特性:先進(jìn)先出
1.9:arraylist/vector:ArrayList是List接口的實(shí)現(xiàn)類宁否,底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組窒升,實(shí)現(xiàn)大小可變的數(shù)組。
ArrayList?線程不安全慕匠,jdk1.2
ArrayList?底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組饱须,默認(rèn)數(shù)組大小是10,如果添加的元素個(gè)數(shù)超過默認(rèn)容量,ArrayList會(huì)自動(dòng)拓容台谊,拓容原則:newCapacity = oldCapacity + oldCapacity / 2;
如果未來確定序列的元素不在增加蓉媳,通過調(diào)用trimToSize()調(diào)制容量至合適的空間。
ArrayList作為L(zhǎng)ist接口的實(shí)現(xiàn)類锅铅,常用方法和遍歷方法參考List接口酪呻。
Vector?是List接口的實(shí)現(xiàn)類,底層數(shù)據(jù)結(jié)構(gòu)也是數(shù)組盐须,也是大小可變的數(shù)組玩荠。
Vector是線程安全的,jdk1.0
Vector底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組丰歌,默認(rèn)數(shù)組大小是10,如果添加的元素個(gè)數(shù)超過默認(rèn)容量姨蟋,Vector會(huì)自動(dòng)拓容屉凯,拓容原則:newCapacity = oldCapacity +capacityIncrement(增長(zhǎng)因子);如果未來確定序列的元素不在增加立帖,通過調(diào)用trimToSize()調(diào)制容量至合適的空間。
注意:Vector在實(shí)現(xiàn)List接口的同時(shí)悠砚,同添加了自身特有的方法xxxElement,未來使用時(shí)為了程序的可拓展性晓勇,一定要按照接口來操作Vector。
1.10linkedlist:LinkedList是List接口的實(shí)現(xiàn)類灌旧,底層數(shù)據(jù)結(jié)構(gòu)是鏈表绑咱。
LinekList常用方法和遍歷方法參照List接口。
LinkedList線程不安全枢泰。
除了實(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在迭代過程中不允許向集合中添加元素
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)通過Iterator集合迭代器遍歷集合過程中,不能再向集合匯總添加元素衡蚂,否則出現(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.泛型:泛型允許開發(fā)者在強(qiáng)類型程序設(shè)計(jì)語言(java)編寫代碼時(shí)定義一些可變部分年叮,這些部分在使用前必須作出指明具被。泛型就是將類型參數(shù)化
ArrayList<E> ?list表示聲明了一個(gè)列表list,列表的元素是E類型
ArrayList<String> list = new ArrayList<String>();
聲明了一個(gè)列表list只损,列表的元素只能是String類型一姿。
泛型在編譯器起作用,運(yùn)行時(shí)jvm察覺不到泛型的存在跃惫。
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.泛型類:當(dāng)一個(gè)類中屬性的數(shù)據(jù)類型不確定時(shí),具體是什么類型由使用者來確定時(shí)爆存,使用泛型衬横。泛型類的形式”
public?class 類名<T>?{
}
定義一個(gè)泛型類
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ù)類型不確定時(shí),具體是什么類型由使用者來確定终蒂,可以考慮使用泛型方法蜂林。形式:
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í)確定(指明)類型。
泛型方法在一定程度上優(yōu)化了方法重載拇泣。
泛型方法可以定義多個(gè)泛型類型
//可以定義多個(gè)泛型的類型
public?<A,B> void?showInfo(A?a,B b) {
System.out.println(a);
System.out.println(b);
}
多個(gè)泛型類型進(jìn)一步優(yōu)化了方法重載噪叙。
多個(gè)同類型的泛型
//多個(gè)同類型的泛型
/*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是什么類型的數(shù)組由開發(fā)者調(diào)用處傳參決定。
stu.print(1);
stu.print(1,2);
stu.print("apple");
stu.print("apple","banana");
print(A...a) 方法稱為可變參數(shù)的泛型形式债朵。
3.泛型接口:如果接口中的方法的參數(shù)(形參子眶、返回值)不確定時(shí),可以考慮使用泛型接口序芦。形式
public interface FanInterface<T>?{
public void showInfo(T t);
}
[1]實(shí)現(xiàn)類能確定泛型接口的類型
public?class?ImplClass implements?FanInterface<String>{
@Override
public?void?showInfo(String?t) {
// TODO?Auto-generated method stub
}
}
[2]實(shí)現(xiàn)類不能確定泛型接口的類型->繼續(xù)泛臭杰。
public?class?ImplClass2<T> implements?FanInterface<T>{
@Override
public?void?showInfo(T t) {
}
}
4.泛型的上限和下限:泛型的上限ArrayList(? extends Pet) list 聲明了一個(gè)容器,容器中的元素類型一定要繼承于Pet谚中,我們稱這種形式叫做泛型的上限渴杆。泛型的下限ArrayList(? super Pet) list 聲明了一個(gè)容器,容器中的元素類型一定要是Pet的父類宪塔,我們稱這個(gè)形式為泛型的下限磁奖。
3.set接口:Set接口表示一個(gè)唯一、無序的容器(和添加順序無關(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]添加
//無序
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)類常見的有HashSet某筐、LinkedHashSet比搭、TreeSet
3.2hashset:
ashSet是Set接口的實(shí)現(xiàn)類,底層數(shù)據(jù)結(jié)構(gòu)是哈希表南誊。
HashSet是線程不安全的(不保證同步)
哈希表工作原理:
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):添加盗冷、刪除、查詢效率高;缺點(diǎn):無序
4.linkedhashset:LinkedHashSet是Set接口的實(shí)現(xiàn)類同廉,底層數(shù)據(jù)結(jié)構(gòu)哈希表+鏈表哈希表用于散列元素仪糖;鏈表用于維持添加順序。如果要添加自定義對(duì)象元素迫肖,也需要重寫hashCode和equals方法锅劝。
5.treeset:TreeSet 是Set接口的實(shí)現(xiàn)類,底層數(shù)據(jù)結(jié)構(gòu)是二叉樹蟆湖。TreeSet?存儲(chǔ)的數(shù)據(jù)按照一定的規(guī)則存儲(chǔ)故爵。存儲(chǔ)規(guī)則讓數(shù)據(jù)表現(xiàn)出自然順序。
5.1treeset的工作原理:
添加一個(gè)新元素t的存儲(chǔ)的步驟
[1]?如果集合無元素隅津,t直接加入诬垂;如果集合有元素,t和根節(jié)點(diǎn)比較伦仍;
[2] 如果t小于根節(jié)點(diǎn)结窘;把t放到根節(jié)點(diǎn)的左子樹上;重復(fù)1-3步驟
[3] t大于根節(jié)點(diǎn)充蓝;把t放到根節(jié)點(diǎn)的右子樹上隧枫;重復(fù)1-3步驟
輸出時(shí)按照一定的規(guī)則:左子樹->根節(jié)點(diǎn)->右子樹
根據(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í)卑笨,通過指定具體的比較策略,此時(shí)稱為內(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ì)象寫在前面,待比較對(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í)際開發(fā)過程中不知道添加元素的源代碼近迁、無權(quán)修改別人的代碼,此時(shí)可以使用外部比較器簸州。Comparator?位于java.util包中鉴竭,定義了compare(o1,o2)用于提供外部比較策略歧譬。TreeSet接受一個(gè)指定比較策略的構(gòu)造方法,這些比較策略的實(shí)現(xiàn)類必須實(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)部類優(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接口稱為鍵值對(duì)集合或者映射集合瑰步,其中的元素(entry)是以鍵值對(duì)(key-value)的形式存在。Map?容器接口中提供了增璧眠、刪缩焦、改、查的方式對(duì)集合進(jìn)行操作责静。Map接口中都是通過key來操作鍵值對(duì)袁滥,一般key是已知。通過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的接口遍歷:
通過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無序
//可以根據(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中稱為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無序
//可以根據(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)類HashMap、LinkedHashMap熄赡、TreeMap
5.2hashmap:HashMap?是Map的實(shí)現(xiàn)類猾普,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)類初家,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)類溜在,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接口元素唯一芙粱,無序。
list:
1.arraylist:底層數(shù)據(jù)結(jié)構(gòu)為數(shù)組氧映。優(yōu)點(diǎn):遍歷元素和隨機(jī)訪問元素的效率比較高春畔;缺點(diǎn):添加和刪除需要大量移動(dòng)元素效率低,按照內(nèi)容查詢效率低岛都。
2.linkedlist:底層數(shù)據(jù)結(jié)構(gòu)為鏈表律姨,優(yōu)點(diǎn):摻入刪除元素的效率比較高;缺點(diǎn):? ?遍歷訪問元素效率較為低下臼疫。
3.vector:底層數(shù)據(jù)結(jié)構(gòu)為數(shù)組择份。
set:
1.hashset:底層數(shù)據(jù)結(jié)構(gòu)為hash表,無序烫堤,存儲(chǔ)到hashset中的元素必須實(shí)現(xiàn)hashcode和equals來實(shí)現(xiàn)元素的散列和去重荣赶。
2.linkedhashset:底層數(shù)據(jù)結(jié)構(gòu)為哈希表加鏈表,插入順序鸽斟,存儲(chǔ)到linkedhashset中的元素必須實(shí)現(xiàn)hashcode和equals來實(shí)現(xiàn)元素的散列和去重拔创,linkedhashset通過鏈表來維持插入順序。
treeset:底層二叉樹富蓄,升序剩燥,存儲(chǔ)在treeset中的元素必須comparable接口下的comparato用于比較排序并且可以去重,當(dāng)comparable接口不能滿足需求時(shí)立倍,可以通過comparator接口實(shí)現(xiàn)比較排序并去重灭红。