Java中的集合(上)
第11章 集合
本章學習目標
- 知道集合與數(shù)組的區(qū)別
- 掌握Collection接口的常用方法
- 理解HashSet、LinkedHashSet、TreeSet的區(qū)別
- 理解Set與List集合的區(qū)別
- 掌握List接口的常用方法
- 理解Vector和ArrayList的區(qū)別
- 理解ArrayList與LinkedList的區(qū)別
- 掌握Queue和Deque隊列接口的常用方法
- 掌握棧和隊列的區(qū)別
- 知道Collection集合與Map集合的區(qū)別
- 掌握Map接口的常用方法
- 掌握Hashtable與HashMap的區(qū)別
- 掌握LinkedHashMap、TreeMap、Properties的區(qū)別
- 了解Set與Map之間的關(guān)系
- 掌握集合工具類Collections的常用方法
- 掌握數(shù)組與List集合之間的轉(zhuǎn)換
- 掌握集合框架關(guān)系圖
11.1 Collection集合
11.1.1 集合的概念
集合是java中提供的一種容器,可以用來存儲多個數(shù)據(jù)。
集合和數(shù)組既然都是容器,它們有啥區(qū)別呢?
- 數(shù)組的長度是固定的。集合的長度是可變的。
- 數(shù)組中可以存儲基本數(shù)據(jù)類型值,也可以存儲對象,而集合中只能存儲對象
集合主要分為兩大系列:Collection和Map,Collection 表示一組對象,Map表示一組映射關(guān)系或鍵值對。
11.1.2 Collection<E>接口
Collection 層次結(jié)構(gòu)中的根接口。Collection 表示一組對象,這些對象也稱為 collection 的元素。一些 collection 允許有重復(fù)的元素,而另一些則不允許。一些 collection 是有序的,而另一些則是無序的。JDK 不提供此接口的任何直接實現(xiàn):它提供更具體的子接口(如 Set 和 List、Queue)實現(xiàn)。此接口通常用來傳遞 collection,并在需要最大普遍性的地方操作這些 collection。
Collection<E>是所有單列集合的父接口,因此在Collection中定義了單列集合(List和Set)通用的一些方法,這些方法可用于操作所有的單列集合。方法如下:
1、添加元素
- (1)add(E obj):添加元素對象到當前集合中
- (2)addAll(Collection<? extends E> other):添加other集合中的所有元素對象到當前集合中,即this = this ∪ other
2、刪除元素
- (1) boolean remove(Object obj) :從當前集合中刪除第一個找到的與obj對象equals返回true的元素。
- (2)boolean removeAll(Collection<?> coll):從當前集合中刪除所有與coll集合中相同的元素。即this = this - this ∩ coll
- (3)boolean retainAll(Collection<?> coll):從當前集合中刪除兩個集合中不同的元素,使得當前集合僅保留與c集合中的元素相同的元素,即當前集合中僅保留兩個集合的交集,即this = this ∩ coll;
- (4)void clear():清空集合
- (5)boolean removeIf(Predicate<? super E> filter) :刪除滿足給定條件的此集合的所有元素。removeIf方法是**Java8**引入的。
3、查詢與獲取元素
- (1)boolean isEmpty():判斷當前集合是否為空集合。
- (2)boolean contains(Object obj):判斷當前集合中是否存在一個與obj對象equals返回true的元素。
- (3)boolean containsAll(Collection<?> c):判斷c集合中的元素是否在當前集合中都存在。即c集合是否是當前集合的“子集”。
- (4)int size():獲取當前集合中實際存儲的元素個數(shù)
- (5)Object[] toArray():返回包含當前集合中所有元素的數(shù)組
- (6)T[] toArray(T[] arr):返回包含當前集合中所有元素的數(shù)組
4、遍歷集合
- (1)default void forEach(Consumer<? super T> action)
- (2)foreach循環(huán)。
所有實現(xiàn)了java.lang.Iterable接口的集合都支持foreach循環(huán)。而Collection接口就繼承了Iterable接口。
5、示例代碼
package com.atguigu.collection;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Predicate;
public class TestCollection {
@Test
public void test1(){
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
System.out.println(coll);
}
@Test
public void test2(){
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
System.out.println(coll);
Collection<String> other = new ArrayList<>();
other.add("尚硅谷");
other.add("JavaEE");
other.add("大數(shù)據(jù)");
other.add("嵌入式");
other.add("鴻蒙");
coll.addAll(other);
System.out.println(coll);
}
@Test
public void test3(){
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
coll.add("atguigu");
coll.add("chai");
coll.remove("java");
System.out.println(coll);
Predicate<String> p = new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("a");
}
};
coll.removeIf(p);
System.out.println(coll);
Collection<String> other = new ArrayList<>();
other.add("尚硅谷");
other.add("JavaEE");
other.add("world");
other.add("hello");
coll.removeAll(other);
System.out.println(coll);
}
@Test
public void test4() {
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
coll.add("atguigu");
coll.add("chai");
Collection<String> other = new ArrayList<>();
other.add("尚硅谷");
other.add("JavaEE");
other.add("world");
other.add("hello");
coll.retainAll(other);
System.out.println(coll);
}
@Test
public void test5() {
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
coll.add("atguigu");
coll.add("chai");
System.out.println(coll.isEmpty());
System.out.println(coll.size());
System.out.println(coll.contains("java"));
Collection<String> other = new ArrayList<>();
other.add("尚硅谷");
other.add("JavaEE");
other.add("world");
other.add("hello");
System.out.println(coll.containsAll(other));
}
@Test
public void test6() {
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
coll.add("atguigu");
coll.add("chai");
Object[] objects = coll.toArray();
System.out.println(Arrays.toString(objects));
String[] strings = new String[0];
strings = coll.toArray(strings);
System.out.println(Arrays.toString(strings));
}
@Test
public void test7() {
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
coll.add("atguigu");
coll.add("chai");
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
coll.forEach(c);
}
@Test
public void test8() {
Collection<String> coll = new ArrayList<>();
coll.add("hello");
coll.add("java");
coll.add("world");
coll.add("atguigu");
coll.add("chai");
for (String s : coll) {
System.out.println(s);
}
}
}
11.2 Set集合
11.2.1 Set接口介紹
`Set`接口是`Collection`的子接口,set接口沒有提供額外需要實現(xiàn)類實現(xiàn)的抽象方法。但是比`Collection`接口更加嚴格了。
Set 集合不允許包含相同的元素,即元素不可重復(fù)。
Set的常用實現(xiàn)類有:`HashSet`、`TreeSet`、`LinkedHashSet`等。
package com.atguigu.list;
import org.junit.Test;
import java.util.HashSet;
public class TestSet {
@Test
public void test03(){
LinkedHashSet<String> set = new LinkedHashSet<>();//按照添加順序,不可重復(fù)
set.add("hello");
set.add("java");
set.add("hello");
set.add("java");
System.out.println(set);
}
@Test
public void test02(){
TreeSet<String> set = new TreeSet<>();//有大小順序,不可重復(fù)
set.add("hello");
set.add("java");
set.add("hello");
set.add("java");
System.out.println(set);
}
@Test
public void test01(){
HashSet<String> set = new HashSet<>();//無序,不可重復(fù)
set.add("hello");
set.add("java");
set.add("hello");
set.add("java");
System.out.println(set);
}
}
11.2.2 元素相等和重復(fù)問題
- HashSet和LinkedHashSet元素不可重復(fù)是依賴于equals和hashCode方法
package com.atguigu.set;
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public String toString() {
return "Circle{" +
"radius=" + radius +
'"}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass()!= o.getClass()) return false;
Circle circle = (Circle) o;
return Double.compare(circle.radius, radius) == 0;
}
@Override
public int hashCode() {
long temp = Double.doubleToLongBits(radius);
return (int) (temp ^ (temp >>> 32));
}
}
@Test
public void test08(){
HashSet<Circle> set = new HashSet<>();
set.add(new Circle(1));
set.add(new Circle(1));
System.out.println(set);
}
- TreeSet元素不可重復(fù)是依賴于比較器的compareTo或compare方法
package com.atguigu.set;
import org.junit.Test;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.TreeSet;
public class TestTreeSet {
@Test
public void test1(){
//String類實現(xiàn)Comparable,所以String類的對象可以方法TreeSet中,默認按照字符的編碼值排序
TreeSet treeSet = new TreeSet();
treeSet.add("hello");
treeSet.add("java");
treeSet.add("haha");
treeSet.add("world");
treeSet.add("heihei");
System.out.println(treeSet);
//[haha, heihei, hello, java, world]
}
@Test
public void test2(){
//使用String類的定制比較器,按照中文的拼音順序
Collator collator = Collator.getInstance(Locale.CHINA);//得到一個實現(xiàn)了Comparator接口的字符串定制比較器
TreeSet treeSet = new TreeSet(collator);
treeSet.add("張三");
treeSet.add("李四");
treeSet.add("王五");
treeSet.add("趙六");
System.out.println(treeSet);
//[李四, 王五, 張三, 趙六]
//li wang zhang zhao
}
@Test
public void test3(){
//使用String類的定制比較器,按照字符串的長短
Comparator lengthComparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
return s1.length() - s2.length();
}
};
TreeSet treeSet = new TreeSet(lengthComparator);
treeSet.add("hi");
treeSet.add("hello");
treeSet.add("hey");
treeSet.add("haha");
treeSet.add("heihei");
treeSet.add("world");//沒添加成功 因為world和hello一樣長
treeSet.add("java");//沒添加成功 因為java和haha一樣長
System.out.println(treeSet);
//[hi, hey, haha, hello, heihei]
}
@Test
public void test4(){
//使用String類的定制比較器,按照字符串的長短,長度一樣,再按內(nèi)容比較大小
Comparator lengthComparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
int result = s1.length() - s2.length();
if(result == 0){
return s1.compareTo(s2);
}
return result;
}
};
TreeSet treeSet = new TreeSet(lengthComparator);
treeSet.add("hi");
treeSet.add("hello");
treeSet.add("hey");
treeSet.add("haha");
treeSet.add("heihei");
treeSet.add("world");
treeSet.add("java");
System.out.println(treeSet);
//[hi, hey, haha, java, hello, world, heihei]
}
}
11.3 List集合
11.3.1 `List<E>`接口介紹
`java.util.List`接口繼承自`Collection`接口,是單列集合的一個重要分支,習慣性地會將實現(xiàn)了`List`接口的對象稱為List集合。
List的常用實現(xiàn)類有:`ArrayList`、`Vector`、`LinkedList`、`Stack`等。
- List集合所有的元素是以一種==線性方式==進行存儲的
- 它是一個元素==存取有序==的集合。即元素的存入順序和取出順序有保證。
- 它是一個==帶有索引==的集合,通過索引就可以精確的操作集合中的元素(與數(shù)組的索引是一個道理)。
- 集合中可以有==重復(fù)==的元素
這就像銀行門口客服,給每一個來辦理業(yè)務(wù)的客戶分配序號:第一個來的是“張三”,客服給他分配的是0;第二個來的是“李四”,客服給他分配的1;以此類推,最后一個序號應(yīng)該是“總?cè)藬?shù)-1”。
注意:
List集合關(guān)心元素是否有序,而不關(guān)心是否重復(fù),請大家記住這個原則。例如“張三”可以領(lǐng)取兩個號。
在JavaSE中`List`名稱的類型有兩個,一個是`java.util.List<E>`集合接口,一個是`java.awt.List`圖形界面的組件,別導(dǎo)錯包了。
11.3.2 ` List<E>`接口中常用方法
List作為Collection集合的子接口,不但繼承了Collection接口中的全部方法,而且還增加了一些根據(jù)索引來操作集合元素的特有方法,如下:
1、添加元素
- `void add(int index, E ele)`:把元素添加到指定位置
- `boolean addAll(int index, Collection<? extends E> eles)`:把一組元素添加到指定位置
2、刪除元素
- `E remove(int index)`:刪除指定位置的元素
3、修改元素
- `E set(int index, E ele)`:替換[index]位置的元素
- `default void replaceAll(UnaryOperator<E> operator)`:按指定操作的要求替換元素
4、獲取元素
- `E get(int index)`:返回[index]位置的元素
- `List subList(int fromIndex, int toIndex)`:返回[fromIndex, toIndex)范圍的元素
- `int indexOf(Object obj)`:查詢obj在列表中的位置,如果有重復(fù),返回第1個
- `int lastIndexOf(Object obj)`:查詢obj在列表中的地位,如果有重復(fù),返回最后1個
5、其他方法
- `default void sort(Comparator<? super E> c) `:對List集合元素進行排序,如果想要通過元素的自然比較器排序,調(diào)用sort方法時傳入null即可。
示例代碼
package com.atguigu.list;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.UnaryOperator;
public class TestList {
@Test
public void test1(){
/*
ArrayList是List接口的實現(xiàn)類。
演示添加add
*/
List<String> list = new ArrayList<>();
list.add("hello");
list.add("java");
list.add(0,"atguigu");
list.add(2,"world");
System.out.println(list);//[atguigu, hello, world, java]
List<String> list2 = Arrays.asList("chai", "lin", "yan");
list.addAll(1,list2);
System.out.println(list);//[atguigu, chai, lin, yan, hello, world, java]
}
@Test
public void test2(){
/*
ArrayList是List接口的實現(xiàn)類。
演示刪除remove(index)
*/
List<String> list = new ArrayList<>();
list.add("hello");
list.add("java");
list.remove(0);
System.out.println(list);
}
@Test
public void test3(){
/*
ArrayList是List接口的實現(xiàn)類。
演示刪除
*/
List<Integer> list =new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.remove(1);//刪除[1]位置的元素
System.out.println(list);//[10, 30, 40]
//list.remove(30);//刪除元素值為30的元素
list.remove(Integer.valueOf(30));//手動裝箱
System.out.println(list);//[10, 40]
}
@Test
public void test4(){
/*
ArrayList是List接口的實現(xiàn)類。
演示修改替換
*/
List<String> list = new ArrayList<>();
list.add("hello");
list.add("java");
list.set(0,"hi");
System.out.println(list);//[hi, java]
UnaryOperator<String> u = new UnaryOperator<String>() {
@Override
public String apply(String s) {
return s.toUpperCase();
}
};
list.replaceAll(u);
System.out.println(list);//[HI, JAVA]
}
@Test
public void test5(){
/*
ArrayList是List接口的實現(xiàn)類.
演示查詢,截取
*/
List<String> list = new ArrayList<>();
list.add("hello");
list.add("java");
list.add("world");
list.add("mysql");
list.add("java");
System.out.println(list.get(1));//java
System.out.println(list.indexOf("java"));//1
System.out.println(list.lastIndexOf("java"));//4
List<String> subList = list.subList(1, 3);//[1,3)下標范圍的元素
System.out.println("subList = " + subList);//[java, world]
}
@Test
public void test6(){
//演示排序
List<String> list = new ArrayList<>();
list.add("hello");
list.add("java");
list.add("world");
list.add("mysql");
list.add("java");
System.out.println(list);
list.sort(null);
System.out.println(list);
Comparator<String> c = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
};
list.sort(c);
System.out.println(list);
}
}