8-集合
集合
集合的作用: 理論上儲存多個不同型別的元素資料。(實際開發中 儲存相同型別的元素)
集合元素型別: 都是引用型別。
所有的集合:(儲存,遍歷)
集合儲存資料: 資料從哪裡來的??---->資料庫查詢來的
集合體系
分為2類: Collection Map
Collection 儲存單值元素 value
Map: 儲存一組元素 key----value
Collection介面
<>: 泛型的標誌 可以修飾類(泛型類) 修飾介面(泛型介面)
: 引數化型別 (限定集合元素的資料型別)----> 集合元素型別單一 A-Z //< >裡放 A-Z的大寫字母都可以
Collection的元素本身就是無序的(沒有索引位置)
tips:一般在建立物件時,將未知的型別確定具體的型別。當沒有指定泛型時,預設型別為Object型別。
Collection是所有單列集合的父介面,因此在Collection中定義了單列集合(List和Set)通用的一些方法,這些方法可用於操作所有的單列集合。方法如下:
增刪:
*boolean add(E e) 將元素資料新增集合物件中
boolean addAll(Collection<? extends E> c)
*boolean remove(Object o) 根據元素資料刪除
boolean removeAll(Collection<?> c)
default boolean removeIf(Predicate<? super E> filter) 刪除多個符合條件的元素 lamda
*void clear() 刪除/清空集合裡面所有的元素
遍歷:
//增強for迴圈
default void forEach(Consumer<? super T> action) 遍歷集合元素 lamda
Iterator<T> iterator() 獲得集合物件的迭代器物件(遍歷集合元素) --->集合的所有的元素都在迭代器物件
Iterator介面的常用方法如下:
1. boolean hasNext() 判斷游標後面是否有更多的元素需要遍歷
2. E next() 獲得游標之後的元素
3. default void remove() 刪除集合元素
判斷:
*boolean contains(Object o) 判斷集合物件中是否包含一個元素
boolean containsAll(Collection<?> c)
*boolean isEmpty() 集合是否是空
*int size() 獲得集合元素個數
*`public Object[] toArray()`: 把集合中的元素,儲存到陣列中。
default Stream<E> parallelStream() 獲得集合物件的Stream例項--->集合可以執行並行化操作 lamda
public class Demo1Collection {
public static void main(String[] args) {
// 建立集合物件
// 使用多型形式
//建立物件的時候 new的必須是實現類
Collection<String> coll = new ArrayList<String>();
// 使用方法
// 新增功能 boolean add(String s)
coll.add("小李廣");
coll.add("掃地僧");
coll.add("石破天");
System.out.println(coll);
// boolean contains(E e) 判斷o是否在集合中存在
System.out.println("判斷 掃地僧 是否在集合中"+coll.contains("掃地僧"));
//boolean remove(E e) 刪除在集合中的o元素
System.out.println("刪除石破天:"+coll.remove("石破天"));
System.out.println("操作之後集合中元素:"+coll);
// size() 集合中有幾個元素
System.out.println("集合中有"+coll.size()+"個元素");
// Object[] toArray()轉換成一個Object陣列
Object[] objects = coll.toArray();
// 遍歷陣列
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
// void clear() 清空集合
coll.clear();
System.out.println("集合中內容為:"+coll);
// boolean isEmpty() 判斷是否為空
System.out.println(coll.isEmpty());
}
}
//如何使用Iterator迭代集合中元素:
public class IteratorDemo {
public static void main(String[] args) {
// 使用多型方式 建立物件
Collection<String> coll = new ArrayList<String>();
// 新增元素到集合
coll.add("串串星人");
coll.add("吐槽星人");
coll.add("汪星人");
//遍歷
//使用迭代器 遍歷 每個集合物件都有自己的迭代器
Iterator<String> it = coll.iterator();
// 泛型指的是 迭代出 元素的資料型別
while(it.hasNext()){ //判斷是否有迭代元素
String s = it.next();//獲取迭代出的元素
System.out.println(s);
}
//使用增強for遍歷
for(String s :coll){//接收變數s代表 代表被遍歷到的集合元素
System.out.println(s);
}
}
}
}
//tips::在進行集合元素取出時,如果集合中已經沒有元素了,還繼續使用迭代器的next方法
//將會發生java.util.NoSuchElementException沒有集合元素的錯誤。
List介面
元素是否有序(索引) | 元素是否可重複 | |
---|---|---|
List | 有序(即元素的存入順序和取出順序一致) | 可重複 |
Set | 無序 | 元素唯一 |
獨有的功能方法:
void add(int index, E element) 指定索引位置新增元素資料
E get(int index) 獲得指定索引位置的元素資料 0--size()-1
ListIterator<E> listIterator() 獲得集合迭代器物件
E remove(int index) 刪除指定索引元素資料並獲得舊值
E set(int index, E element) 修改指定索引的元素並返回修改之前的資料
List<E> subList(int fromIndex, int toIndex) 對擷取陣列增加,刪除,修改會高度還原到原陣列上.
Object[] toArray()
<T> T[] toArray(T[] a)(推薦)
public class ListDemo {
public static void main(String[] args) {
// 建立List集合物件
List<String> list = new ArrayList<String>();
// 往 尾部新增 指定元素
list.add("圖圖");
list.add("小美");
list.add("不高興");
System.out.println(list);
// add(int index,String s) 往指定位置新增
list.add(1,"沒頭腦");
System.out.println(list);
// String remove(int index) 刪除指定位置元素 返回被刪除元素
// 刪除索引位置為2的元素
System.out.println("刪除索引位置為2的元素");
System.out.println(list.remove(2));
System.out.println(list);
// String set(int index,String s)
// 在指定位置 進行 元素替代(改)
// 修改指定位置元素
list.set(0, "三毛");
System.out.println(list);
// String get(int index) 獲取指定位置元素
// 跟size() 方法一起用 來 遍歷的
for(int i = 0;i<list.size();i++){
System.out.println(list.get(i));
}
//還可以使用增強for
for (String string : list) {
System.out.println(string);
}
}
}
底層資料結構 | 效率 | 執行緒安全 | |
---|---|---|---|
* ArrayList | 動態陣列 | 查詢最快 | 不安全 |
LInkedList | 雙向連結串列 | 刪除 新增效率最快 | 不安全 |
Vector | 動態陣列 | 都慢 | 安全 |
連結串列:
元素資料 引用(記憶體地址值)—(上一個元素的引用 下一個元素的引用)
單向連結串列: 元素資料 下一個元素的引用
雙向連結串列: 元素資料 上一個元素的引用 下一個元素的引用
* ArrayList
常用的構造:
ArrayList() 構造一個初始容量為十的空列表。(1.5擴容)
ArrayList(Collection<? extends E> c)
ArrayList(int initialCapacity) //10
initialCapacity: (儲存的元素個數/負載因子+1)
//建立List集合物件
ArrayList<Integer> list = new ArrayList<>();//初始化容量10
//1.新增元素
list.add(100);
list.add(200);
list.add(200);
list.add(300);
list.add(2);
list.add(3);
list.add(0,1);// >=0 <=size
System.out.println(list);
//2.獲得
Integer num = list.get(0);//elementData[index]
System.out.println(num);
//3.刪除
System.out.println(list.remove(1));
System.out.println(list);
//4.修改
System.out.println(list.set(0, 11));
System.out.println(list);//[11, 200, 200, 300, 2, 3]
List<Integer> list1 = list.subList(0, 3);//包頭不包尾
System.out.println(list1);
//對擷取陣列增加 刪除 修改 會 高度還原到原陣列上的
System.out.println("list1:"+list1);
System.out.println("list:"+list);
// list1.remove(0);
// list.add(0,12);//modCount==size failfast
//集合 轉換陣列
// Object[] toArray()
Object[] toArray = list.toArray();
System.out.println("toArray:"+Arrays.toString(toArray));
for (Object o : toArray) { //這樣轉換的陣列 要想遍歷Integer的話 還需要強轉
//手動強制
Integer num1 = (Integer) o;
}
//<T> T[] toArray(T[] a)(推薦)
Integer[] integers = list.toArray(new Integer[0]);
System.out.println("toArray:"+Arrays.toString(integers));
遍歷
private static void demo2() {
List<String> list = new ArrayList<>(10);
//遍歷
list.add("abc");
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
list.add("abc");
//1.普通迴圈
// for (int i = 0,size = list.size(); i < size; i++) {
// System.out.println(list.get(i));
// }
//2.增強for
// for (String s : list) {
// System.out.println(s);
// }
//3.迭代器
// Iterator<String> iterator = list.iterator();
// while(iterator.hasNext()){
// String next = iterator.next();
// System.out.println(next);
// }
//4.listIterator
// ListIterator<String> listIterator = list.listIterator();
// while (listIterator.hasNext()) {
// String next = listIterator.next();
// System.out.println(next);
//
// }
//5.forEach
list.forEach((String str)->{
System.out.println(str);
});
}
遍歷修改
private static void demo3() {
ArrayList<String> list = new ArrayList<>(10);
//遍歷
list.add("abc");
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
list.add("abc");
System.out.println("刪除之前:"+list);
//刪除元素都是abc
// list.forEach((String str)->{
// if("abc".equals(str)){
// //找到了元素 刪除
// list.add("123"); 遍歷期間forEach刪除元素會報錯 修改一般不會 可能會出現
// }
// });
// for (int i = 0; i < list.size(); i++) { for迴圈都可以
// if("abc".equals(list.get(i))
// list.remove("abc");
// }
// }
// Iterator<String> iterator = list.iterator(); ***
// System.out.println(iterator); //java.util.ArrayList$Itr@4141d797
// while(iterator.hasNext()){
// String next = iterator.next();
// if("abc".equals(next)){
// iterator.remove(); 迭代器不能用list的remove 只能用iterator.remove();
// }
// }
// System.out.println("刪除之後:"+list);// Exception in thread "main" java.util.ConcurrentModificationException
// for (String s : list) { //迭代器實現的
// if("abc3".equals(s)){
// //找到了元素 刪除
// list.remove(s); //只能刪倒數第二個元素
// }
// }
Iterator<String> iterator = list.iterator();
for(;iterator.hasNext();){
String next = iterator.next();//cursor
if("abc3".equals(next)){
//找到了元素 刪除
list.remove(next); //只能刪倒數第二個元素
}
}
System.out.println("刪除之後:"+list);
}
LinkedList
LinkedList 集合資料儲存的結構是連結串列結構。方便元素新增、刪除的集合。
理論上可以儲存無數個元素。
佇列: 排隊---> 先進先出
棧: fifo 先進後出
LinkedList()
LinkedList提供了大量首尾操作的方法。這些方法我們作為了解即可:
* `public void addFirst(E e)`:將指定元素插入此列表的開頭。
* `public void addLast(E e)`:將指定元素新增到此列表的結尾。
* `public E getFirst()`:返回此列表的第一個元素。
* `public E getLast()`:返回此列表的最後一個元素。
* `public E removeFirst()`:移除並返回此列表的第一個元素。
* `public E removeLast()`:移除並返回此列表的最後一個元素。
* `public E pop()`:從此列表所表示的堆疊處彈出一個元素。
* `public void push(E e)`:將元素推入此列表所表示的堆疊。
* `public boolean isEmpty()`:如果列表不包含元素,則返回true。
LinkedList是List的子類,List中的方法LinkedList都是可以使用,這裡就不做詳細介紹,
我們只需要瞭解LinkedList的特有方法即可。在開發時,LinkedList集合也可以作為堆疊,佇列的結構使用。(瞭解即可)
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> link = new LinkedList<String>();
//新增元素
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
System.out.println(link);
// 獲取元素
System.out.println(link.getFirst());
System.out.println(link.getLast());
// 刪除元素
System.out.println(link.removeFirst());
System.out.println(link.removeLast());
while (!link.isEmpty()) { //判斷集合是否為空
System.out.println(link.pop()); //彈出集合中的棧頂元素
}
System.out.println(link);
}
}
Vector
Vector()
Vector(int initialCapacity) //10
Set介面
Set集合的元素是無序的(index) 元素唯一的
tips:Set集合取出元素的方式可以採用:迭代器、增強for
資料結構 | 執行緒安全 | 元素是否可以為null | |
---|---|---|---|
HashSet | 雜湊表(HashMap) | 不安全 | 可以為null |
LinkedHashSet | 連結串列+雜湊表 | 不安全 | 可以為null |
TreeSet | 紅黑樹 | 不安全 | 不能為null |
* HashSet
此類實現Set介面,由雜湊表(實際為HashMap例項)支援. 元素無序,(順序)
HashSet() 構造一個新的空集合; 背景HashMap例項具有預設初始容量(16)和負載因子(0.75)。
HashSet(int initialCapacity) (儲存的元素個數/負載因子)+1
HashSet(Collection<? extends E> c) (List集合去重)
public class HashSetDemo {
public static void main(String[] args) {
demo1();
}
private static void demo1() {
HashSet<Integer> hashSet = new HashSet<>();
//新增元素
System.out.println(hashSet.add(100));//true
System.out.println(hashSet.add(100));//false
System.out.println(hashSet.add(1));
System.out.println(hashSet.add(10));
System.out.println(hashSet.add(null));
System.out.println(hashSet.add(10));
System.out.println(hashSet.toString());
//其它的方法與Collection一模一樣
//3種遍歷方法
for (Integer integer : hashSet) {
System.out.println(integer);
}
System.out.println("------------------------");
Iterator<Integer> iterator = hashSet.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("------------------------");
hashSet.forEach((num)->{
System.out.println(num);
});
}
}
- HashSet儲存自定義型別元素
給HashSet中存放自定義型別元素時,需要重寫物件中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的物件唯一
建立自定義Student類
/*
HashSet儲存自定義型別元素
set集合報錯元素唯一:
儲存的元素(String,Integer,...Student,Person...),必須重寫hashCode方法和equals方法
要求:
同名同年齡的人,視為同一個人,只能儲存一次
*/
public class HashSetDemo2 {
public static void main(String[] args) {
//建立集合物件 該集合中儲存 Student型別物件
HashSet<Student> stuSet = new HashSet<Student>();
//儲存
Student stu = new Student("于謙", 43);
stuSet.add(stu);
stuSet.add(new Student("郭德綱", 44));
stuSet.add(new Student("于謙", 43));
stuSet.add(new Student("郭麒麟", 23));
stuSet.add(stu); //不重寫 相同名字跟年齡的都會存進去
for (Student stu2 : stuSet) {
System.out.println(stu2);
}
}
}
執行結果:
Student [name=郭德綱, age=44]
Student [name=于謙, age=43]
Student [name=郭麒麟, age=23]
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.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;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
LinkedHashSet
我們知道HashSet保證元素唯一,可是元素存放進去是沒有順序的,那麼我們要保證有序,怎麼辦呢?
在HashSet下面有一個子類java.util.LinkedHashSet
,它是連結串列和雜湊表組合的一個資料儲存結構。
演示程式碼如下:
雜湊表和連結串列實現了Set介面,具有可預測的迭代次序(插入順序與遍歷順序是一致的)
LinkedHashSet() 構造一個具有預設初始容量(16)和負載因子(0.75)的新的,空的連結雜湊集
LinkedHashSet(int initialCapacity)
構造一個具有指定初始容量和預設負載因子(0.75)的新的,空的連結雜湊集
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("bbb");
set.add("aaa");
set.add("abc");
set.add("bbc");
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
結果:
bbb
aaa
abc
bbc
TreeSet
基於TreeMap。 元素都是有序的(會按照自然順序排列)--->要求元素型別必須有排序規則(Comparable)
TreeSet()
TreeSet(Comparator<? super E> comparator) 外部比較器(排序規則)
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>();//預設是按照升序排列的
treeSet.add(100);
treeSet.add(1);
treeSet.add(2);
System.out.println(treeSet);
}
}
Map<K,V>介面
儲存一組元素。 有key 有value K V 都是map集合的引數化型別。
將key對映到value上。 可以根據key獲得value值
map集合的key是唯一的。value可以重複。
底層資料結構 | 執行緒安全 | k/v是否可以為null | |
---|---|---|---|
HashMap<K,V> | 雜湊表 | 否 | 都可以為null |
LinkedHashMap<K,V> | 雜湊表+連結串列 | 否 | 都可以為null |
TreeMap<K,V> | 紅黑樹 | 否 | k不能為null V:可以 |
HashTable<K,V> | 雜湊表 | 安全(悲觀鎖) | K/V都不能為null |
ConcurrentHashMap<K,V> | 鎖分段技術/CAS(樂觀鎖) | 安全 | K/V都不能為null |
static interface Map.Entry<K,V> 維護map集合裡面每組元素的
void clear() 清空map集合所有的元素
boolean containsKey(Object key) 判斷map集合是否包含指定的key
boolean containsValue(Object value) 判斷map集合是否包含指定的value
V get(Object key) 根據key獲得v
default V getOrDefault(Object key, V defaultValue)
boolean isEmpty()
V put(K key, V value) 新增一組元素
V remove(Object key) 刪除
default boolean remove(Object key, Object value)
default V replace(K key, V value)
default boolean replace(K key, V oldValue, V newValue)
int size()
通過檢視Map介面描述,看到Map有多個子類,這裡我們主要講解常用的HashMap集合、LinkedHashMap集合。
- HashMap<K,V>:儲存資料採用的雜湊表結構,元素的存取順序不能保證一致。由於要保證鍵的唯一、不重複,需要重寫鍵的hashCode()方法、equals()方法。
- LinkedHashMap<K,V>:HashMap下有個子類LinkedHashMap,儲存資料採用的雜湊表結構+連結串列結構。通過連結串列結構可以保證元素的存取順序一致;通過雜湊表結構可以保證的鍵的唯一、不重複,需要重寫鍵的hashCode()方法、equals()方法。
tips:Map介面中的集合都有兩個泛型變數<K,V>,在使用時,要為兩個泛型變數賦予資料型別。兩個泛型變數<K,V>的資料型別可以相同,也可以不同。
* HashMap<K,v>
HashMap(int initialCapacity)
private static void demo1() {
//在正常的開發中,map的key的資料型別:String居多====> json串--->屬性名稱(全部都是字串): 屬性值
HashMap<Integer, String> hashMap = new HashMap<>(16);
//1.儲存元素
hashMap.put(1, "a");
hashMap.put(10, "b");
hashMap.put(100, "c");
hashMap.put(1, "ccccc");
System.out.println(hashMap.size());// map的key重複的時候 value會被覆蓋。
//2.獲取map元素
String s = hashMap.get(1);
System.out.println(s);
//3.刪除
// System.out.println(hashMap.remove(1));//ccccc
// System.out.println(hashMap.remove(1,"ccccc"));
//4.修改
System.out.println(hashMap.replace(1, "10"));
//5.判斷
System.out.println(hashMap.containsKey(1));
System.out.println(hashMap.containsValue("10"));
System.out.println(hashMap);
}
- 遍歷
Set<Map.Entry<K,V>> entrySet()
遍歷map集合的方法(獲得map集合的每一組k/V轉換成一個個entry物件 並儲存到set集合中)
default void forEach(BiConsumer<? super K,? super V> action) 遍歷map集合
Set<K> keySet() 遍歷map集合方法(獲得map集合裡面所有的key 並把key儲存到set)
Collection<V> values() 獲得map集合的所有的v
黑馬:
Map集合遍歷鍵找值方式
鍵找值方式:即通過元素中的鍵,獲取鍵所對應的值
分析步驟:
1. 獲取Map中所有的鍵,由於鍵是唯一的,所以返回一個Set集合儲存所有的鍵。方法提示:`keyset()`
2. 遍歷鍵的Set集合,得到每一個鍵。
3. 根據鍵,獲取鍵所對應的值。方法提示:`get(K key)`
public class MapDemo01 {
public static void main(String[] args) {
//建立Map集合物件
HashMap<String, String> map = new HashMap<String,String>();
//新增元素到集合
map.put("胡歌", "霍建華");
map.put("郭德綱", "于謙");
map.put("薛之謙", "大張偉");
//獲取所有的鍵 獲取鍵集
Set<String> keys = map.keySet();
// 遍歷鍵集 得到 每一個鍵
for (String key : keys) {
//key 就是鍵
//獲取對應值
String value = map.get(key);
System.out.println(key+"的CP是:"+value);
}
}
}
黑馬:
Map集合遍歷鍵值對方式
鍵值對方式:即通過集合中每個鍵值對(Entry)物件,獲取鍵值對(Entry)物件中的鍵與值。
操作步驟與圖解:
1. 獲取Map集合中,所有的鍵值對(Entry)物件,以Set集合形式返回。方法提示:entrySet()。
2. 遍歷包含鍵值對(Entry)物件的Set集合,得到每一個鍵值對(Entry)物件。
3. 通過鍵值對(Entry)物件,獲取Entry物件中的鍵與值。 方法提示:getkey() getValue()
public class MapDemo02 {
public static void main(String[] args) {
// 建立Map集合物件
HashMap<String, String> map = new HashMap<String,String>();
// 新增元素到集合
map.put("胡歌", "霍建華");
map.put("郭德綱", "于謙");
map.put("薛之謙", "大張偉");
// 獲取 所有的 entry物件 entrySet
Set<Entry<String,String>> entrySet = map.entrySet();
// 遍歷得到每一個entry物件
for (Entry<String, String> entry : entrySet) {
// 解析
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"的CP是:"+value);
}
}
}
private static void demo2() {
HashMap<Integer, String> hashMap = new HashMap<>(16);
hashMap.put(1, "a");
hashMap.put(10, "b");
hashMap.put(100, "c");
hashMap.put(0, "c");
hashMap.put(null, "ccccc");
hashMap.put(2, null);
//遍歷
//forEach遍歷 需要重寫方法
hashMap.forEach(new BiConsumer<Integer, String>() {
@Override
public void accept(Integer key, String value) {
System.out.println("key:"+key+",value:"+value);
}
});
//forEach遍歷 -----lambda 簡化方式
hashMap.forEach((key, value)->{
System.out.println("key:"+key+",value:"+value);
});
//jdk1.8之前-
// hashMap.entrySet(); entry:鍵值對 推薦
Set<Map.Entry<Integer, String>> entries = hashMap.entrySet();//等同遍歷set集合了
Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();
while(iterator.hasNext()){
Map.Entry<Integer, String> entry = iterator.next();// k v
System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
}
//keySet()
Set<Integer> keySet = hashMap.keySet();//map的key
keySet.forEach(key->{
System.out.println("key:"+key+",value:"+hashMap.get(key));
});
//Collection<V> values() java.util.HashMap$Values
Collection<String> values = hashMap.values();
System.out.println(values);
}
LinkedHashMap
我們知道HashMap保證成對元素唯一,並且查詢速度很快,可是成對元素存放進去是沒有順序的,那麼我們要保證有序,還要速度快怎麼辦呢?
在HashMap下面有一個子類LinkedHashMap,它是連結串列和雜湊表組合的一個資料儲存結構。
public class LinkedHashMapDemo {
public static void main(String[] args) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("鄧超", "孫儷");
map.put("李晨", "范冰冰");
map.put("劉德華", "朱麗倩");
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
結果:
鄧超 孫儷
李晨 范冰冰
劉德華 朱麗倩
TreeMap
TreeMap(Comparator<? super K> comparator)
TreeMap()
private static void demo4() {
TreeMap<Integer, String> map = new TreeMap<>();
//無參構造建立物件 在底層comparator = null; 自定義比較器(自定義的排序規則)
map.put(1, "a");
map.put(10, "b");
map.put(100, "c");
map.put(1, "c");
map.put(2, null);
System.out.println(map);
}
Collections 類
常用功能
java.utils.Collections
是集合工具類,用來對集合進行操作。部分方法如下:
-
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中新增一些元素。 -
public static void shuffle(List<?> list) 打亂順序
:打亂集合順序。 -
public static <T> void sort(List<T> list)
:將集合中元素按照預設規則排序。 -
public static <T> void sort(List<T> list,Comparator<? super T> )
:將集合中元素按照指定規則排序。 -
static List synchronizedList(List list) :將集合變成執行緒安全的方法
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
程式碼演示:
private static void demo2() {
List<Integer> list = new ArrayList<>(10);
Collections.addAll(list, 2, 10, 30, 1, 101, 100);
System.out.println("排序之前:" + list);
Collections.sort(list);// 要求集合元素型別必須實現Comparable介面
//預設按照升序排列 //預設按照集合元素型別規定的額排序規則 Integer.compareTo()
System.out.println("排序之後:" + list);
}
//[2,10,30,1,101,100]
//[1,2,10,30,100,101]
private static List<String> myList;//執行緒安全
private static void demo1() {
List<String> list = new ArrayList<>(10);
Collections.addAll(list, "abc", "11", "123", "a", "b");
System.out.println(list);
//將執行緒不安全的例項轉換成執行緒安全的物件
myList = Collections.synchronizedList(list);
}
}
排序
-
一種是比較死板的採用
java.lang.Comparable
介面去實現 -
一種是靈活的當我需要做排序的時候在去選擇的
java.util.Comparator
介面完成
//public static <T> void sort(List<T> list):將集合中元素按照預設規則排序
//Comparable`介面去實現
public class CollectionsDemo2 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法
Collections.sort(list);
System.out.println(list);
}
}
//[aba, cba, nba, sba]
//當你想改變預設的排序方式
// public int compare(String o1, String o2):比較其兩個引數的順序
//Comparator`介面完成
public class CollectionsDemo3 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法 按照第一個單詞的降序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.charAt(0) - o1.charAt(0);
}
});
System.out.println(list);
}
}
//[sba, nba, cba, aba]
Comparable和Comparator兩個介面的區別
Comparable:強行對實現它的每個類的物件進行整體排序。這種排序被稱為類的自然排序,類的compareTo方法被稱為它的自然比較方法。只能在類中實現compareTo()一次,不能經常修改類的程式碼實現自己想要的排序。實現此介面的物件列表(和陣列)可以通過Collections.sort(和Arrays.sort)進行自動排序,物件可以用作有序對映中的鍵或有序集合中的元素,無需指定比較器。
Comparator強行對某個物件進行整體排序。可以將Comparator 傳遞給sort方法(如Collections.sort或 Arrays.sort),從而允許在排序順序上實現精確控制。還可以使用Comparator來控制某些資料結構(如有序set或有序對映)的順序,或者為那些沒有自然順序的物件collection提供排序。
List
Comparable<T>: java.lang.* 內部比較器 compareTo()
Comparable
private static void demo3() {
//List集合元素可以重複 list集合的元素型別沒有必要重寫equals和hashcode
List<User> userList = new ArrayList<>(10);
Collections.addAll(userList,
new User(1, "jim1"),
new User(1, "jim1"),
new User(8, "jim3"),
new User(8, "jim4"));
System.out.println("排序之前:" + userList);
Collections.sort(userList);
System.out.println("排序之後:" + userList);
}
@Setter
@Getter
@AllArgsConstructor
@ToString
public class User implements Comparable<User> {
private Integer id;
private String name;
@Override
public int compareTo(User user) {
Objects.requireNonNull(user);
if (this == user) {
return 0;//代表2個物件是相等的
}
//比較規則 看屬性 根據id升序排列
//id一致 name也參與比較(降序)
int result = this.id.compareTo(user.id);
if (result == 0) {
result = user.name.compareTo(this.name);
}
return result;//0 -1 1
}
}
Comparator
@Setter
@Getter
@AllArgsConstructor
@ToString
public class User{
private Integer id;
private String name;
}
private static void demo4() {
List<User> userList = new ArrayList<>(10);
Collections.addAll(userList,
new User(1, "jim1"),
new User(10, "jim11"),
new User(8, "jim3"),
new User(7, "jim4"));
System.out.println("排序之前:" + userList);
//TreeSet TreeMap 有參構造 Comparator 自定義外部比較器規則
Collections.sort(userList, new Comparator<User>() {
@Override
public int compare(User user1, User user2) {
int result = user1.getId().compareTo(user2.getId());
if(result==0){
result = user1.getName().compareTo(user2.getName());
}
return result;
}
});
//lambada 簡化格式
Collections.sort(userList, (user1, user2) -> {
int result = user1.getId().compareTo(user2.getId());
if (result == 0) {
result = user1.getName().compareTo(user2.getName());
}
return result;
});
//
System.out.println("排序之後:" + userList);
}
set (集合元素是唯一)
HashSet/LinkedHashSet 無法排序
TreeSet 排序
private static void demo4() {
//分支
TreeSet<User> treeSet = new TreeSet<>();
treeSet.add(new User(1, "jim7"));
treeSet.add(new User(1, "jim1"));
treeSet.add(new User(8, "jim7"));
treeSet.add(new User(8, "jim4"));
System.out.println(treeSet);
}
public class User implements Comparable<User> {
//public class User{
private Integer id;
private String name;
@Override
public int compareTo(User user) {
Objects.requireNonNull(user);
if (this == user) {
return 0;//代表2個物件是相等的
}
return user.name.compareTo(this.name);//0 -1 1
}
}
//lambda簡寫
private static void demo5() {
TreeSet<User> treeSet = new TreeSet<>((User o1, User o2)->{
return o2.getName().compareTo(o1.getName());
});
treeSet.add(new User(1, "jim7"));
treeSet.add(new User(1, "jim1"));
treeSet.add(new User(8, "jim7"));
treeSet.add(new User(8, "jim4"));
System.out.println(treeSet);
}
map
Map的key排序 TreeMap
1. Map的key儲存的是自定義的類物件
public static void main(String[] args) {
TreeMap<User,Integer> treeMap = new TreeMap<>((user1,user2)->{
return user1.getName().compareTo(user2.getName());
});
treeMap.put(new User(1, "jim7"),1);
treeMap.put(new User(1, "jim1"),1);
treeMap.put(new User(8, "jim7"),1);
treeMap.put(new User(8, "jim4"),1);
System.out.println(treeMap);
}
泛型
泛型的好處
- 將執行時期的ClassCastException,轉移到了編譯時期變成了編譯失敗。
- 避免了型別強轉的麻煩
public class GenericDemo2 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<String>();
list.add("abc");
list.add("itcast");
// list.add(5);//當集合明確型別後,存放型別不一致就會編譯報錯
// 集合已經明確具體存放的元素型別,那麼在使用迭代器的時候,迭代器也同樣會知道具體遍歷元素型別
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();
//當使用Iterator<String>控制元素型別後,就不需要強轉了。獲取到的元素直接就是String型別
System.out.println(str.length());
}
}
}
tips : 泛型是資料型別的一部分,我們將類名與泛型合併一起看做資料型別
泛型的定義與使用
泛型,用來靈活地將資料型別應用到不同的類、方法、介面當中。將資料型別作為引數進行傳遞。
含有泛型的類
定義格式:
修飾符 class 類名<代表泛型的變數> { }
使用泛型: 即什麼時候確定泛型。
//舉例自定義泛型類
public class MyGenericClass<MVP> {
//沒有MVP型別,在這裡代表 未知的一種資料型別 未來傳遞什麼就是什麼型別
private MVP mvp;
public void setMVP(MVP mvp) {
this.mvp = mvp;
}
public MVP getMVP() {
return mvp;
}
}
//使用:
public class GenericClassDemo {
public static void main(String[] args) {
// 建立一個泛型為String的類
MyGenericClass<String> my = new MyGenericClass<String>();
// 呼叫setMVP
my.setMVP("大鬍子登登");
// 呼叫getMVP
String mvp = my.getMVP();
System.out.println(mvp);
//建立一個泛型為Integer的類
MyGenericClass<Integer> my2 = new MyGenericClass<Integer>();
my2.setMVP(123);
Integer mvp2 = my2.getMVP();
}
}
含有泛型的方法
定義格式:
修飾符 <代表泛型的變數> 返回值型別 方法名(引數){ }
例:
public class MyGenericMethod {
public <MVP> void show(MVP mvp) {
System.out.println(mvp.getClass());
}
public <MVP> MVP show2(MVP mvp) {
return mvp;
}
}
//使用格式:呼叫方法時,確定泛型的型別
public class GenericMethodDemo {
public static void main(String[] args) {
// 建立物件
MyGenericMethod mm = new MyGenericMethod();
// 演示看方法提示
mm.show("aaa");
mm.show(123);
mm.show(12.45);
}
}
含有泛型的介面
定義格式:
修飾符 interface介面名<代表泛型的變數> { }
使用格式:
//1、定義類時確定泛型的型別
例如
public class MyImp1 implements MyGenericInterface<String> {
@Override
public void add(String e) {
// 省略...
}
@Override
public String getE() {
return null;
}
}
//此時,泛型E的值就是String型別。
//2、始終不確定泛型的型別,直到建立物件時,確定泛型的型別
例如
public class MyImp2<E> implements MyGenericInterface<E> {
@Override
public void add(E e) {
// 省略...
}
@Override
public E getE() {
return null;
}
}
//確定泛型:
public class GenericInterface {
public static void main(String[] args) {
MyImp2<String> my = new MyImp2<String>();
my.add("aa");
}
}
泛型萬用字元
泛型的萬用字元:不知道使用什麼型別來接收的時候,此時可以使用?,?表示未知萬用字元。
public static void getElement(Collection<?> coll){}
//這個類定義時用的問號 這樣子建立物件的時候只要不是同一個物件 可隨意定義資料型別
//遍歷時使用次數也比較多
//?代表可以接收任意型別
public static void main(String[] args) {
Collection<Intger> list1 = new ArrayList<Integer>();
getElement(list1);
Collection<String> list2 = new ArrayList<String>();
getElement(list2);
}
萬用字元高階使用----受限泛型
之前設定泛型的時候,實際上是可以任意設定的,只要是類就可以設定。但是在JAVA的泛型中可以指定一個泛型的上限和下限。
泛型的上限:
- 格式:
型別名稱 <? extends 類 > 物件名稱
- 意義:
只能接收該型別及其子類
泛型的下限:
- 格式:
型別名稱 <? super 類 > 物件名稱
- 意義:
只能接收該型別及其父型別
比如:現已知Object類,String 類,Number類,Integer類,其中Number是Integer的父類
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>();
getElement(list1);
getElement(list2);//報錯
getElement(list3);
getElement(list4);//報錯
getElement2(list1);//報錯
getElement2(list2);//報錯
getElement2(list3);
getElement2(list4);
}
// 泛型的上限:此時的泛型?,必須是Number型別或者Number型別的子類
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此時的泛型?,必須是Number型別或者Number型別的父類
public static void getElement2(Collection<? super Number> coll){}
集合巢狀
城市級聯:
一個省份有多個城市:
可以根據省份獲得所有的城市資訊
public static void main(String[] args) {
//儲存資料 到集合
List<String> city = new ArrayList<>(10);
Collections.addAll(city, "鄭州市", "洛陽市", "鄭州市1", "鄭州市2", "鄭州市3");
//可以根據省份獲得所有的城市資訊: ===> map: 根據key獲得value
Map<String, List<String>> province = new HashMap<>(16);
province.put("hn", city);
city = new ArrayList<>(10);
Collections.addAll(city, "石家莊市", "保定市", "保定1", "保定2", "保定3");
province.put("he", city);
System.out.println(province.get("he"));
}
Stream
List集合元素去重
1.List 轉換 Set(利用set構造)
2.Stream的distinct
跟下面程式碼關係不大
public static void main(String[] args) {
//Stream: 支援並行化 操作集合元素
//除了迭代器,我們能否在遍歷集合元素期間 對集合進行新增 刪除 修改等操作?
//不可以。 ConcurrentModificationException
//併發?
//並行?
//正在吃飯 有人打電話
//1. 邊吃飯 邊打電話 並行
//2. 吃了一口飯 與別人打電話 併發 cpu 上下文的切換時間 短---->專案中: 高併發(叢集 負載均衡)
//在遍歷過程中 刪除符合條件的多個元素資料
List<User> userList = new ArrayList<>(10);
Collections.addAll(userList,
new User(1, "jim1"),
new User(10, "jim11"),
new User(8, "jim3"),
new User(7, "jim4"));
System.out.println(userList);
// userList.parallelStream().distinct()
//刪除name中包含1的物件 //不支援 報錯
// userList.forEach(user->{
// if(user.getName().contains("1")){
// userList.remove(user);
// }
// });
//1.獲得集合物件的Stream例項(集合的所有的元素儲存到Stream的物件中)
Stream<User> userStream = userList.parallelStream();
userStream.filter(new Predicate<User>() {
@Override
public boolean test(User user) {
return !user.getName().contains("1");//過濾下來名字裡麵包含1
}
});
userStream = userStream.filter(user -> !user.getName().contains("1"));
//將過濾下來的元素 儲存到集合裡面去(收集起來)
userList = userStream.collect(Collectors.toList());
//簡寫
userList = userList.parallelStream().filter(user -> !user.getName().contains("1")).collect(Collectors.toList());
// System.out.println(userStream.count());
System.out.println(userList);
}
相關文章
- rust-algorithms:8-堆排序RustGo排序
- 8-字串的壓縮儲存字串
- 實戰8-滑塊驗證
- 8-使用者互動Scanner
- Pytest學習筆記8-引數化筆記
- Java學習筆記8-資料型別Java筆記資料型別
- 更換IDEA專案的JAVA版本(8->11),IdeaJava
- 連載 8-拆解 - 微服務有哪些被測屬性微服務
- 8-佇列的鏈式儲存結構的操作佇列
- 【linux】驅動-8-一文解決裝置樹Linux
- 20234105 2024- 8- 17暑期第七週學習總結
- 【Java集合】1 集合概述Java
- Guava集合--新集合型別Guava型別
- Guava集合--Immutable(不可變)集合Guava
- Collection集合、List集合及其方法
- Hash Map集合和Hash Set集合
- 程式碼隨想錄——棧與佇列8-前K個高頻元素佇列
- L2-005 集合相似度【集合】
- 【Java集合原始碼剖析】Java集合框架Java原始碼框架
- 【JAVA集合】JAVA集合框架及其常用方法Java框架
- 集合容器
- DataTransferItemList 集合
- Map集合
- java集合Java
- 集合sum
- 集合框架框架
- redis集合Redis
- [ARKit]8-對裸眼3D效果一次不太成功的嘗試3D
- 【java】【集合】陣列和集合的基本概述Java陣列
- Java集合 - 集合知識點總結概述Java
- Java集合詳解(一):全面理解Java集合Java
- Java程式設計基礎17——集合(List集合)Java程式設計
- List集合(ArrayList-LinkedList);Set集合(HashSet-TreeSet)
- 【Java集合】單列集合Collection常用方法詳解Java
- 洛谷題單指南-集合-P1621 集合
- 年度文章集合 | 最全微前端集合【建議收藏】前端
- 泛型方法、初始集合和集合的遍歷泛型
- Map集合&&Map集合的不同遍歷【keySet()&&entrySet()】