今天在看了好多個集合帖子后發(fā)現(xiàn)講的都是一半一半的,這下就逼死我這個強(qiáng)迫癥患者了.于是自己寫點,有不足之處還望各位道友多多指點
一、Collection接口
1.Collection接口
1.java.util.Collection接口:
1.所有單列集合的最頂層的接口,里邊定義了所有單列集合共性的方法
2.任意的單列集合都可以使用Collection接口中的方法
共性的方法:
public boolean add(E e): 把給定的對象添加到當(dāng)前集合中 。
public void clear() :清空集合中所有的元素。
public boolean remove(E e): 把給定的對象在當(dāng)前集合中刪除。
public boolean contains(E e): 判斷當(dāng)前集合中是否包含給定的對象。
public boolean isEmpty(): 判斷當(dāng)前集合是否為空。
public int size(): 返回集合中元素的個數(shù)。
public Object[] toArray(): 把集合中的元素,存儲到數(shù)組中。
示例
public class Collection {
public static void main(String[] args) {
//創(chuàng)建集合對象,可以使用多態(tài)
//Collection<String> coll = new ArrayList<>();
Collection<String> coll = new HashSet<>();
System.out.println(coll);//重寫了toString方法 []
?
/*
public boolean add(E e):把給定的對象添加到當(dāng)前集合中 。
返回值是一個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): 把給定的對象在當(dāng)前集合中刪除。
返回值是一個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)前集合中是否包含給定的對象。
包含返回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(): 返回集合中元素的個數(shù)。
int size = coll.size();
System.out.println("size:"+size);//size:3
?
//public Object[] toArray(): 把集合中的元素,存儲到數(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工具類
java.utils.Collections是集合工具類,用來對集合進(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<>();
//往集合中添加多個元素
/*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)使用前提:
被排序的集合里邊存儲的元素,必須實現(xiàn)Comparable,重寫接口中的方法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ù))比較,自己需要實現(xiàn)Comparable接口,重寫比較的規(guī)則compareTo方法
Comparator:相當(dāng)于找一個第三方的裁判,比較兩個
Comparable接口位于java.lang包下;Comparator位于java.util包下 Comparable接口只提供了一個compareTo()方法;Comparator接口不僅提供了compara()方法,還提供了其他默認(rèn)方法,如reversed()、thenComparing(),使我們可以按照更多的方式進(jìn)行排序如果要用Comparable接口,則必須實現(xiàn)這個接口,并重寫comparaTo()方法;但是Comparator接口可以在類外部使用,通過將該接口的一個匿名類對象當(dāng)做參數(shù)傳遞給Collections.sort()方法或者Arrays.sort()方法實現(xiàn)排序。Comparator體現(xiàn)了一種策略模式,即可以不用要把比較方法嵌入到類中,而是可以單獨在類外部使用,這樣我們就可有不用改變類本身的代碼而實現(xiàn)對類對象進(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>() {
//重寫比較的規(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();
//如果兩個人年齡相同,再使用姓名的第一個字比較
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;
} ?
//重寫排序的規(guī)則
@Override
public int compareTo(Person o) {
//return 0;//認(rèn)為元素都是相同的
//自定義比較的規(guī)則,比較兩個人的年齡(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接口:迭代器(對集合進(jìn)行遍歷)
常用的方法
boolean hasNext() 如果仍有元素可以迭代,則返回 true。
判斷集合中還有沒有下一個元素,有就返回true,沒有就返回false E next() 返回迭代的下一個元素。取出集合中的下一個元素
**注意:**
Iterator迭代器,是一個接口,我們無法直接使用,需要使用Iterator接口的實現(xiàn)類對象,獲取實現(xiàn)類的方式比較特殊
Collection接口中有一個方法,叫iterator(),這個方法返回的就是迭代器的實現(xiàn)類對象
Iterator<E> iterator() 返回在此 collection 的元素上進(jìn)行迭代的迭代器
迭代器的使用步驟(重點):
1.使用集合中的方法iterator()獲取迭代器的實現(xiàn)類對象,使用Iterator接口接收(多態(tài))
2.使用Iterator接口中的方法hasNext判斷還有沒有下一個元素
3.使用Iterator接口中的方法next取出集合中的下一個元素
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
?
public class Iterator {
public static void main(String[] args) {
//創(chuàng)建一個集合對象
Collection<String> coll = new ArrayList<>();
//往集合中添加元素
coll.add("姚明");
coll.add("科比");
coll.add("麥迪");
coll.add("詹姆斯");
coll.add("艾弗森");
?
/*
1.使用集合中的方法iterator()獲取迭代器的實現(xiàn)類對象,使用Iterator接口接收(多態(tài))
注意:
Iterator<E>接口也是有泛型的,迭代器的泛型跟著集合走,集合是什么泛型,迭代器就是什么泛型
*/
//多態(tài) 接口 實現(xiàn)類對象
Iterator<String> it = coll.iterator();
?
?
/*
發(fā)現(xiàn)使用迭代器取出集合中元素的代碼,是一個重復(fù)的過程
所以我們可以使用循環(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判斷還有沒有下一個元素
boolean b = it.hasNext();
System.out.println(b);//true
//3.使用Iterator接口中的方法next取出集合中的下一個元素
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);//沒有元素,返回false
s = it.next();//沒有元素,在取出元素會拋出NoSuchElementException沒有元素異常
System.out.println(s);*/
}
}
2.增強(qiáng)for循環(huán)
增強(qiáng)for循環(huán):底層使用的也是迭代器,使用for循環(huán)的格式,簡化了迭代器的書寫 是JDK1.5之后出現(xiàn)的新特性
Collectionextends Iterable:所有的單列集合都可以使用增強(qiáng)for public interface
Iterable實現(xiàn)這個接口允許對象成為 “foreach” 語句的目標(biāo)。
增強(qiáng)for循環(huán):用來遍歷集合和數(shù)組 格式:
for(集合/數(shù)組的數(shù)據(jù)類型 變量名: 集合名/數(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)建集合對象,使用泛型
好處:
1.避免了類型轉(zhuǎn)換的麻煩,存儲的是什么類型,取出的就是什么類型
2.把運行期異常(代碼運行之后會拋出的異常),提升到了編譯期(寫代碼的時候會報錯)
弊端:
泛型是什么類型,只能存儲什么類型的數(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)建集合對象,不使用泛型
好處:
集合不使用泛型,默認(rèn)的類型就是Object類型,可以存儲任意類型的數(shù)據(jù)
弊端:
不安全,會引發(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類型
Object obj = it.next();
System.out.println(obj);
?
//想要使用String類特有的方法,length獲取字符串的長度;不能使用 多態(tài) Object obj = "abc";
//需要向下轉(zhuǎn)型
//會拋出ClassCastException類型轉(zhuǎn)換異常,不能把Integer類型轉(zhuǎn)換為String類型
String s = (String)obj;
System.out.println(s.length());
}
}
}
①定義含有泛型的類
模擬ArrayList集合
泛型是一個未知的數(shù)據(jù)類型,當(dāng)我們不確定什么什么數(shù)據(jù)類型的時候,可以使用泛型
泛型可以接收任意的數(shù)據(jù)類型,可以使用Integer,String,Student... 創(chuàng)建對象的時候確定泛型的數(shù)據(jù)類型
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) {
//不寫泛型默認(rèn)為Object類型
GenericClass gc = new GenericClass();
gc.setName("只能是字符串");
Object obj = gc.getName(); ?
//創(chuàng)建GenericClass對象,泛型使用Integer類型
GenericClass<Integer> gc2 = new GenericClass<>();
gc2.setName(1); ?
Integer name = gc2.getName();
System.out.println(name); ?
//創(chuàng)建GenericClass對象,泛型使用String類型
GenericClass<String> gc3 = new GenericClass<>();
gc3.setName("小明");
String name1 = gc3.getName();
System.out.println(name1);
} }
②定義含有泛型的方法
泛型定義在方法的修飾符和返回值類型之間
格式:
修飾符 <泛型> 返回值類型 方法名(參數(shù)列表(使用泛型)){
方法體;
}含有泛型的方法,在調(diào)用方法的時候確定泛型的數(shù)據(jù)類型 傳遞什么類型的參數(shù),泛型就是什么類型
public class GenericMethod {
//定義一個含有泛型的方法
public <M> void method01(M m){
System.out.println(m);
}
?
//定義一個含有泛型的靜態(tài)方法
public static <S> void method02(S s){
System.out.println(s);
}
}
測試含有泛型的方法
public class DemoGenericMethod {
public static void main(String[] args) {
//創(chuàng)建GenericMethod對象
GenericMethod gm = new GenericMethod();
/*
調(diào)用含有泛型的方法method01
傳遞什么類型,泛型就是什么類型
*/
gm.method01(10);
gm.method01("abc");
gm.method01(8.8);
gm.method01(true);
gm.method02("靜態(tài)方法,不建議創(chuàng)建對象使用");
//靜態(tài)方法,通過類名.方法名(參數(shù))可以直接使用
GenericMethod.method02("靜態(tài)方法");
GenericMethod.method02(1);
}
}
定義含有泛型的接口
public interface GenericInterface<I> {
public abstract void method(I i);
}
③定義含有泛型的接口的實現(xiàn)類
含有泛型的接口,第一種使用方式:定義接口的實現(xiàn)類,實現(xiàn)接口,指定接口的泛型 public interface Iterator<E> {
E next(); } Scanner類實現(xiàn)了Iterator接口,并指定接口的泛型為String,所以重寫的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);
}
}
含有泛型的接口第二種使用方式:接口使用什么泛型,實現(xiàn)類就使用什么泛型,類跟著接口走
就相當(dāng)于定義了一個含有泛型的類,創(chuàng)建對象的時候確定泛型的類型
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);
}
}
測試含有泛型的接口
public class Demo04GenericInterface {
public static void main(String[] args) {
//創(chuàng)建GenericInterfaceImpl1對象
GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
gi1.method("字符串");
?
//創(chuàng)建GenericInterfaceImpl2對象
GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
gi2.method(10);
?
GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();
gi3.method(8.8);
}
}
④泛型標(biāo)識符
泛型的通配符:
?:代表任意的數(shù)據(jù)類型 使用方式:
不能創(chuàng)建對象使用
只能作為方法的參數(shù)使用 泛型的上限限定: ? extends E 代表使用的泛型只能是E類型的子類/本身 泛型的下限限定: ? super E 代表使用的泛型只能是E類型的父類/本身
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<?>();
}
?
/*
定義一個方法,能遍歷所有類型的ArrayList集合
這時候我們不知道ArrayList集合使用什么數(shù)據(jù)類型,可以泛型的通配符?來接收數(shù)據(jù)類型
注意:
泛型沒有繼承概念的
*/
public static void printArray(ArrayList<?> list){
//使用迭代器遍歷集合
Iterator<?> it = list.iterator();
while(it.hasNext()){
//it.next()方法,取出的元素是Object,可以接收任意的數(shù)據(jù)類型
Object o = it.next();
System.out.println(o);
}
}
}
import java.util.ArrayList;
import java.util.Collection;
?
/*
泛型的上限限定: ? extends E 代表使用的泛型只能是E類型的子類/本身
泛型的下限限定: ? super E 代表使用的泛型只能是E類型的父類/本身
*/
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);//報錯
getElement1(list3);
//getElement1(list4);//報錯
?
//getElement2(list1);//報錯
//getElement2(list2);//報錯
getElement2(list3);
getElement2(list4);
?
/*
類與類之間的繼承關(guān)系
Integer extends Number extends Object
String extends Object
*/
?
}
// 泛型的上限:此時的泛型?,必須是Number類型或者Number類型的子類
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此時的泛型?,必須是Number類型或者Number類型的父類
public static void getElement2(Collection<? super Number> coll){}
}
三、幾種數(shù)據(jù)結(jié)構(gòu)的簡單圖解
四、幾種集合的介紹與使用方法
1.List集合
①ArrayList集合
java.util.List接口 extends Collection接口
List接口的特點:
1.有序的集合,存儲元素和取出元素的順序是一致的(存儲123 取出123)
2.有索引,包含了一些帶索引的方法
?3.允許存儲重復(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):用指定元素替換集合中指定位置的元素,返回值的更新前的元素。
注意:
操作索引的時候,一定要防止索引越界異常
IndexOutOfBoundsException:索引越界異常,集合會報
ArrayIndexOutOfBoundsException:數(shù)組索引越界異常
StringIndexOutOfBoundsException:字符串索引越界異常
public class List {
public static void main(String[] args) {
//創(chuàng)建一個List集合對象,多態(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] 不是地址重寫了toString
?
//public void add(int index, E element): 將指定的元素,添加到該集合中的指定位置上。
//在c和d之間添加一個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):用指定元素替換集合中指定位置的元素,返回值的更新前的元素。
//把最后一個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集合的特點:
1.底層是一個鏈表結(jié)構(gòu):查詢慢,增刪快
2.里邊包含了大量操作首尾元素的方法
注意:使用LinkedList集合特有的方法,不能使用多態(tài)
public void addFirst(E e):將指定元素插入此列表的開頭。
public void addLast(E e):將指定元素添加到此列表的結(jié)尾。
public void push(E e):將元素推入此列表所表示的堆棧。
public E getFirst():返回此列表的第一個元素。
public E getLast():返回此列表的最后一個元素。
public E removeFirst():移除并返回此列表的第一個元素。
public E removeLast():移除并返回此列表的最后一個元素。
public E pop():從此列表所表示的堆棧處彈出一個元素。
public boolean isEmpty():如果列表不包含元素,則返回true。
public class LinkedList {
public static void main(String[] args) {
show03();
}
?
/*
- public E removeFirst():移除并返回此列表的第一個元素。
- public E removeLast():移除并返回此列表的最后一個元素。
- public E pop():從此列表所表示的堆棧處彈出一個元素。此方法相當(dāng)于 removeFirst
*/
private static void show03() {
//創(chuàng)建LinkedList集合對象
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("被移除的第一個元素:"+first);
String last = linked.removeLast();
System.out.println("被移除的最后一個元素:"+last);
System.out.println(linked);//[b]
}
?
/*
- public E getFirst():返回此列表的第一個元素。
- public E getLast():返回此列表的最后一個元素。
*/
private static void show02() {
//創(chuàng)建LinkedList集合對象
LinkedList<String> linked = new LinkedList<>();
//使用add方法往集合中添加元素
linked.add("a");
linked.add("b");
linked.add("c");
?
//linked.clear();//清空集合中的元素 在獲取集合中的元素會拋出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):將指定元素插入此列表的開頭。
- public void addLast(E e):將指定元素添加到此列表的結(jié)尾。
- public void push(E e):將元素推入此列表所表示的堆棧。此方法等效于 addFirst(E)。
*/
private static void show01() {
//創(chuàng)建LinkedList集合對象
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):將指定元素插入此列表的開頭。
//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接口的特點:
1.不允許存儲重復(fù)的元素
2.沒有索引,沒有帶索引的方法,也不能使用普通的for循環(huán)遍歷
java.util.HashSet集合 implements Set接口
HashSet特點:
1.不允許存儲重復(fù)的元素 2.沒有索引,沒有帶索引的方法,也不能使用普通的for循環(huán)遍歷 3.是一個無序的集合,存儲元素和取出元素的順序有可能不一致 4.底層是一個哈希表結(jié)構(gòu)(查詢的速度非常的快)
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);
}
}
}
②哈希值
哈希值:是一個十進(jìn)制的整數(shù),由系統(tǒng)隨機(jī)給出(就是對象的地址值,是一個邏輯地址,是模擬出來得到地址,不是數(shù)據(jù)實際存儲的物理地址)
在Object類有一個方法,可以獲取對象的哈希值 int hashCode() 返回該對象的哈希碼值。
hashCode方法的源碼:
public native int hashCode();
native:代表該方法調(diào)用的是本地操作系統(tǒng)的方法
public class Person extends Object{
//重寫hashCode方法
?
@Override
public int hashCode() {
return 1;
}
}
public class HashCode {
public static void main(String[] args) {
//Person類繼承了Object類,所以可以使用Object類的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類的哈希值
String類重寫Obejct類的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("通話".hashCode());//1179395
}
}
③HashSet集合
import java.util.HashSet;
/**
* Set集合不允許存儲重復(fù)元素的原理
*/
public class HashSetSaveString {
public static void main(String[] args) {
//創(chuàng)建HashSet集合對象
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("通話");
set.add("abc");
System.out.println(set);//[重地, 通話, abc]
}
}
import java.util.HashSet;
/*
HashSet存儲自定義類型元素
set集合報錯元素唯一:
存儲的元素(String,Integer,...Student,Person...),必須重寫hashCode方法和equals方法
要求:
同名同年齡的人,視為同一個人,只能存儲一次
*/
public class HashSetSavePerson {
public static void main(String[] args) {
//創(chuàng)建HashSet集合存儲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集合特點:
底層是一個哈希表(數(shù)組+鏈表/紅黑樹)+鏈表:多了一條鏈表(記錄元素的存儲順序),保證元素有序
*/
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] 無序,不允許重復(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ù)類型已經(jīng)確定,但是參數(shù)的個數(shù)不確定,就可以使用可變參數(shù). 使用格式:定義方法時使用
修飾符 返回值類型 方法名(數(shù)據(jù)類型...變量名){} 可變參數(shù)的原理:
可變參數(shù)底層就是一個數(shù)組,根據(jù)傳遞參數(shù)個數(shù)不同,會創(chuàng)建不同長度的數(shù)組,來存儲這些參數(shù)
傳遞的參數(shù)個數(shù),可以是0個(不傳遞),1,2...多個
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ù)的注意事項
1.一個方法的參數(shù)列表,只能有一個可變參數(shù)
2.如果方法的參數(shù)有多個,那么可變參數(shù)必須寫在參數(shù)列表的末尾
*/
/*public static void method(int...a,String...b){
錯誤寫法
}*/
?
/*public static void method(String b,double c,int d,int...a){
}*/
?
//可變參數(shù)的特殊(終極)寫法
public static void method(Object...obj){
?
}
?
/*
定義計算(0-n)整數(shù)和的方法
已知:計算整數(shù)的和,數(shù)據(jù)類型已經(jīng)確定int
但是參數(shù)的個數(shù)不確定,不知道要計算幾個整數(shù)的和,就可以使用可變參數(shù)
add(); 就會創(chuàng)建一個長度為0的數(shù)組, new int[0]
add(10); 就會創(chuàng)建一個長度為1的數(shù)組,存儲傳遞來過的參數(shù) new int[]{10};
add(10,20); 就會創(chuàng)建一個長度為2的數(shù)組,存儲傳遞來過的參數(shù) new int[]{10,20};
add(10,20,30,40,50,60,70,80,90,100); 就會創(chuàng)建一個長度為2的數(shù)組,存儲傳遞來過的參數(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 底層是一個數(shù)組
//System.out.println(arr.length);//0,1,2,10
//定義一個初始化的變量,記錄累加求和
int sum = 0;
//遍歷數(shù)組,獲取數(shù)組中的每一個元素
for (int i : arr) {
//累加求和
sum += i;
}
//把求和結(jié)果返回
return sum;
}
}
4.Map集合
①Map集合
java.util.Map<k,v>集合
Map集合的特點:
1.Map集合是一個雙列集合,一個元素包含兩個值(一個key,一個value)
2.Map集合中的元素,key和value的數(shù)據(jù)類型可以相同,也可以不同
3.Map集合中的元素,key是不允許重復(fù)的,value是可以重復(fù)的
4.Map集合中的元素,key和value是一一對應(yīng)
java.util.HashMap<k,v>集合 implements Map<k,v>接口
HashMap集合的特點:
1.HashMap集合底層是哈希表:查詢的速度特別的快
JDK1.8之前:數(shù)組+單向鏈表
JDK1.8之后:數(shù)組+單向鏈表|紅黑樹(鏈表的長度超過8):提高查詢的速度
2.hashMap集合是一個無序的集合,存儲元素和取出元素的順序有可能不一致 1
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
LinkedHashMap的特點:
1.LinkedHashMap集合底層是哈希表+鏈表(保證迭代的順序)
2.LinkedHashMap集合是一個有序的集合,存儲元素和取出元素的順序是一致的
public class Map {
public static void main(String[] args) {
show04();
}
/*
boolean containsKey(Object key) 判斷集合中是否包含指定的鍵。
包含返回true,不包含返回false
*/
private static void show04() {
//創(chuàng)建Map集合對象
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集合中獲取對應(yīng)的值。
返回值:
key存在,返回對應(yīng)的value值
key不存在,返回null
*/
private static void show03() {
//創(chuàng)建Map集合對象
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): 把指定的鍵 所對應(yīng)的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
返回值:V
key存在,v返回被刪除的值
key不存在,v返回null
*/
private static void show02() {
//創(chuàng)建Map集合對象
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("林志穎");//自動拆箱 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
存儲鍵值對的時候,key不重復(fù),返回值V是null
存儲鍵值對的時候,key重復(fù),會使用新的value替換map中重復(fù)的value,返回被替換的value值
*/
private static void show01() {
//創(chuàng)建Map集合對象,多態(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("楊過","小龍女");
map.put("尹志平","小龍女");
System.out.println(map);//{楊過=小龍女, 尹志平=小龍女, 李晨=范冰冰2, 冷鋒=龍小云}
}
}
Map集合的第一種遍歷方式:通過鍵找值的方式
Map集合中的方法:
Set<K> keySet() 返回此映射中包含的鍵的 Set 視圖。
實現(xiàn)步驟:
1.使用Map集合中的方法keySet(),把Map集合所有的key取出來,存儲到一個Set集合中
2.遍歷set集合,獲取Map集合中的每一個key
3.通過Map集合中的方法get(key),通過key找到value
public class KeySet {
public static void main(String[] args) {
//創(chuàng)建Map集合對象
Map<String,Integer> map = new HashMap<>();
map.put("李志",168);
map.put("李德軒",165);
map.put("方永泰",178);
?
//1.使用Map集合中的方法keySet(),把Map集合所有的key取出來,存儲到一個Set集合中
Set<String> set = map.keySet();
?
//2.遍歷set集合,獲取Map集合中的每一個key
//使用迭代器遍歷Set集合
Iterator<String> it = set.iterator();
while (it.hasNext()){
String key = it.next();
//3.通過Map集合中的方法get(key),通過key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
System.out.println("-------------------");
//使用增強(qiáng)for遍歷Set集合
for(String key : set){
//3.通過Map集合中的方法get(key),通過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.通過Map集合中的方法get(key),通過key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}
}
}
Map集合遍歷的第二種方式:使用Entry對象遍歷
Map集合中的方法:
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射關(guān)系的 Set 視圖。
實現(xiàn)步驟:
1.使用Map集合中的方法entrySet(),把Map集合中多個Entry對象取出來,存儲到一個Set集合中
2.遍歷Set集合,獲取每一個Entry對象
3.使用Entry對象中的方法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集合對象
Map<String,Integer> map = new HashMap<>();
map.put("趙麗穎",168);
map.put("楊穎",165);
map.put("林志玲",178);
?
//1.使用Map集合中的方法entrySet(),把Map集合中多個Entry對象取出來,存儲到一個Set集合中
Set<Map.Entry<String, Integer>> set = map.entrySet();
?
//2.遍歷Set集合,獲取每一個Entry對象
//使用迭代器遍歷Set集合
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Integer> entry = it.next();
//3.使用Entry對象中的方法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對象中的方法getKey()和getValue()獲取鍵與值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
HashMap存儲自定義類型鍵值
Map集合保證key是唯一的:
作為key的元素,必須重寫hashCode方法和equals方法,以保證key唯一
public class HashMapSavePerson {
public static void main(String[] args) {
show02();
}
?
/*
HashMap存儲自定義類型鍵值
key:Person類型
Person類就必須重寫hashCode方法和equals方法,以保證key唯一
value:String類型
可以重復(fù)
*/
private static void show02() {
//創(chuàng)建HashMap集合
HashMap<Person,String> map = new HashMap<>();
//往集合中添加元素
map.put(new Person("女王",18),"英國");
map.put(new Person("秦始皇",18),"秦國");
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存儲自定義類型鍵值
key:String類型
String類重寫hashCode方法和equals方法,可以保證key唯一
value:Person類型
value可以重復(fù)(同名同年齡的人視為同一個)
*/
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 接口的哈希表和鏈接列表實現(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ù),無序 {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:底層也是一個哈希表,是一個線程安全的集合,是單線程集合,速度慢
HashMap:底層是一個哈希表,是一個線程不安全的集合,是多線程的集合,速度快 HashMap集合(前面所有的集合):可以存儲null值
Hashtable集合,不能存儲null值,null鍵Hashtable和Vector集合一樣,在jdk1.2版本之后被更先進(jìn)的集合(HashMap,ArrayList)取代了
Hashtable的子類Properties依然活躍在歷史舞臺 Properties集合是一個唯一和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接口:里邊增加了一個靜態(tài)的方法of,可以給集合一次性添加多個元素 static List of(E…
elements)
使用前提:
當(dāng)集合中存儲的元素的個數(shù)已經(jīng)確定了,不在改變時使用
注意:
1.of方法只適用于List接口,Set接口,Map接口,不適用于接接口的實現(xiàn)類
2.of方法的返回值是一個不能改變的集合,集合不能再使用add,put方法添加元素,會拋出異常
3.Set接口和Map接口在調(diào)用of方法的時候,不能有重復(fù)的元素,否則會拋出異常
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:不支持操作異常
}
}