今天在看了好多個(gè)集合帖子后發(fā)現(xiàn)講的都是一半一半的,這下就逼死我這個(gè)強(qiáng)迫癥患者了.于是自己寫(xiě)點(diǎn),有不足之處還望各位道友多多指點(diǎn)
一、Collection接口
1.Collection接口
1.java.util.Collection接口:
1.所有單列集合的最頂層的接口,里邊定義了所有單列集合共性的方法
2.任意的單列集合都可以使用Collection接口中的方法
共性的方法:
public boolean add(E e): 把給定的對(duì)象添加到當(dāng)前集合中 。
public void clear() :清空集合中所有的元素悔耘。
public boolean remove(E e): 把給定的對(duì)象在當(dāng)前集合中刪除扛吞。
public boolean contains(E e): 判斷當(dāng)前集合中是否包含給定的對(duì)象伊约。
public boolean isEmpty(): 判斷當(dāng)前集合是否為空撕瞧。
public int size(): 返回集合中元素的個(gè)數(shù)尤蛮。
public Object[] toArray(): 把集合中的元素县匠,存儲(chǔ)到數(shù)組中风科。
示例
public class Collection {
public static void main(String[] args) {
//創(chuàng)建集合對(duì)象,可以使用多態(tài)
//Collection<String> coll = new ArrayList<>();
Collection<String> coll = new HashSet<>();
System.out.println(coll);//重寫(xiě)了toString方法 []
?
/*
public boolean add(E e):把給定的對(duì)象添加到當(dāng)前集合中 。
返回值是一個(gè)boolean值,一般都返回true,所以可以不用接收
*/
boolean b1 = coll.add("張三");
System.out.println("b1:"+b1);//b1:true
System.out.println(coll);//[張三]
coll.add("李四");
coll.add("李四");
coll.add("趙六");
coll.add("田七");
System.out.println(coll);//[張三, 李四, 趙六, 田七]
?
/*
public boolean remove(E e): 把給定的對(duì)象在當(dāng)前集合中刪除乞旦。
返回值是一個(gè)boolean值,集合中存在元素,刪除元素,返回true
集合中不存在元素,刪除失敗,返回false
*/
boolean b2 = coll.remove("趙六");
System.out.println("b2:"+b2);//b2:true
?
boolean b3 = coll.remove("趙四");
System.out.println("b3:"+b3);//b3:false
System.out.println(coll);//[張三, 李四, 田七]
?
/*
public boolean contains(E e): 判斷當(dāng)前集合中是否包含給定的對(duì)象丐重。
包含返回true
不包含返回false
*/
boolean b4 = coll.contains("李四");
System.out.println("b4:"+b4);//b4:true
?
boolean b5 = coll.contains("趙四");
System.out.println("b5:"+b5);//b5:false
?
//public boolean isEmpty(): 判斷當(dāng)前集合是否為空。集合為空返回true,集合不為空返回false
boolean b6 = coll.isEmpty();
System.out.println("b6:"+b6);//b6:false
?
//public int size(): 返回集合中元素的個(gè)數(shù)杆查。
int size = coll.size();
System.out.println("size:"+size);//size:3
?
//public Object[] toArray(): 把集合中的元素扮惦,存儲(chǔ)到數(shù)組中。
Object[] arr = coll.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
?
//public void clear() :清空集合中所有的元素亲桦。但是不刪除集合,集合還存在
coll.clear();
System.out.println(coll);//[]
System.out.println(coll.isEmpty());//true
}
}
2.Collection工具類(lèi)
java.utils.Collections是集合工具類(lèi)崖蜜,用來(lái)對(duì)集合進(jìn)行操作。部分方法如下:
public static <T> boolean addAll(Collection<T> c, T...
elements):往集合中添加一些元素客峭。
public static void shuffle(List<?> list) :打亂順序:打亂集合順序豫领。
示例
?public class Collections {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//往集合中添加多個(gè)元素
/*list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");*/
?
//public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
Collections.addAll(list,"a","b","c","d","e");
?
System.out.println(list);//[a, b, c, d, e]
?
//public static void shuffle(List<?> list) 打亂順序:打亂集合順序舔琅。
Collections.shuffle(list);
System.out.println(list);//[b, d, c, a, e], [b, d, c, a, e]
}
}
public static void sort(List list):將集合中元素按照默認(rèn)規(guī)則排序等恐。
注意:
sort(List list)使用前提:
被排序的集合里邊存儲(chǔ)的元素,必須實(shí)現(xiàn)Comparable,重寫(xiě)接口中的方法compareTo定義排序的規(guī)則
?
public class Sort {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(3);
list01.add(2);
System.out.println(list01);//[1, 3, 2]
?
//public static <T> void sort(List<T> list):將集合中元素按照默認(rèn)規(guī)則排序。
Collections.sort(list01);//默認(rèn)是升序
?
System.out.println(list01);//[1, 2, 3]
?
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("c");
list02.add("b");
System.out.println(list02);//[a, c, b]
?
Collections.sort(list02);
System.out.println(list02);//[a, b, c]
?
ArrayList<Person> list03 = new ArrayList<>();
list03.add(new Person("張三",18));
list03.add(new Person("李四",20));
list03.add(new Person("王五",15));
System.out.println(list03);//[Person{name='張三', age=18}, Person{name='李四', age=20}, Person{name='王五', age=15}]
?
Collections.sort(list03);
System.out.println(list03);
}
}
Comparator和Comparable的區(qū)別
Comparable:自己(this)和別人(參數(shù))比較,自己需要實(shí)現(xiàn)Comparable接口,重寫(xiě)比較的規(guī)則compareTo方法
Comparator:相當(dāng)于找一個(gè)第三方的裁判,比較兩個(gè)
Comparable接口位于java.lang包下备蚓;Comparator位于java.util包下 Comparable接口只提供了一個(gè)compareTo()方法课蔬;Comparator接口不僅提供了compara()方法,還提供了其他默認(rèn)方法郊尝,如reversed()二跋、thenComparing(),使我們可以按照更多的方式進(jìn)行排序如果要用Comparable接口流昏,則必須實(shí)現(xiàn)這個(gè)接口扎即,并重寫(xiě)comparaTo()方法吞获;但是Comparator接口可以在類(lèi)外部使用,通過(guò)將該接口的一個(gè)匿名類(lèi)對(duì)象當(dāng)做參數(shù)傳遞給Collections.sort()方法或者Arrays.sort()方法實(shí)現(xiàn)排序谚鄙。Comparator體現(xiàn)了一種策略模式各拷,即可以不用要把比較方法嵌入到類(lèi)中,而是可以單獨(dú)在類(lèi)外部使用闷营,這樣我們就可有不用改變類(lèi)本身的代碼而實(shí)現(xiàn)對(duì)類(lèi)對(duì)象進(jìn)行排序烤黍。
Comparator的排序規(guī)則:
o1-o2:升序
public class Sort2 {
public static void main(String[] args) {
? ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(3);
list01.add(2);
System.out.println(list01);//[1, 3, 2]
?
Collections.sort(list01, new Comparator<Integer>() {
//重寫(xiě)比較的規(guī)則
@Override
public int compare(Integer o1, Integer o2) {
//return o1-o2;//升序
return o2-o1;//降序
}
});
?
System.out.println(list01);
?
ArrayList<Student> list02 = new ArrayList<>();
list02.add(new Student("李志",18));
list02.add(new Student("李德軒",20));
list02.add(new Student("方永泰",17));
list02.add(new Student("段睿新",18));
System.out.println(list02);
?
/*Collections.sort(list02, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//按照年齡升序排序
return o1.getAge()-o2.getAge();
}
});*/
?
//擴(kuò)展:了解
Collections.sort(list02, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//按照年齡升序排序
int result = o1.getAge()-o2.getAge();
//如果兩個(gè)人年齡相同,再使用姓名的第一個(gè)字比較
if(result==0){
result = o1.getName().charAt(0)-o2.getName().charAt(0);
}
return result;
}
?
});
?
System.out.println(list02);
}
}
public class Person implements Comparable<Person>{
private String name;
private int age; ?
public Person() {
} ?
public Person(String name, int age) {
this.name = name;
this.age = age;
} ?
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
} ?
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;
} ?
//重寫(xiě)排序的規(guī)則
@Override
public int compareTo(Person o) {
//return 0;//認(rèn)為元素都是相同的
//自定義比較的規(guī)則,比較兩個(gè)人的年齡(this,參數(shù)Person)
//return this.getAge() - o.getAge();//年齡升序排序
return o.getAge() - this.getAge();//年齡升序排序
} }
public class Student {
private String name;
private int age;
?
public Student() {
}
?
public Student(String name, int age) {
this.name = name;
this.age = age;
}
?
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
?
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;
}
}
二、Iterator迭代器粮坞、增強(qiáng)for循環(huán)蚊荣、泛型
1.Iterator迭代器
java.util.Iterator接口:迭代器(對(duì)集合進(jìn)行遍歷)
常用的方法
boolean hasNext() 如果仍有元素可以迭代,則返回 true莫杈。
判斷集合中還有沒(méi)有下一個(gè)元素,有就返回true,沒(méi)有就返回false E next() 返回迭代的下一個(gè)元素互例。取出集合中的下一個(gè)元素
**注意:**
Iterator迭代器,是一個(gè)接口,我們無(wú)法直接使用,需要使用Iterator接口的實(shí)現(xiàn)類(lèi)對(duì)象,獲取實(shí)現(xiàn)類(lèi)的方式比較特殊
Collection接口中有一個(gè)方法,叫iterator(),這個(gè)方法返回的就是迭代器的實(shí)現(xiàn)類(lèi)對(duì)象
Iterator<E> iterator() 返回在此 collection 的元素上進(jìn)行迭代的迭代器
迭代器的使用步驟(重點(diǎn)):
1.使用集合中的方法iterator()獲取迭代器的實(shí)現(xiàn)類(lèi)對(duì)象,使用Iterator接口接收(多態(tài))
2.使用Iterator接口中的方法hasNext判斷還有沒(méi)有下一個(gè)元素
3.使用Iterator接口中的方法next取出集合中的下一個(gè)元素
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
?
public class Iterator {
public static void main(String[] args) {
//創(chuàng)建一個(gè)集合對(duì)象
Collection<String> coll = new ArrayList<>();
//往集合中添加元素
coll.add("姚明");
coll.add("科比");
coll.add("麥迪");
coll.add("詹姆斯");
coll.add("艾弗森");
?
/*
1.使用集合中的方法iterator()獲取迭代器的實(shí)現(xiàn)類(lèi)對(duì)象,使用Iterator接口接收(多態(tài))
注意:
Iterator<E>接口也是有泛型的,迭代器的泛型跟著集合走,集合是什么泛型,迭代器就是什么泛型
*/
//多態(tài) 接口 實(shí)現(xiàn)類(lèi)對(duì)象
Iterator<String> it = coll.iterator();
?
?
/*
發(fā)現(xiàn)使用迭代器取出集合中元素的代碼,是一個(gè)重復(fù)的過(guò)程
所以我們可以使用循環(huán)優(yōu)化
不知道集合中有多少元素,使用while循環(huán)
循環(huán)結(jié)束的條件,hasNext方法返回false
*/
while(it.hasNext()){
String e = it.next();
System.out.println(e);
}
System.out.println("----------------------");
for(Iterator<String> it2 = coll.iterator();it2.hasNext();){
String e = it2.next();
System.out.println(e);
}
?
?
/* //2.使用Iterator接口中的方法hasNext判斷還有沒(méi)有下一個(gè)元素
boolean b = it.hasNext();
System.out.println(b);//true
//3.使用Iterator接口中的方法next取出集合中的下一個(gè)元素
String s = it.next();
System.out.println(s);//姚明
?
b = it.hasNext();
System.out.println(b);
s = it.next();
System.out.println(s);
?
b = it.hasNext();
System.out.println(b);
s = it.next();
System.out.println(s);
?
b = it.hasNext();
System.out.println(b);
s = it.next();
System.out.println(s);
b = it.hasNext();
System.out.println(b);
s = it.next();
System.out.println(s);
?
b = it.hasNext();
System.out.println(b);//沒(méi)有元素,返回false
s = it.next();//沒(méi)有元素,在取出元素會(huì)拋出NoSuchElementException沒(méi)有元素異常
System.out.println(s);*/
}
}
2.增強(qiáng)for循環(huán)
增強(qiáng)for循環(huán):底層使用的也是迭代器,使用for循環(huán)的格式,簡(jiǎn)化了迭代器的書(shū)寫(xiě) 是JDK1.5之后出現(xiàn)的新特性
Collectionextends Iterable:所有的單列集合都可以使用增強(qiáng)for public interface
Iterable實(shí)現(xiàn)這個(gè)接口允許對(duì)象成為 “foreach” 語(yǔ)句的目標(biāo)。
增強(qiáng)for循環(huán):用來(lái)遍歷集合和數(shù)組 格式:
for(集合/數(shù)組的數(shù)據(jù)類(lèi)型 變量名: 集合名/數(shù)組名){ sout(變量名); }
import java.util.ArrayList;
public class Foreach {
public static void main(String[] args) {
demo02();
}
?
//使用增強(qiáng)for循環(huán)遍歷集合
private static void demo02() {
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
for(String s : list){
System.out.println(s);
}
}
?
//使用增強(qiáng)for循環(huán)遍歷數(shù)組
private static void demo01() {
int[] arr = {1,2,3,4,5};
for(int i:arr){
System.out.println(i);
}
}
}
3.泛型
import java.util.ArrayList;
import java.util.Iterator;
?
public class Generic {
public static void main(String[] args) {
show02();
}
?
/*
創(chuàng)建集合對(duì)象,使用泛型
好處:
1.避免了類(lèi)型轉(zhuǎn)換的麻煩,存儲(chǔ)的是什么類(lèi)型,取出的就是什么類(lèi)型
2.把運(yùn)行期異常(代碼運(yùn)行之后會(huì)拋出的異常),提升到了編譯期(寫(xiě)代碼的時(shí)候會(huì)報(bào)錯(cuò))
弊端:
泛型是什么類(lèi)型,只能存儲(chǔ)什么類(lèi)型的數(shù)據(jù)
*/
private static void show02() {
ArrayList<String> list = new ArrayList<>();
list.add("abc");
//list.add(1);//add(java.lang.String)in ArrayList cannot be applied to (int)
?
//使用迭代器遍歷list集合
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s+"->"+s.length());
}
}
?
/*
創(chuàng)建集合對(duì)象,不使用泛型
好處:
集合不使用泛型,默認(rèn)的類(lèi)型就是Object類(lèi)型,可以存儲(chǔ)任意類(lèi)型的數(shù)據(jù)
弊端:
不安全,會(huì)引發(fā)異常
*/
private static void show01() {
ArrayList list = new ArrayList();
list.add("abc");
list.add(1);
?
//使用迭代器遍歷list集合
//獲取迭代器
Iterator it = list.iterator();
//使用迭代器中的方法hasNext和next遍歷集合
while(it.hasNext()){
//取出元素也是Object類(lèi)型
Object obj = it.next();
System.out.println(obj);
?
//想要使用String類(lèi)特有的方法,length獲取字符串的長(zhǎng)度;不能使用 多態(tài) Object obj = "abc";
//需要向下轉(zhuǎn)型
//會(huì)拋出ClassCastException類(lèi)型轉(zhuǎn)換異常,不能把Integer類(lèi)型轉(zhuǎn)換為String類(lèi)型
String s = (String)obj;
System.out.println(s.length());
}
}
}
①定義含有泛型的類(lèi)
模擬ArrayList集合
泛型是一個(gè)未知的數(shù)據(jù)類(lèi)型,當(dāng)我們不確定什么什么數(shù)據(jù)類(lèi)型的時(shí)候,可以使用泛型
泛型可以接收任意的數(shù)據(jù)類(lèi)型,可以使用Integer,String,Student... 創(chuàng)建對(duì)象的時(shí)候確定泛型的數(shù)據(jù)類(lèi)型
public class GenericClass<E> {
private E name;
?
public E getName() {
return name;
}
?
public void setName(E name) {
this.name = name;
}
}
public class GenericClass {
public static void main(String[] args) {
//不寫(xiě)泛型默認(rèn)為Object類(lèi)型
GenericClass gc = new GenericClass();
gc.setName("只能是字符串");
Object obj = gc.getName(); ?
//創(chuàng)建GenericClass對(duì)象,泛型使用Integer類(lèi)型
GenericClass<Integer> gc2 = new GenericClass<>();
gc2.setName(1); ?
Integer name = gc2.getName();
System.out.println(name); ?
//創(chuàng)建GenericClass對(duì)象,泛型使用String類(lèi)型
GenericClass<String> gc3 = new GenericClass<>();
gc3.setName("小明");
String name1 = gc3.getName();
System.out.println(name1);
} }
②定義含有泛型的方法
泛型定義在方法的修飾符和返回值類(lèi)型之間
格式:
修飾符 <泛型> 返回值類(lèi)型 方法名(參數(shù)列表(使用泛型)){
方法體;
}含有泛型的方法,在調(diào)用方法的時(shí)候確定泛型的數(shù)據(jù)類(lèi)型 傳遞什么類(lèi)型的參數(shù),泛型就是什么類(lèi)型
public class GenericMethod {
//定義一個(gè)含有泛型的方法
public <M> void method01(M m){
System.out.println(m);
}
?
//定義一個(gè)含有泛型的靜態(tài)方法
public static <S> void method02(S s){
System.out.println(s);
}
}
測(cè)試含有泛型的方法
public class DemoGenericMethod {
public static void main(String[] args) {
//創(chuàng)建GenericMethod對(duì)象
GenericMethod gm = new GenericMethod();
/*
調(diào)用含有泛型的方法method01
傳遞什么類(lèi)型,泛型就是什么類(lèi)型
*/
gm.method01(10);
gm.method01("abc");
gm.method01(8.8);
gm.method01(true);
gm.method02("靜態(tài)方法,不建議創(chuàng)建對(duì)象使用");
//靜態(tài)方法,通過(guò)類(lèi)名.方法名(參數(shù))可以直接使用
GenericMethod.method02("靜態(tài)方法");
GenericMethod.method02(1);
}
}
定義含有泛型的接口
public interface GenericInterface<I> {
public abstract void method(I i);
}
③定義含有泛型的接口的實(shí)現(xiàn)類(lèi)
含有泛型的接口,第一種使用方式:定義接口的實(shí)現(xiàn)類(lèi),實(shí)現(xiàn)接口,指定接口的泛型 public interface Iterator<E> {
E next(); } Scanner類(lèi)實(shí)現(xiàn)了Iterator接口,并指定接口的泛型為String,所以重寫(xiě)的next方法泛型默認(rèn)就是String
public final class Scanner implements Iterator<String>{
public String next() {}
}
public class GenericInterfaceImpl1 implements GenericInterface<String>{
@Override
public void method(String s) {
System.out.println(s);
}
}
含有泛型的接口第二種使用方式:接口使用什么泛型,實(shí)現(xiàn)類(lèi)就使用什么泛型,類(lèi)跟著接口走
就相當(dāng)于定義了一個(gè)含有泛型的類(lèi),創(chuàng)建對(duì)象的時(shí)候確定泛型的類(lèi)型
public interface List<E>{
boolean add(E e);
E get(int index);
}
public class ArrayList<E> implements List<E>{
public boolean add(E e) {}
public E get(int index) {}
}
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
測(cè)試含有泛型的接口
public class Demo04GenericInterface {
public static void main(String[] args) {
//創(chuàng)建GenericInterfaceImpl1對(duì)象
GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
gi1.method("字符串");
?
//創(chuàng)建GenericInterfaceImpl2對(duì)象
GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
gi2.method(10);
?
GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();
gi3.method(8.8);
}
}
④泛型標(biāo)識(shí)符
泛型的通配符:
?:代表任意的數(shù)據(jù)類(lèi)型 使用方式:
不能創(chuàng)建對(duì)象使用
只能作為方法的參數(shù)使用 泛型的上限限定: ? extends E 代表使用的泛型只能是E類(lèi)型的子類(lèi)/本身 泛型的下限限定: ? super E 代表使用的泛型只能是E類(lèi)型的父類(lèi)/本身
public class Demo05Generic {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
?
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("b");
?
printArray(list01);
printArray(list02);
?
//ArrayList<?> list03 = new ArrayList<?>();
}
?
/*
定義一個(gè)方法,能遍歷所有類(lèi)型的ArrayList集合
這時(shí)候我們不知道ArrayList集合使用什么數(shù)據(jù)類(lèi)型,可以泛型的通配符?來(lái)接收數(shù)據(jù)類(lèi)型
注意:
泛型沒(méi)有繼承概念的
*/
public static void printArray(ArrayList<?> list){
//使用迭代器遍歷集合
Iterator<?> it = list.iterator();
while(it.hasNext()){
//it.next()方法,取出的元素是Object,可以接收任意的數(shù)據(jù)類(lèi)型
Object o = it.next();
System.out.println(o);
}
}
}
import java.util.ArrayList;
import java.util.Collection;
?
/*
泛型的上限限定: ? extends E 代表使用的泛型只能是E類(lèi)型的子類(lèi)/本身
泛型的下限限定: ? super E 代表使用的泛型只能是E類(lèi)型的父類(lèi)/本身
*/
public class Demo06Generic {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
?
getElement1(list1);
//getElement1(list2);//報(bào)錯(cuò)
getElement1(list3);
//getElement1(list4);//報(bào)錯(cuò)
?
//getElement2(list1);//報(bào)錯(cuò)
//getElement2(list2);//報(bào)錯(cuò)
getElement2(list3);
getElement2(list4);
?
/*
類(lèi)與類(lèi)之間的繼承關(guān)系
Integer extends Number extends Object
String extends Object
*/
?
}
// 泛型的上限:此時(shí)的泛型?筝闹,必須是Number類(lèi)型或者Number類(lèi)型的子類(lèi)
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此時(shí)的泛型?媳叨,必須是Number類(lèi)型或者Number類(lèi)型的父類(lèi)
public static void getElement2(Collection<? super Number> coll){}
}
三、幾種數(shù)據(jù)結(jié)構(gòu)的簡(jiǎn)單圖解
四关顷、幾種集合的介紹與使用方法
1.List集合
①ArrayList集合
java.util.List接口 extends Collection接口
List接口的特點(diǎn):
1.有序的集合,存儲(chǔ)元素和取出元素的順序是一致的(存儲(chǔ)123 取出123)
2.有索引,包含了一些帶索引的方法
?3.允許存儲(chǔ)重復(fù)的元素
List接口中帶索引的方法(特有)
- public void add(int index, E element): 將指定的元素糊秆,添加到該集合中的指定位置上。
- public E get(int index):返回集合中指定位置的元素议双。
- public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素痘番。
- public E set(int index, E element):用指定元素替換集合中指定位置的元素,返回值的更新前的元素。
注意:
操作索引的時(shí)候,一定要防止索引越界異常
IndexOutOfBoundsException:索引越界異常,集合會(huì)報(bào)
ArrayIndexOutOfBoundsException:數(shù)組索引越界異常
StringIndexOutOfBoundsException:字符串索引越界異常
public class List {
public static void main(String[] args) {
//創(chuàng)建一個(gè)List集合對(duì)象,多態(tài)
List<String> list = new ArrayList<>();
//使用add方法往集合中添加元素
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("a");
//打印集合
System.out.println(list);//[a, b, c, d, a] 不是地址重寫(xiě)了toString
?
//public void add(int index, E element): 將指定的元素平痰,添加到該集合中的指定位置上汞舱。
//在c和d之間添加一個(gè)itheima
list.add(3,"itheima");//[a, b, c, itheima, d, a]
System.out.println(list);
?
//public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
//移除元素
String removeE = list.remove(2);
System.out.println("被移除的元素:"+removeE);//被移除的元素:c
System.out.println(list);//[a, b, itheima, d, a]
?
//public E set(int index, E element):用指定元素替換集合中指定位置的元素,返回值的更新前的元素宗雇。
//把最后一個(gè)a,替換為A
String setE = list.set(4, "A");
System.out.println("被替換的元素:"+setE);//被替換的元素:a
System.out.println(list);//[a, b, itheima, d, A]
?
//List集合遍歷有3種方式
//使用普通的for循環(huán)
for(int i=0; i<list.size(); i++){
//public E get(int index):返回集合中指定位置的元素昂芜。
String s = list.get(i);
System.out.println(s);
}
System.out.println("-----------------");
//使用迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("-----------------");
//使用增強(qiáng)for
for (String s : list) {
System.out.println(s);
}
?
String r = list.get(5);//IndexOutOfBoundsException: Index 5 out-of-bounds for length 5
System.out.println(r);
?
}
}
②LinkedList集合
java.util.LinkedList集合 implements List接口
LinkedList集合的特點(diǎn):
1.底層是一個(gè)鏈表結(jié)構(gòu):查詢(xún)慢,增刪快
2.里邊包含了大量操作首尾元素的方法
注意:使用LinkedList集合特有的方法,不能使用多態(tài)
public void addFirst(E e):將指定元素插入此列表的開(kāi)頭。
public void addLast(E e):將指定元素添加到此列表的結(jié)尾赔蒲。
public void push(E e):將元素推入此列表所表示的堆棧泌神。
public E getFirst():返回此列表的第一個(gè)元素。
public E getLast():返回此列表的最后一個(gè)元素舞虱。
public E removeFirst():移除并返回此列表的第一個(gè)元素欢际。
public E removeLast():移除并返回此列表的最后一個(gè)元素。
public E pop():從此列表所表示的堆棧處彈出一個(gè)元素砾嫉。
public boolean isEmpty():如果列表不包含元素幼苛,則返回true。
public class LinkedList {
public static void main(String[] args) {
show03();
}
?
/*
- public E removeFirst():移除并返回此列表的第一個(gè)元素焕刮。
- public E removeLast():移除并返回此列表的最后一個(gè)元素舶沿。
- public E pop():從此列表所表示的堆棧處彈出一個(gè)元素。此方法相當(dāng)于 removeFirst
*/
private static void show03() {
//創(chuàng)建LinkedList集合對(duì)象
LinkedList<String> linked = new LinkedList<>();
//使用add方法往集合中添加元素
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println(linked);//[a, b, c]
?
//String first = linked.removeFirst();
String first = linked.pop();
System.out.println("被移除的第一個(gè)元素:"+first);
String last = linked.removeLast();
System.out.println("被移除的最后一個(gè)元素:"+last);
System.out.println(linked);//[b]
}
?
/*
- public E getFirst():返回此列表的第一個(gè)元素配并。
- public E getLast():返回此列表的最后一個(gè)元素括荡。
*/
private static void show02() {
//創(chuàng)建LinkedList集合對(duì)象
LinkedList<String> linked = new LinkedList<>();
//使用add方法往集合中添加元素
linked.add("a");
linked.add("b");
linked.add("c");
?
//linked.clear();//清空集合中的元素 在獲取集合中的元素會(huì)拋出NoSuchElementException
?
//public boolean isEmpty():如果列表不包含元素,則返回true溉旋。
if(!linked.isEmpty()){
String first = linked.getFirst();
System.out.println(first);//a
String last = linked.getLast();
System.out.println(last);//c
}
}
?
/*
- public void addFirst(E e):將指定元素插入此列表的開(kāi)頭畸冲。
- public void addLast(E e):將指定元素添加到此列表的結(jié)尾。
- public void push(E e):將元素推入此列表所表示的堆棧观腊。此方法等效于 addFirst(E)邑闲。
*/
private static void show01() {
//創(chuàng)建LinkedList集合對(duì)象
LinkedList<String> linked = new LinkedList<>();
//使用add方法往集合中添加元素
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println(linked);//[a, b, c]
?
//public void addFirst(E e):將指定元素插入此列表的開(kāi)頭。
//linked.addFirst("www");
linked.push("www");
System.out.println(linked);//[www, a, b, c]
?
//public void addLast(E e):將指定元素添加到此列表的結(jié)尾梧油。此方法等效于 add()
linked.addLast("com");
System.out.println(linked);//[www, a, b, c, com]
}
}
2.Set集合
①Set集合
java.util.Set接口 extends Collection接口
Set接口的特點(diǎn):
1.不允許存儲(chǔ)重復(fù)的元素
2.沒(méi)有索引,沒(méi)有帶索引的方法,也不能使用普通的for循環(huán)遍歷
java.util.HashSet集合 implements Set接口
HashSet特點(diǎn):
1.不允許存儲(chǔ)重復(fù)的元素 2.沒(méi)有索引,沒(méi)有帶索引的方法,也不能使用普通的for循環(huán)遍歷 3.是一個(gè)無(wú)序的集合,存儲(chǔ)元素和取出元素的順序有可能不一致 4.底層是一個(gè)哈希表結(jié)構(gòu)(查詢(xún)的速度非常的快)
public class Set {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
//使用add方法往集合中添加元素
set.add(1);
set.add(3);
set.add(2);
set.add(1);
//使用迭代器遍歷set集合
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer n = it.next();
System.out.println(n);//1,2,3
}
//使用增強(qiáng)for遍歷set集合
System.out.println("-----------------");
for (Integer i : set) {
System.out.println(i);
}
}
}
②哈希值
哈希值:是一個(gè)十進(jìn)制的整數(shù),由系統(tǒng)隨機(jī)給出(就是對(duì)象的地址值,是一個(gè)邏輯地址,是模擬出來(lái)得到地址,不是數(shù)據(jù)實(shí)際存儲(chǔ)的物理地址)
在Object類(lèi)有一個(gè)方法,可以獲取對(duì)象的哈希值 int hashCode() 返回該對(duì)象的哈希碼值苫耸。
hashCode方法的源碼:
public native int hashCode();
native:代表該方法調(diào)用的是本地操作系統(tǒng)的方法
public class Person extends Object{
//重寫(xiě)hashCode方法
?
@Override
public int hashCode() {
return 1;
}
}
public class HashCode {
public static void main(String[] args) {
//Person類(lèi)繼承了Object類(lèi),所以可以使用Object類(lèi)的hashCode方法
Person p1 = new Person();
int h1 = p1.hashCode();
System.out.println(h1);//1967205423 | 1
?
Person p2 = new Person();
int h2 = p2.hashCode();
System.out.println(h2);//42121758 | 1
?
/*
toString方法的源碼:
return getClass().getName() + "@" + Integer.toHexString(hashCode());
*/
System.out.println(p1);//com.itheima.demo03.hashCode.Person@75412c2f
System.out.println(p2);//com.itheima.demo03.hashCode.Person@282ba1e
System.out.println(p1==p2);//false
?
/*
String類(lèi)的哈希值
String類(lèi)重寫(xiě)Obejct類(lèi)的hashCode方法
*/
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.hashCode());//96354
System.out.println(s2.hashCode());//96354
?
System.out.println("重地".hashCode());//1179395
System.out.println("通話(huà)".hashCode());//1179395
}
}
③HashSet集合
import java.util.HashSet;
/**
* Set集合不允許存儲(chǔ)重復(fù)元素的原理
*/
public class HashSetSaveString {
public static void main(String[] args) {
//創(chuàng)建HashSet集合對(duì)象
HashSet<String> set = new HashSet<>();
String s1 = new String("abc");
String s2 = new String("abc");
set.add(s1);
set.add(s2);
set.add("重地");
set.add("通話(huà)");
set.add("abc");
System.out.println(set);//[重地, 通話(huà), abc]
}
}
import java.util.HashSet;
/*
HashSet存儲(chǔ)自定義類(lèi)型元素
set集合報(bào)錯(cuò)元素唯一:
存儲(chǔ)的元素(String,Integer,...Student,Person...),必須重寫(xiě)hashCode方法和equals方法
要求:
同名同年齡的人,視為同一個(gè)人,只能存儲(chǔ)一次
*/
public class HashSetSavePerson {
public static void main(String[] args) {
//創(chuàng)建HashSet集合存儲(chǔ)Person
HashSet<Person> set = new HashSet<>();
Person p1 = new Person("小姐姐",18);
Person p2 = new Person("小姐姐",18);
Person p3 = new Person("小姐姐",19);
System.out.println(p1.hashCode());//1967205423
System.out.println(p2.hashCode());//42121758
?
System.out.println(p1==p2);//false
System.out.println(p1.equals(p2));//false
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);
}
}
import java.util.Objects;
?
public class Person {
private String name;
private int age;
?
public Person() {
}
?
public Person(String name, int age) {
this.name = name;
this.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 String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
?
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;
}
}
④LinkedHashSet集合
import java.util.HashSet;
import java.util.LinkedHashSet;
?
/*
java.util.LinkedHashSet集合 extends HashSet集合
LinkedHashSet集合特點(diǎn):
底層是一個(gè)哈希表(數(shù)組+鏈表/紅黑樹(shù))+鏈表:多了一條鏈表(記錄元素的存儲(chǔ)順序),保證元素有序
*/
public class Demo04LinkedHashSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("www");
set.add("abc");
set.add("abc");
set.add("itcast");
System.out.println(set);//[abc, www, itcast] 無(wú)序,不允許重復(fù)
?
LinkedHashSet<String> linked = new LinkedHashSet<>();
linked.add("www");
linked.add("abc");
linked.add("abc");
linked.add("itcast");
System.out.println(linked);//[www, abc, itcast] 有序,不允許重復(fù)
}
}
3.可變參數(shù)
使用前提:
當(dāng)方法的參數(shù)列表數(shù)據(jù)類(lèi)型已經(jīng)確定,但是參數(shù)的個(gè)數(shù)不確定,就可以使用可變參數(shù). 使用格式:定義方法時(shí)使用
修飾符 返回值類(lèi)型 方法名(數(shù)據(jù)類(lèi)型...變量名){} 可變參數(shù)的原理:
可變參數(shù)底層就是一個(gè)數(shù)組,根據(jù)傳遞參數(shù)個(gè)數(shù)不同,會(huì)創(chuàng)建不同長(zhǎng)度的數(shù)組,來(lái)存儲(chǔ)這些參數(shù)
傳遞的參數(shù)個(gè)數(shù),可以是0個(gè)(不傳遞),1,2...多個(gè)
public class Demo01VarArgs {
public static void main(String[] args) {
//int i = add();
//int i = add(10);
int i = add(10,20);
//int i = add(10,20,30,40,50,60,70,80,90,100);
System.out.println(i);
?
method("abc",5.5,10,1,2,3,4);
}
?
/*
可變參數(shù)的注意事項(xiàng)
1.一個(gè)方法的參數(shù)列表,只能有一個(gè)可變參數(shù)
2.如果方法的參數(shù)有多個(gè),那么可變參數(shù)必須寫(xiě)在參數(shù)列表的末尾
*/
/*public static void method(int...a,String...b){
錯(cuò)誤寫(xiě)法
}*/
?
/*public static void method(String b,double c,int d,int...a){
}*/
?
//可變參數(shù)的特殊(終極)寫(xiě)法
public static void method(Object...obj){
?
}
?
/*
定義計(jì)算(0-n)整數(shù)和的方法
已知:計(jì)算整數(shù)的和,數(shù)據(jù)類(lèi)型已經(jīng)確定int
但是參數(shù)的個(gè)數(shù)不確定,不知道要計(jì)算幾個(gè)整數(shù)的和,就可以使用可變參數(shù)
add(); 就會(huì)創(chuàng)建一個(gè)長(zhǎng)度為0的數(shù)組, new int[0]
add(10); 就會(huì)創(chuàng)建一個(gè)長(zhǎng)度為1的數(shù)組,存儲(chǔ)傳遞來(lái)過(guò)的參數(shù) new int[]{10};
add(10,20); 就會(huì)創(chuàng)建一個(gè)長(zhǎng)度為2的數(shù)組,存儲(chǔ)傳遞來(lái)過(guò)的參數(shù) new int[]{10,20};
add(10,20,30,40,50,60,70,80,90,100); 就會(huì)創(chuàng)建一個(gè)長(zhǎng)度為2的數(shù)組,存儲(chǔ)傳遞來(lái)過(guò)的參數(shù) new int[]{10,20,30,40,50,60,70,80,90,100};
*/
public static int add(int...arr){
//System.out.println(arr);//[I@2ac1fdc4 底層是一個(gè)數(shù)組
//System.out.println(arr.length);//0,1,2,10
//定義一個(gè)初始化的變量,記錄累加求和
int sum = 0;
//遍歷數(shù)組,獲取數(shù)組中的每一個(gè)元素
for (int i : arr) {
//累加求和
sum += i;
}
//把求和結(jié)果返回
return sum;
}
}
4.Map集合
①M(fèi)ap集合
java.util.Map<k,v>集合
Map集合的特點(diǎn):
1.Map集合是一個(gè)雙列集合,一個(gè)元素包含兩個(gè)值(一個(gè)key,一個(gè)value)
2.Map集合中的元素,key和value的數(shù)據(jù)類(lèi)型可以相同,也可以不同
3.Map集合中的元素,key是不允許重復(fù)的,value是可以重復(fù)的
4.Map集合中的元素,key和value是一一對(duì)應(yīng)
java.util.HashMap<k,v>集合 implements Map<k,v>接口
HashMap集合的特點(diǎn):
1.HashMap集合底層是哈希表:查詢(xún)的速度特別的快
JDK1.8之前:數(shù)組+單向鏈表
JDK1.8之后:數(shù)組+單向鏈表|紅黑樹(shù)(鏈表的長(zhǎng)度超過(guò)8):提高查詢(xún)的速度
2.hashMap集合是一個(gè)無(wú)序的集合,存儲(chǔ)元素和取出元素的順序有可能不一致 1
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
LinkedHashMap的特點(diǎn):
1.LinkedHashMap集合底層是哈希表+鏈表(保證迭代的順序)
2.LinkedHashMap集合是一個(gè)有序的集合,存儲(chǔ)元素和取出元素的順序是一致的
public class Map {
public static void main(String[] args) {
show04();
}
/*
boolean containsKey(Object key) 判斷集合中是否包含指定的鍵。
包含返回true,不包含返回false
*/
private static void show04() {
//創(chuàng)建Map集合對(duì)象
Map<String,Integer> map = new HashMap<>();
map.put("趙麗穎",168);
map.put("楊穎",165);
map.put("林志玲",178);
?
boolean b1 = map.containsKey("趙麗穎");
System.out.println("b1:"+b1);//b1:true
?
boolean b2 = map.containsKey("趙穎");
System.out.println("b2:"+b2);//b2:false
}
?
/*
public V get(Object key) 根據(jù)指定的鍵儡陨,在Map集合中獲取對(duì)應(yīng)的值褪子。
返回值:
key存在,返回對(duì)應(yīng)的value值
key不存在,返回null
*/
private static void show03() {
//創(chuàng)建Map集合對(duì)象
Map<String,Integer> map = new HashMap<>();
map.put("趙麗穎",168);
map.put("楊穎",165);
map.put("林志玲",178);
?
Integer v1 = map.get("楊穎");
System.out.println("v1:"+v1);//v1:165
?
Integer v2 = map.get("迪麗熱巴");
System.out.println("v2:"+v2);//v2:null
}
?
/*
public V remove(Object key): 把指定的鍵 所對(duì)應(yīng)的鍵值對(duì)元素 在Map集合中刪除,返回被刪除元素的值骗村。
返回值:V
key存在,v返回被刪除的值
key不存在,v返回null
*/
private static void show02() {
//創(chuàng)建Map集合對(duì)象
Map<String,Integer> map = new HashMap<>();
map.put("趙麗穎",168);
map.put("楊穎",165);
map.put("林志玲",178);
System.out.println(map);//{林志玲=178, 趙麗穎=168, 楊穎=165}
?
Integer v1 = map.remove("林志玲");
System.out.println("v1:"+v1);//v1:178
?
System.out.println(map);//{趙麗穎=168, 楊穎=165}
?
//int v2 = map.remove("林志穎");//自動(dòng)拆箱 NullPointerException
Integer v2 = map.remove("林志穎");
System.out.println("v2:"+v2);//v2:null
?
System.out.println(map);//{趙麗穎=168, 楊穎=165}
}
?
/*
public V put(K key, V value): 把指定的鍵與指定的值添加到Map集合中嫌褪。
返回值:v
存儲(chǔ)鍵值對(duì)的時(shí)候,key不重復(fù),返回值V是null
存儲(chǔ)鍵值對(duì)的時(shí)候,key重復(fù),會(huì)使用新的value替換map中重復(fù)的value,返回被替換的value值
*/
private static void show01() {
//創(chuàng)建Map集合對(duì)象,多態(tài)
Map<String,String> map = new HashMap<>();
?
String v1 = map.put("李晨", "范冰冰1");
System.out.println("v1:"+v1);//v1:null
?
String v2 = map.put("李晨", "范冰冰2");
System.out.println("v2:"+v2);//v2:范冰冰1
?
System.out.println(map);//{李晨=范冰冰2}
?
map.put("冷鋒","龍小云");
map.put("楊過(guò)","小龍女");
map.put("尹志平","小龍女");
System.out.println(map);//{楊過(guò)=小龍女, 尹志平=小龍女, 李晨=范冰冰2, 冷鋒=龍小云}
}
}
Map集合的第一種遍歷方式:通過(guò)鍵找值的方式
Map集合中的方法:
Set<K> keySet() 返回此映射中包含的鍵的 Set 視圖。
實(shí)現(xiàn)步驟:
1.使用Map集合中的方法keySet(),把Map集合所有的key取出來(lái),存儲(chǔ)到一個(gè)Set集合中
2.遍歷set集合,獲取Map集合中的每一個(gè)key
3.通過(guò)Map集合中的方法get(key),通過(guò)key找到value
public class KeySet {
public static void main(String[] args) {
//創(chuàng)建Map集合對(duì)象
Map<String,Integer> map = new HashMap<>();
map.put("李志",168);
map.put("李德軒",165);
map.put("方永泰",178);
?
//1.使用Map集合中的方法keySet(),把Map集合所有的key取出來(lái),存儲(chǔ)到一個(gè)Set集合中
Set<String> set = map.keySet();
?
//2.遍歷set集合,獲取Map集合中的每一個(gè)key
//使用迭代器遍歷Set集合
Iterator<String> it = set.iterator();
while (it.hasNext()){
String key = it.next();
//3.通過(guò)Map集合中的方法get(key),通過(guò)key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
System.out.println("-------------------");
//使用增強(qiáng)for遍歷Set集合
for(String key : set){
//3.通過(guò)Map集合中的方法get(key),通過(guò)key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
System.out.println("-------------------");
//使用增強(qiáng)for遍歷Set集合
for(String key : map.keySet()){
//3.通過(guò)Map集合中的方法get(key),通過(guò)key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
}
}
Map集合遍歷的第二種方式:使用Entry對(duì)象遍歷
Map集合中的方法:
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射關(guān)系的 Set 視圖胚股。
實(shí)現(xiàn)步驟:
1.使用Map集合中的方法entrySet(),把Map集合中多個(gè)Entry對(duì)象取出來(lái),存儲(chǔ)到一個(gè)Set集合中
2.遍歷Set集合,獲取每一個(gè)Entry對(duì)象
3.使用Entry對(duì)象中的方法getKey()和getValue()獲取鍵與值
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class EntrySet {
public static void main(String[] args) {
//創(chuàng)建Map集合對(duì)象
Map<String,Integer> map = new HashMap<>();
map.put("趙麗穎",168);
map.put("楊穎",165);
map.put("林志玲",178);
?
//1.使用Map集合中的方法entrySet(),把Map集合中多個(gè)Entry對(duì)象取出來(lái),存儲(chǔ)到一個(gè)Set集合中
Set<Map.Entry<String, Integer>> set = map.entrySet();
?
//2.遍歷Set集合,獲取每一個(gè)Entry對(duì)象
//使用迭代器遍歷Set集合
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Integer> entry = it.next();
//3.使用Entry對(duì)象中的方法getKey()和getValue()獲取鍵與值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
System.out.println("-----------------------");
for(Map.Entry<String,Integer> entry:set){
//3.使用Entry對(duì)象中的方法getKey()和getValue()獲取鍵與值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
HashMap存儲(chǔ)自定義類(lèi)型鍵值
Map集合保證key是唯一的:
作為key的元素,必須重寫(xiě)hashCode方法和equals方法,以保證key唯一
public class HashMapSavePerson {
public static void main(String[] args) {
show02();
}
?
/*
HashMap存儲(chǔ)自定義類(lèi)型鍵值
key:Person類(lèi)型
Person類(lèi)就必須重寫(xiě)hashCode方法和equals方法,以保證key唯一
value:String類(lèi)型
可以重復(fù)
*/
private static void show02() {
//創(chuàng)建HashMap集合
HashMap<Person,String> map = new HashMap<>();
//往集合中添加元素
map.put(new Person("女王",18),"英國(guó)");
map.put(new Person("秦始皇",18),"秦國(guó)");
map.put(new Person("普京",30),"俄羅斯");
map.put(new Person("女王",18),"毛里求斯");
//使用entrySet和增強(qiáng)for遍歷Map集合
Set<Map.Entry<Person, String>> set = map.entrySet();
for (Map.Entry<Person, String> entry : set) {
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"-->"+value);
}
}
?
/*
HashMap存儲(chǔ)自定義類(lèi)型鍵值
key:String類(lèi)型
String類(lèi)重寫(xiě)hashCode方法和equals方法,可以保證key唯一
value:Person類(lèi)型
value可以重復(fù)(同名同年齡的人視為同一個(gè))
*/
private static void show01() {
//創(chuàng)建HashMap集合
HashMap<String,Person> map = new HashMap<>();
//往集合中添加元素
map.put("北京",new Person("張三",18));
map.put("上海",new Person("李四",19));
map.put("廣州",new Person("王五",20));
map.put("北京",new Person("趙六",18));
//使用keySet加增強(qiáng)for遍歷Map集合
Set<String> set = map.keySet();
for (String key : set) {
Person value = map.get(key);
System.out.println(key+"-->"+value);
}
}
}
import java.util.Objects;
?
public class Person {
private String name;
private int age;
?
public Person() {
}
?
public Person(String name, int age) {
this.name = name;
this.age = 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);
}
?
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;
}
}
②LinkedHashMap集合
java.util.LinkedHashMap<K,V> entends HashMap<K,V>
Map 接口的哈希表和鏈接列表實(shí)現(xiàn)笼痛,具有可預(yù)知的迭代順序。 底層原理:
哈希表+鏈表(記錄元素的順序)
public class LinkedHashMap {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("a","a");
map.put("c","c");
map.put("b","b");
map.put("a","d");
System.out.println(map);// key不允許重復(fù),無(wú)序 {a=d, b=b, c=c}
?
LinkedHashMap<String,String> linked = new LinkedHashMap<>();
linked.put("a","a");
linked.put("c","c");
linked.put("b","b");
linked.put("a","d");
System.out.println(linked);// key不允許重復(fù),有序 {a=d, c=c, b=b}
}
}
③Hashtable集合
java.util.Hashtable<K,V>集合 implements Map<K,V>接口
Hashtable:底層也是一個(gè)哈希表,是一個(gè)線(xiàn)程安全的集合,是單線(xiàn)程集合,速度慢
HashMap:底層是一個(gè)哈希表,是一個(gè)線(xiàn)程不安全的集合,是多線(xiàn)程的集合,速度快 HashMap集合(前面所有的集合):可以存儲(chǔ)null值
Hashtable集合,不能存儲(chǔ)null值,null鍵Hashtable和Vector集合一樣,在jdk1.2版本之后被更先進(jìn)的集合(HashMap,ArrayList)取代了
Hashtable的子類(lèi)Properties依然活躍在歷史舞臺(tái) Properties集合是一個(gè)唯一和IO流相結(jié)合的集合
public class Hashtable {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put(null,"a");
? map.put("b",null);
map.put(null,null);
System.out.println(map);//{null=null, b=null}
?
Hashtable<String,String> table = new Hashtable<>();
//table.put(null,"a");//NullPointerException
//table.put("b",null);//NullPointerException
table.put(null,null);//NullPointerException
}
}
5.of方法
List接口,Set接口,Map接口:里邊增加了一個(gè)靜態(tài)的方法of,可以給集合一次性添加多個(gè)元素 static List of(E…
elements)
使用前提:
當(dāng)集合中存儲(chǔ)的元素的個(gè)數(shù)已經(jīng)確定了,不在改變時(shí)使用
注意:
1.of方法只適用于List接口,Set接口,Map接口,不適用于接接口的實(shí)現(xiàn)類(lèi)
2.of方法的返回值是一個(gè)不能改變的集合,集合不能再使用add,put方法添加元素,會(huì)拋出異常
3.Set接口和Map接口在調(diào)用of方法的時(shí)候,不能有重復(fù)的元素,否則會(huì)拋出異常
public class Demo {
public static void main(String[] args) {
List<String> list = List.of("a", "b", "a", "c", "d");
System.out.println(list);//[a, b, a, c, d]
//list.add("w");//UnsupportedOperationException:不支持操作異常
?
//Set<String> set = Set.of("a", "b", "a", "c", "d");//IllegalArgumentException:非法參數(shù)異常,有重復(fù)的元素
Set<String> set = Set.of("a", "b", "c", "d");
System.out.println(set);
//set.add("w");//UnsupportedOperationException:不支持操作異常
?
//Map<String, Integer> map = Map.of("張三", 18, "李四", 19, "王五", 20,"張三",19);////IllegalArgumentException:非法參數(shù)異常,有重復(fù)的元素
Map<String, Integer> map = Map.of("張三", 18, "李四", 19, "王五", 20);
System.out.println(map);//{王五=20, 李四=19, 張三=18}
//map.put("趙四",30);//UnsupportedOperationException:不支持操作異常
}
}