1.Collection接口
1.1介紹
英文名稱(chēng)Collection,是用來(lái)存放對(duì)象的數(shù)據(jù)結(jié)構(gòu)。其中長(zhǎng)度可變,而且集合中可以存放不同類(lèi)型的對(duì)象。并提供了一組操作成批對(duì)象的方法。
數(shù)組的缺點(diǎn):長(zhǎng)度是固定不可變的,訪問(wèn)方式單一,插入、刪除等操作繁瑣。
1.2 集合的繼承結(jié)構(gòu)

1.3 常用方法測(cè)試
package cn.tedu.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
//這個(gè)類(lèi)用來(lái)測(cè)試Collection接口
public class Test1_Collection {
public static void main(String[] args) {
//1,創(chuàng)建Collection接口對(duì)象
// Collection c = new Collection();//報(bào)錯(cuò),因?yàn)镃ollection是接口不能new
//a,<Integer>是泛型,用來(lái)約束集合中元素的類(lèi)型,只能寫(xiě)引用類(lèi)型不能是基本類(lèi)型
Collection<Integer> c = new ArrayList();
//2,常用方法
c.add(100);//添加元素
c.add(200);
c.add(300);
System.out.println(c);
// c.clear();//清空集合
System.out.println( c.contains(300) );//判斷集合是否包含指定元素
System.out.println( c.equals(100) );//判斷和100是否相等
System.out.println( c.hashCode() );//返回集合的哈希碼值
System.out.println( c.isEmpty() );//判斷集合是否為空
System.out.println( c.remove(200) );//判斷是否成功刪除集合中的元素
System.out.println( c.size() );//獲取集合的長(zhǎng)度/個(gè)數(shù)
Object[] os = c.toArray();//把集合的元素放入數(shù)組
System.out.println( Arrays.toString(os) );
//集合間的操作
Collection<Integer> c2 = new ArrayList();
c2.add(9);
c2.add(8);
c2.add(7);
c.addAll(c2);//把c2加到c里
System.outprintln( c.containsAll(c2) );//判斷c中是否包含c2
System.out.println( c.removeAll(c2) );//刪除c2
// System.out.println( c.retainAll(c2) );//刪除c
System.out.println(c);
//用來(lái) 遍歷/迭代 集合中的元素Iterator<E> iterator()
Iterator<Integer> it = c.iterator();
//通過(guò)Iterator迭代器,循環(huán)著獲取集合中的元素
while(it.hasNext()) {
//hasNext()用來(lái)判斷集合中是否有下個(gè)元素,有就返回true
Integer inte = it.next();//next()獲取迭代到的元素
System.out.println(inte);
}
}
}
2.List接口
2.1介紹
有序的 collection(也稱(chēng)為序列)。此接口的用戶(hù)可以對(duì)列表中每個(gè)元素的插入位置進(jìn)行精確地控制。用戶(hù)可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問(wèn)元素,并搜索列表中的元素。
2.2常用方法測(cè)試
package cn.tedu.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
//這個(gè)類(lèi)用測(cè)試List接口
public class Test2_List {
public static void main(String[] args) {
//1,創(chuàng)建List接口對(duì)象
List<String> list = new ArrayList();
//2,繼承自Collection接口的方法
list.add("jack");//添加元素
list.add("tony");
list.add("hanmeimei");
list.add("tony");
list.add("tony");
list.add("tony");
list.clear();//清空集合
System.out.println( list.contains("jack") );
System.out.println( list.equals("jack") );
System.out.println( list.hashCode() );
System.out.println( list.isEmpty() );
System.out.println( list.remove("hanmeimei") );
System.out.println( list.size() );
System.out.println( list.toArray() );//變成數(shù)組
//3,List接口的特有方法 -- 都是可以按照索引來(lái)操作的方式
list.add(1, "蔡徐坤");//在指定索引處添加指定的元素
System.out.println(list+"===");
System.out.println(list.get(2));//獲取下標(biāo)對(duì)應(yīng)的元素
System.out.println(list.indexOf("tony"));//獲取指定元素第一次出現(xiàn)的下標(biāo)
System.out.println(list.lastIndexOf("tony"));//獲取指定元素最后一次出現(xiàn)的下標(biāo)
System.out.println(list.remove(3));//按照下標(biāo)刪除指定元素
System.out.println(list.set(0,"xiongda"));//置換元素
List<String> subList = list.subList(2, 4);//截取下標(biāo)2-4的元素(含頭不含尾)
System.out.println(subList);
//TODO 集合間的操作
List<String> list2 = new ArrayList();
list2.add("1");
list2.add("2");
list2.add("3");
System.out.println( list.addAll(list2));//把list2加到list里
System.out.println( list.addAll(1, list2));//在指定下標(biāo)處添加元素
System.out.println( list.contains(list2));//判斷是否包含
System.out.println( list.removeAll(list2));//刪除list2
System.out.println( list.retainAll(list2));//刪除list
//TODO 集合的迭代 -- List集合的迭代方式有多種:
//iterator() listIterator() for() foreach
//方式1:由于List集合有下標(biāo),所以可以根據(jù)下標(biāo)遍歷數(shù)據(jù)
//i < list.size() 下標(biāo)最大值是集合長(zhǎng)度-1
for(int i = 0 ; i < list.size() ; i++) {
String s = list.get(i);//list.get(i)根據(jù)下標(biāo)獲取元素
System.out.println(s);
}
//方式2:普通for循環(huán)遍歷的效率低,可以用foreach提高,好處:語(yǔ)法簡(jiǎn)潔效率高 壞處:不能按照下標(biāo)獲取
//for(1 2:3){} -- 3是要遍歷的數(shù)據(jù) 1是遍歷得到的數(shù)據(jù)的類(lèi)型 2是變量名
for(String str:list) {
System.out.println(str);//str代表的是當(dāng)前遍歷到的數(shù)據(jù)
}
//方式3:iterator() 是繼承自父接口Collection的
Iterator<String> it = list.iterator();
while(it.hasNext()) {//hasNext()判讀是否有下一個(gè)元素
String str = it.next();//next()獲取元素
System.out.println(str);//打印獲取到的值
}
//方式4:listIterator() 是List接口的特有方法
//Iterator<E> iterator() --父接口 --hasNext() --next() --remove()
//ListIterator<E> listIterator() --子接口,擁有父接口的方法,也有自己的特有方法(逆向迭代)
//public interface ListIterator<E> extends Iterator<E>
ListIterator<String> it2 = list.listIterator();
while(it2.hasNext()) {//hasNext()判斷后面有沒(méi)有數(shù)據(jù)
String s = it2.next();//next()獲取后一個(gè)數(shù)據(jù)
System.out.println(s);//打印獲取到的數(shù)據(jù)
}
//總結(jié):方式3和方式4有什么區(qū)別?-- 3是父接口Iterator4是子接口ListIterator
//子接口擁有父接口的所有方法也有自己的特有方法,子接口的特有方法就是向前/逆向遍歷
}
}
3.ArrayList實(shí)現(xiàn)類(lèi)
3.1介紹
1.存在于java.util包中。
2.內(nèi)部用數(shù)組存放數(shù)據(jù),封裝了數(shù)組的操作,每個(gè)對(duì)象都有下標(biāo)。
3.內(nèi)部數(shù)組默認(rèn)初始容量是10,如果不夠會(huì)以1.5倍容量增長(zhǎng)。
4.查詢(xún)快,增刪數(shù)據(jù)效率會(huì)降低。
ArrayList的用法和List一樣只是創(chuàng)建對(duì)象時(shí)用的是:
ArrayList<Integer> list = new ArrayList<>();
4.LinkedList實(shí)現(xiàn)類(lèi)
4.1介紹
雙向鏈表,兩端效率高,下標(biāo)遍歷效率低,迭代器遍歷效率高。底層就是數(shù)組和鏈表實(shí)現(xiàn)的。

4.2常用方法測(cè)試
package cn.tedu.collection;
import java.util.LinkedList;
//這個(gè)類(lèi)用來(lái)測(cè)試LinkedList
public class Test4_LinkedList {
public static void main(String[] args) {
//1,創(chuàng)建對(duì)象
LinkedList<String> list = new LinkedList();
//2,常用方法
list.add("杰克");
list.add("肉絲");
list.add("凹凸曼");
list.add("蜘蛛俠");
System.out.println(list);
//3,LinkedList特有方法
list.addFirst("美隊(duì)");//添加首元素
list.addLast("鋼鐵俠");//添加尾元素
System.out.println(list);
System.out.println( list.getFirst());//獲取首元素
System.out.println( list.getLast());//獲取尾元素
System.out.println( list.removeFirst());//刪除首元素
System.out.println( list.removeLast());//刪除尾元素
}
}
5.Set接口
5.1介紹
一個(gè)不包含重復(fù)元素的 collection。數(shù)據(jù)無(wú)序(因?yàn)閟et集合沒(méi)有下標(biāo))。由于集合中的元素不可以重復(fù)。常用于給數(shù)據(jù)去重。HashSet:底層是哈希表。TreeSet:底層是TreeMap,也是紅黑樹(shù)的形式,便于查找數(shù)據(jù)。
5.2常用方法測(cè)試
package cn.tedu.collection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
//這個(gè)類(lèi)用來(lái)測(cè)試Set接口的用法
public class Test5_Set {
public static void main(String[] args) {
//1,創(chuàng)建Set對(duì)象
// Set set = new Set();//報(bào)錯(cuò),因?yàn)镾et是接口,不能new
Set<String> set = new HashSet();
//2,常用方法
set.add("jack");
set.add("rose");
set.add("tony");
set.add("hanmeimei");
set.add("tony");
set.add("null");
System.out.println(set);
set.clear();//清空集合
System.out.println(set.contains("tony"));//判斷set中是否包含元素
System.out.println(set.equals("tony"));//判斷set是否和tony相等
System.out.println(set.hashCode());//獲取set集合的哈希碼值
System.out.println(set.isEmpty());//判斷set集合是否為空
System.out.println(set.remove("null"));//刪除集合的指定元素
System.out.println(set.size());//獲取集合的長(zhǎng)度
Object[] obs = set.toArray();//把集合的元素放入數(shù)組中
System.out.println(Arrays.toString(obs));//查看數(shù)組里的元素值
//集合間的操作
Set<String> set2 = new HashSet();
set2.add("1");
set2.add("2");
set2.add("3");
System.out.println(set.addAll(set2));//把set2加入到set中
System.out.println(set.containsAll(set2));//判斷set中是否包含set2
System.out.println(set.removeAll(set2));//刪除set2
System.out.println(set.retainAll(set2));//刪除set
//集合的迭代Iterator<E> iterator()
Iterator<String> it = set.iterator();
while(it.hasNext()) {//判斷有沒(méi)有下一個(gè)元素
String s = it.next();//獲取元素
System.out.println(s);//打印獲取到的元素
}
}
}
6.HashSet實(shí)現(xiàn)類(lèi)
6.1介紹
底層是哈希表,包裝了HashMap,相當(dāng)于向HashSet中存入數(shù)據(jù)時(shí),會(huì)把數(shù)據(jù)作為K,存入內(nèi)部的HashMap中。其中,K不許重復(fù)。此類(lèi)允許使用 null 元素。
HashSet的方法用法和Set一樣只是創(chuàng)建對(duì)象時(shí)用的是:
HashSet<Integer> set = new HashSet();
7.Set給自定義對(duì)象去重
Set集合去重原理:Set集合去重主要是調(diào)用 add 方法時(shí),使用了 hashCode 方法和equals 方法,如果在 Set集合 中找不到與該元素 hashCode 值相同的元素,則說(shuō)明該元素是新元素,會(huì)被添加到 Set 集合中;如果兩個(gè)元素的 hashCode 值相同,并且使用 equals 方法比較后,返回值為 true,那么就說(shuō)明兩個(gè)元素相同,新元素不會(huì)被添加到 Set 集合中;如果 hashCode 值相同,但是 equals 方法比較后,返回值為 false ,則兩個(gè)元素不相同,新元素會(huì)被添加到 Set 集合中。
創(chuàng)建學(xué)生類(lèi)
package cn.tedu.collection;
//這個(gè)類(lèi)用來(lái)測(cè)試set給自定義對(duì)象去重
public class Student {
//提供構(gòu)造方法
public Student() {}
public Student(String name, int age, String addr) {
super();
this.name = name;
this.age = age;
this.addr = addr;
}
//提供私有屬性
private String name;
private int age;
private String addr;
//提供set()/get()方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
//重寫(xiě)toString()
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", addr=" + addr + "]";
}
//重寫(xiě)hashCode():想要根據(jù)兩個(gè)對(duì)象的屬性值計(jì)算哈希值,
//如果屬性值完全都一樣,就保證產(chǎn)生的hash值也一樣
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((addr == null) ? 0 : addr.hashCode());
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重寫(xiě)equals():要比較對(duì)象間的屬性值,如果屬性值都一樣,返回true
@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 (addr == null) {
if (other.addr != null)
return false;
} else if (!addr.equals(other.addr))
return false;
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;
}
}
測(cè)試
package cn.tedu.collection;
import java.util.HashSet;
import java.util.Set;
//這個(gè)類(lèi)用來(lái)給自定義對(duì)象去重
//總結(jié):
//1、如果你想用Set集合,給自定義對(duì)象去重,要求你在自己的類(lèi)中,同時(shí)提供重寫(xiě)的hashCode()和equals()
//--源碼摘抄:if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))
//重寫(xiě)的hashCode():我們不適用默認(rèn)的自動(dòng)計(jì)算出來(lái)的哈希值,而是要根據(jù)對(duì)象的屬性值計(jì)算,如果對(duì)象的屬性值都相同,那么請(qǐng)產(chǎn)生相同的哈希值
//重寫(xiě)的equals():我們要比較的不是對(duì)象的地址值,而是比較,兩個(gè)對(duì)象間如果屬性值都一樣就返回true
public class Test7_HashSet2 {
public static void main(String[] args) {
//1,創(chuàng)建Set集合對(duì)象
Set<Student> set = new HashSet<Student>();
//2,向set集合中添加自定義對(duì)象
Student s1 = new Student("tony",20,"BJ");
Student s2 = new Student("jack",10,"SH");
Student s3 = new Student("rose",30,"SH");
Student s4 = new Student("jack",10,"SH");
Student s5 = new Student("rose",30,"SH");
set.add(s1);
set.add(s2);
set.add(s3);
//重復(fù)的添加了屬性相同的對(duì)象,為什么沒(méi)有去重??
//1,保證對(duì)象擁有相同的哈希值??默認(rèn)使用的是Object提供的hashCode()計(jì)算的哈希值
//如果你想要根據(jù)兩個(gè)對(duì)象的屬性值計(jì)算哈希值,那就需要重寫(xiě)hashCode()
//2,是要保證兩個(gè)對(duì)象間的equals()返回true,那就需要重寫(xiě)equals()
set.add(s4);
set.add(s5);
System.out.println(set);
}
}