集合
集合類的特點:提供一種存盤空間可變的存盤模型,存盤的資料容量可以隨時發生改變,
Collection:單列(介面)
概述:
是單列集合的頂層介面,表示一組物件,這些物件也成為Cpllection的元素
JDK不提供此介面的任何直接實作,它提供更具體的子介面(如List和Set)實作
實作方法
//創建Collection集合的物件
Collection<String> c = new ArrayList<String>();
//添加元素:boolean add (E e)
c.add("hello");
c.add("My");
c.add("java");
//輸出集合物件
System.out.println(c);
常用方法
| 方法名 | 說明 |
|---|---|
| boolean add(E e) | 添加元素 |
| boolean remove(Object o) | 從集合中移除指定的元素 |
| void clear() | 清空集合中的元素 |
| boolean contains(Object o) | 判斷集合中是否存在指定的元素 |
| boolean isEmpty() | 判斷集合是否為空 |
| int size() | 集合的長度,也就是集合中元素的個數 |
Collection<String> c=new ArrayList<>();
//添加元素
/*System.out.println(c.add("Hello"));
System.out.println(c.add("World"));
System.out.println(c.add("World"));
*/
/*選擇關鍵字 ctrl+B查看原始碼
alt+7 打開一個視窗,查看該類的所有資訊
ArrayList原始碼:
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
永遠回傳true */
c.add("hello");
c.add("World");
c.add("World");
//移除指定元素
System.out.println(c.remove("World"));//true
System.out.println(c.remove("world"));//false
//清空集合所有元素
c.clear();
//判斷集合中是否存在指定元素
System.out.println(c.contains("World"));//true
System.out.println(c.contains("javaSE"));//false
//判斷集合是否為空
System.out.println(c.isEmpty());
//查看集合長度
System.out.println(c.size());//3
//輸出集合物件
System.out.println(c);
遍歷
Iterator:迭代器,集合的專用遍歷方式
-
Iterator<E> iterator():回傳此集合中的迭代器,通過集合的iterator方法得到 -
迭代器是通過集合的iterator()方法得到的,所以我們說他是依賴集合而存在的
常用方法
E next():回傳迭代中的下一個元素boolean hasNext():如果迭代器具有更多的元素,回傳trueCollection<String> c=new ArrayList<>(); c.add("hello"); c.add("World"); c.add("World"); //回傳此集合中的迭代器,通過集合的iterator方法得到 Iterator<String> it = c.iterator(); //原始碼: public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E>{ ... } System.out.println(it.next()); System.out.println(it.next()); System.out.println(it.next()); System.out.println(it.next());//拋出例外:NoSuchElementException 元素不存在 //判斷是否還有元素;hasNext() if (it.hasNext()){ System.out.println(it.next()); } if (it.hasNext()){ System.out.println(it.next()); } if (it.hasNext()){ System.out.println(it.next()); } if (it.hasNext()){ System.out.println(it.next()); } //用while改進判斷 while(it.hasNext()){ //System.out.println(it.next()); String s=it.next(); System.out.println(s); }@Description TODO 創建一個存盤學生物件的集合,存盤3個學生物件,使用程式實作在控制臺遍歷該集合 Collection<Student> students=new ArrayList<>(); Student s1=new Student("鐘無艷",201,21,"男",80.99); Student s2=new Student("諸葛亮",202,22,"男",99.99); Student s3=new Student("伽羅",203,23,"女",80.80); students.add(s1); students.add(s2); students.add(s3); Iterator<Student> it = students.iterator(); while (it.hasNext()) { Student s =it.next(); System.out.println(s.getName() + ',' + s.getId() + ',' + s.getAge() + ',' + s.getSex() + ',' + s.getGrade()); }?
List:可重復(介面)
概述
- 有序集合(也稱為序列),用戶可以精確控制串列中每個元素的插入位置,用戶可以通過整數索引訪問元素,并搜索串列中的元素
- 與Set集合不同,串列通常允許重復的元素
List<String> l=new ArrayList<>();
l.add("hello");
l.add("world");
l.add("java");
l.add("world");
System.out.println(l);
Iterator<String> it = l.iterator();
while (it.hasNext()){
String s=it.next();
System.out.println(s);
}
特有方法:
| 方法名 | 說明 |
|---|---|
| void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
| E remove(int index) | 洗掉指定索引處的元素,回傳被洗掉的元素 |
| E set(int index,E element) | 修改指定索引處的元素,回傳被修改的元素 |
| E get(int index) | 回傳指定索引處的元素 |
List<String> list=new ArrayList<>();
list.add("hello");
list.add("world");
list.add("java");
list.add(1,"javaee");//[hello, javaee, world, java]
list.add(11,"javaee");//[hello, javaee, world, java] //越界例外IndexOutOfBoundsException
list.remove(1); //[hello, world, java]
list.set(1,"javaee"); //[hello, javaee, java]
System.out.println(list.get(1)); //javaee
System.out.println(list);
//用for回圈使用get()方法遍歷集合
for (int i = 0; i<list.size(); i++)
{
String s=list.get(i);
System.out.println(s);
}
@Description TODO 創建一個存盤學生物件的集合,存盤3個學生物件,使用程式實作在控制臺遍歷該集合
List<Student> list = new ArrayList<>();
Student s1 = new Student("鐘無艷", 201, 21, "男", 80.99);
Student s2 = new Student("諸葛亮", 202, 22, "男", 80.99);
Student s3 = new Student("伽羅", 203, 23, "男", 80.99);
list.add(s1);
list.add(s2);
list.add(s3);
Iterator<Student> it = list.iterator();
while (it.hasNext()) {
Student s =it.next();
System.out.println(s.getName() + ',' + s.getId() + ',' + s.getAge() + ',' + s.getSex() + ',' + s.getGrade());
}
System.out.println("--------------------");
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(s.getName() + ',' + s.getId() + ',' + s.getAge() + ',' + s.getSex() + ',' + s.getGrade());
}
并發修改例外
@Description TODO 遍歷集合,得到每一個元素,檢查是否有“world”這個元素,如果有,就添加一個“javaee”元素
List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("java");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s=it.next();//拋出例外:ConcurrentModificationException:并發修改例外
if (s.equals("world")){
list.add("javaee");
}
}
for (int i = 0; i < list.size() ; i++) {
String s=list.get(i);
if (s.equals("world")){
list.add("javaee");
}
}//succeed
System.out.println(list);
原始碼如下:
public interface List<E>{
Iterator<E> iterator();
boolean add(E e);
}
public abstract class AbstractList<E>{
protected int modCount = 0;
}
public class ArrayList<E> extends AbstractList<E> implements List<E>{
public E get(int index) {
Objects.checkIndex(index, size);
return elementData(index);
}//沒有實際修改集合的次數和預期修改集合的次數的判斷
public boolean add(E e) {
modCount++;//實際修改集合次數++
add(e, elementData, size);
return true;
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int expectedModCount = modCount;
/*
modCount:實際修改集合的次數
expectedModCount:預期修改集合的次數
開始都為0
*/
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = https://www.cnblogs.com/hackertyper/p/ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
if (modCount != expectedModCount)//判斷是否相等,modCount++,與expectedModCount不相等
throw new ConcurrentModificationException();
}
}
}
ListIterator :串列迭代器
-
通過List集合的listIterator()方法得到,所以說它是List集合特有的迭代器
-
繼承于Iterator,用于程式員沿任意方向遍歷串列的迭代器,在迭代期間修改串列,并獲取串列中迭代器的當前位置,
-
常用方法
E next():回傳迭代中的下一個元素boolean hasNext():如果迭代具有更多元素,回傳trueE previus:回傳串列中上一個元素bookean hasPrevious():如果串列迭代器在相反方向遍歷串列時具有更多元素,則回傳truevoid add(E e):將指定的元素插入串列
List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("java");
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()){
String s = lit.next();
System.out.println(s);
}
System.out.println("-----------");
while(lit.hasPrevious()){
String s =lit.previous();
System.out.println(s);
}
System.out.println("-------------");
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
String s= lit.next();
if(s.equals("world")){
lit.add("javaee"); //success
}
}
//使用串列迭代器實作添加元素,并無例外
System.out.println(list);
-
增強for回圈 :簡化陣列和Collection集合的遍歷
實作Iterable介面的類允許其物件稱為增強型for陳述句的目標
內部原理是一個Iterator迭代器
-
格式:
for(元素資料型別 變數名:陣列或Collection集合){ //在此處使用變數即可,該變數就是元素 }int[] arr={1,2,3,4,5}; for(int i:arr){ System.out.println(i); }int[] arr = {1, 2, 3, 4, 5}; for (int i : arr) { System.out.println(i); }System.out.println("--------"); String[] stArray = {"hello", "world", "java"}; for (String s : stArray) { System.out.println(s); } System.out.println("-----------"); List<String> list=new ArrayList<>(); list.add("hello"); list.add("world"); list.add("java"); for (String s:list){ System.out.println(s); } System.out.println("-----------"); //內部是一個Iterator迭代器 for (String s:list){ if (s.equals("world")){ list.add("javaee"); //并發修改例外:ConcurrentModificationException;因此內部是一個Iterator迭代器 } }?```
-
至此,共有三種方式遍歷集合:①迭代器—集合特有的遍歷方式,②普通for—帶有索引的遍歷方式,③增強for—最方便的遍歷方式,
- 若只為了遍歷,選擇增強for的方式
- 若使用到了索引,則選擇普通for的方式
資料結構:
? 堆疊:先進后出
? 佇列:先進先出
? 陣列:查詢快、增刪慢的模型
? 鏈表:增刪快、查詢慢的模型
?ArrayList(實作類)
? ArrayList的底層資料結構是陣列 ,查詢快、增刪慢
LinkedList(實作類)
? LinkedList的底層資料結構是鏈表,查詢慢,增刪快
? LinkedList集合的特有方法
| 方法名 | 說明 |
|---|---|
| public void addFirst(E e) | 在該串列開頭插入指定元素 |
| public void addLast(E e) | 將指定的元素追加到此串列的末尾 |
| public E getFirst() | 回傳此串列中的第一個元素 |
| public E getLast() | 回傳此串列中的最后一個元素 |
| public E removeFirst() | 從此串列中洗掉并回傳第一個元素 |
| public E removeLast() | 從此串列中洗掉并回傳最后一個元素 |
LinkedList<String> linkedList =new LinkedList<>();
linkedList.add("hello");
linkedList.add("world");
linkedList.add("java");
System.out.println(linkedList);
//在該串列開頭插入指定元素
linkedList.addFirst("javaee");
//將指定的元素追加到此串列的末尾
linkedList.addLast("javaee");
//回傳此串列中的第一個元素
System.out.println(linkedList.getFirst());
//回傳此串列中的最后一個元素
System.out.println(linkedList.getLast());
//從此串列中洗掉并回傳第一個元素
System.out.println(linkedList.removeFirst());
//從此串列中洗掉并回傳最后一個元素
System.out.println(linkedList.removeLast());
System.out.println(linkedList);
//分別使用ArrayList和LinkedList完成存盤字串遍歷
//創建集合物件ArrayList
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("hello");
arrayList.add("world");
arrayList.add("java");
Iterator<String> it = arrayList.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
System.out.println("---------------");
for (int i = 0; i < arrayList.size(); i++) {
String s = arrayList.get(i);
System.out.println(s);
}
System.out.println("---------------");
for (String s : arrayList) {
System.out.println(s);
}
System.out.println("---------------");
//創建集合物件LinkedList
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("Hello");
linkedList.add("World");
linkedList.add("Java");
Iterator<String> it1 = linkedList.iterator();
while(it1.hasNext()){
String s= it1.next();
System.out.println(s);
}
System.out.println("---------------");
for (int i =0;i<linkedList.size();i++){
String s= linkedList.get(i);
System.out.println(s);
}
System.out.println("---------------");
for(String s:linkedList){
System.out.println(s);
}
System.out.println("---------------");
}
Set:不可重復(介面)
特點:
- 不包含重復元素的集合
- 沒有帶索引的方法,所以不能使用普通for回圈遍歷
HashSet:實作Set介面,對集合的迭代順序不作任何保證
//創建集合物件
Set<String> set= new HashSet<>();
set.add("hello");
set.add("world");
set.add("java");
set.add("world");//最終只會添加一個world
for (String s:set){
System.out.println(s);//world java hello
}
哈希值
哈希值是JDK根據物件的地址或者字串或者數字算出來的int型別的數值
Object類中的public int hashCode()可以獲取物件的哈希值
物件的哈希值的特點 :
-
同一個物件多次呼叫hashCode()方法回傳的哈希值是相同的
-
默認情況下,不同物件的哈希值是不相同的
-
通過方法重寫,可以實作讓不同物件的哈希值相同
HashSet(實作類)
特點 :
- 底層資料結構是哈希表
- 對集合的迭代順序不做任何保證,也就是說不保證存盤和去除的元素順序一致
- 沒有帶索引的方法,所以不能使用普通for回圈遍歷
- 由于是Set集合,所以是不包含重復元素的集合
HashSet<String> hashSet=new HashSet<>();
hashSet.add("hallo");
hashSet.add("world");
hashSet.add("java");
for (String s :hashSet){
System.out.println(s);
}
HashSet集合保證元素唯一性原始碼分析
HashSet<String> hashSet=new HashSet<>();
hashSet.add("hallo");
hashSet.add("world");
hashSet.add("java");
-------------------------------------------------
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
//hash值和元素的hashCode()方法相關
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果哈希表美亞由初始化,就對其初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//根據物件的哈希值計算物件的存盤位置,如果該位置沒有元素就存盤元素
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
/*
存入的元素和以前的元素比較哈希值
如果哈希值不同,會繼續向下執行,把元素添加到集合
如果哈希值相同,會呼叫物件的equals()方法進行比較
如果回傳false,說明元素重復,不存盤
*/
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = https://www.cnblogs.com/hackertyper/p/e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
LinkedHashSet(實作類)
- 繼承于HashSet
- 由哈希表和鏈表實作的Set介面,具有可預測的迭代次序
- 由鏈表保證元素有序,也就是說元素的存盤和取出順序是一致的
- 由哈希表保證元素唯一,也就是說沒有重復的元素
LinkedHashSet<String> linkedHashSet=new LinkedHashSet<>();
linkedHashSet.add("hello");
linkedHashSet.add("world");
linkedHashSet.add("java");
linkedHashSet.add("world");
for (String s:linkedHashSet){
System.out.println(s);//hello world java
}
TreeSet(實作類)
特點:
- 元素有序,這里的順序不是指存盤和去除的順序,而是按照一定的規則進行排序,具體排序方式取決于構造方法
TreeSet():根據其元素的自然排序進行排序TreeSet(Comparator comparator):根據指定的比較器進行排序
- 沒有帶索引的方法,所以不能使用for回圈遍歷
- 由于是Set集合,所以不包含重復元素的集合
//創建集合
TreeSet<Integer> treeSet=new TreeSet<>();
treeSet.add(15);
treeSet.add(44);
treeSet.add(55);
treeSet.add(40);
treeSet.add(10);
treeSet.add(15);
for (Integer i:treeSet){
System.out.print(i+" "); //10 15 40 44 55 自然排序
}
自然排序Comparable的使用
- 用TreeSet集合存盤自定義物件,無參構造方法使用的是自然排序對元素進行排序的
- 自然排序,就是讓元素所屬的類實作Comparable介面,重寫compareTo(To)方法
- 重寫方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫
public class Student implements Comparable<Student> {
@Override
public int compareTo(Student s) {
//return 0;
//return 1;
//return -1;
int num = this.age - s.age;
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
---------------------------------------------------------------------
return 0:輸出結果為duheng,21 認為s2和s1是同一個元素
return 1:輸出結果為duheng,21 love,18 chencui,22 認為s1比s2大,因此按照存盤順序輸出
return -1:輸出結果為chencui,22 love,18 duheng,21 認為s2比s1大,因此按照存盤順序逆向輸出
return num = this.age-s.age: love,18 duheng,21 chencui,22 this即為s2,按照升序排列
return num = s.age-this.age: chencui,22 duheng,21 love,18 this即為s2,按照降序排列
int num = this.age - s.age;
int num2 = num == 0 ? this.name.compareTo(s.name) : num; //年齡從小到大排序,年齡相同時,按照姓名的字母順序排序
return num2;
}
}
/* * 存盤學生物件并遍歷,創建TreeSet集合使用無參構造方法
* 按照年齡從小到大排序,年齡相同時,按照姓名的字母順序排序*/
public static void main(String[] args) {
//創建集合物件
TreeSet<Student> ts = new TreeSet<>();
Student s1=new Student("dyxx",21);
Student s2=new Student("love",18);
Student s3=new Student("zhulu",22);
Student s4=new Student("sss",18);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
for (Student s:ts){
System.out.println(s.getName()+","+s.getAge());//Exception ClassCastException Comparable
}
//因此需要讓Student實作Comparable介面,并重寫方法compareTo方法
}
比較器排序Comparator的使用
- 用TreeSet集合存盤自定義物件,無參構造方法使用的是自然排序對元素進行排序的
- 比較器排序,就是讓集合構造方法接收Comparator的實作類物件,重寫compareTo(To1,To2)方法
- 重寫方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫
//創建集合物件
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return num2;
}
});
Student s1=new Student("duheng",21);
Student s2=new Student("chencui",22);
Student s3=new Student("love",18);
ts.add(s1);
ts.add(s2);
ts.add(s3);
for (Student s:ts){
System.out.println(s.getName()+","+s.getAge());//Exception ClassCastException Comparable
}
泛型
將型別由原來的具體的型別引數化,然后在使用/呼叫時傳入具體的型別,這種引數型別可以用在類、方法和介面中,分別為泛型類、泛型方法、泛型介面
定義格式=:
- <型別>:指定一種型別的格式,這里的型別可以看成時形參
- <型別1,型別2...>:指定多種型別的格式,多種型別之間用逗號隔開,這里的型別可以看成時形參
- 將來具體呼叫時候給定的型別可以看成是實參,并且實參的型別只能是參考資料型別
好處:
- 把運行時期的問題提前到了編譯期間
- 避免了強制型別轉換
//創建集合物件
//Collection c=new ArrayList();
Collection<String> c = new ArrayList<>();//100報錯:提前報錯 迭代器中型別自動為String型別,不需要強轉
c.add("hello"); //將字串賦值給object——向上轉型
c.add("world");
c.add("java");
//c.add(100);//自動封裝為Integer
// Iterator t = c.iterator();
Iterator<String> t = c.iterator();
while (t.hasNext()) {
// Object obj=t.next();
// System.out.println(obj);
// String s= (String) t.next();//100:ClassCastException:因此課采用泛型來解決
String s = t.next();
System.out.println(s);
}
泛型類
定義格式:
-
格式:修飾符 class 類名<型別>{}
-
范例:
public class Generic<T>{}? 此處的T可以隨便寫為任意標識,常見的如T、E、K、V等形式的引數常用于表示泛型
public class GenericClassDemo<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
public static void main(String[] args) {
Generic<String> g1 = new Generic<String>();
g1.setT("杜恒");
System.out.println(g1.getT());
Generic<Integer> g2 = new Generic<Integer>();
g2.setT(30);
System.out.println(g1.getT());
}
泛型方法
定義格式:
- 格式:修飾符<型別> 回傳值型別 方法名(型別 變數名){}
- 范例:
public <T> void show(T t){}
/*public class Generic{
public void show(String s){
System.out.println(s);
}
public void show(Integer i){
System.out.println(i);
}
public void show(Boolean b){
System.out.println(b);
}*/
/*public void show(T t){
System.out.println(t);
}
}
*/
/*public class Generic<T>{
public<> void show(T t){
System.out.println(t);
}
}
*/
public class Generic{
public <T> void show(T t){ //泛型方法
System.out.println(t);
}
}
public static void main(String[] args) {
/*Generic<String> g1 = new Generic<String>();
g1.show("杜恒");
Generic<Integer> g2 = new Generic<Integer>();
g1.show(22);
Generic<Boolean> g3 = new Generic<Boolean>();
g1.show(true);*/
Generic g = new Generic();
g.show("諸葛亮");
g.show(21);
g.show(true);
g.show(12.34);
}
泛型介面
定義格式:
- 格式:修飾符interface 介面名<型別>{}
- 范例:
public interface Generic<T>{}
public interface Generic<T> {
void show(T t);
}
public class GenericImpl<T> implements Generic<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
public class GenericInterfaceDemo {
public static void main(String[] args) {
Generic<String> g1 = new GenericImpl<>();
g1.show("諸葛亮");
Generic<Integer> g2 = new GenericImpl<>();
g2.show(20);
}
}
型別通配符
為了表示各種泛型List的父類,可以使用型別通配符
- 型別通配符:<?>
List<?>:表示元素型別未知的List,他的元素可以匹配任何的型別- 這種帶通配符的List僅表示它是各種泛型List的父類,并不能把元素添加到其中
如果我們不希望List<?>是任何泛型List的父類,只希望它代表某一類泛型List的父類,可以使用型別通配符的上限
- 型別通配符上限:
<?extends 型別> List<? extends Number>:他表示的型別是Number或者其子型別
除了可以指定型別通配符的上限,也可以指定型別通配符的下限
- 型別通配符下限:
<?super 型別> List<? super Number>:他表示的型別是Number或者其父型別
//型別通配符List<?>
List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
List<?> list3 = new ArrayList<Integer>();
System.out.println("---------");
//型別通配符上限
List<? extends Number> list4= new ArrayList<Object>();//上限是Number,不能是Number父類Object
List<? extends Number> list5 = new ArrayList<Number>();
List<? extends Number> list6 = new ArrayList<Integer>();
//型別通配符下限
List<? super Number> list7 =new ArrayList<Object>();
List<? super Number> list8 =new ArrayList<Number>();
List<? super Number> list9 =new ArrayList<Integer>();//下限是Number,不能是Number的子類Integer
可變引數
可變引數又稱引數個數可變,用作方法的形參出現,那么方法引數個數就是可變的了
- 格式:修飾符 回傳值型別 方法名(資料型別... 變數名){}
- 范例:public static int sum(int... a){}
public static void main(String[] args) {
System.out.println(sum(10, 20));
System.out.println(sum(10, 20, 30));
System.out.println(sum(10, 20, 30, 40));
System.out.println(sum(10, 20, 30, 40, 50));
System.out.println(sum(10, 20, 30, 40, 50, 60));
System.out.println(sum(10, 20, 30, 40, 50, 60, 70));
}
public static int sum(int... a) {//a是陣列
int sum = 0;
for (int i : a) {
sum += i;
}
return sum;
}
public static int sum(int b,int... a){//一個方法有多個引數,包含可變引數的情況下,可變引數放在最后
return 0;
}
/*public static int sum(int a,int b){
return a+b;
}
public static int sum(int a,int b,int c){
return a+b+c;
}
public static int sum(int a,int b,int c,int d){
return a+b+c+d;
}
*/
可變引數的使用
Arrays工具類中有一個靜態方法:
public static <T> List<T> asList(T... a):回傳由指定陣列支持的固定大小的串列- 回傳的集合不能做增刪操作,可以修改
List介面中有一個靜態方法:
public static <E> List<E> of(E... elements):回傳包含任意數量元素的不可變串列- 回傳的集合不能做增刪改操作
Arrays工具類中有一個靜態方法:
public static <E> Set<E> of(E... elements):回傳一個包含任意數量元素的不可變集合- 在給元素時不能給重復元素
- 回傳的集合不能做增刪操作,沒有修改方法
List<String> list = Arrays.asList("hello", "world", "java");//這樣做就不用一個個add了
list.add("javaee"); //UnsupportedOperationException:不支持所請求的操作
list.remove("java"); //UnsupportedOperationException
list.set(1,"javaee");//success 陣列大小固定,不能添加洗掉,但是內容可改變
System.out.println(list);
List<String> list = List.of("hello", "world", "java","world");
list.add("javaee"); //UnsupportedOperationException:不支持所請求的操作
list.remove("java"); //UnsupportedOperationException
list.set(1,"javaee");//UnsupportedOperationException of:增刪改都不可以
System.out.println(list);
Set<String> set=Set.of("hello", "world", "java","world"); //IllegalArgumentException:非法或不適當的引數
Set<String> set=Set.of("hello", "world", "java");
set.add("javaee");//UnsupportedOperationException
set.remove("javaee");//UnsupportedOperationException
//set無索引,沒有set方法
Map:雙列(介面)
概述:
interface Map<K,V>K:鍵的型別;V:值的型別- 將鍵映射到值的物件;不能包含重復的鍵;每個鍵可以映射到最多一個值
- 舉例:學生的學號和姓名
- 201 諸葛
- 202 亮
- 203 鐘無艷
創建Map集合的物件
- 多型的方式
- 具體的實作類HashMap
//創建集合物件
Map<String,String> map=new HashMap<>();
map.put("194070201","諸葛亮");//put(K key, V value)將指定的值與此映射中的指定鍵相關聯
map.put("194070202","鐘無艷");
map.put("194070203","伽羅");
map.put("194070203","劉");//當鍵重復時,就會修改元素,替代掉以前的值{194070201=杜恒, 194070202=杜, 194070203=陳}
System.out.println(map); //{201=劉, 202=王, 203=李}
Map集合的基本功能
| 方法名 | 說明 |
|---|---|
| V put(K key,V value) | 添加元素 |
| V remove(Object key) | 更具鍵洗掉鍵值對元素 |
| void clear() | 移除所有的鍵值對元素 |
| boolean containsKey(Object key) | 判斷集合是否包含指定的鍵 |
| boolean containsValue(Object value) | 判斷集合是否包含指定的值 |
| boolean isEmpty() | 判斷集合是否為空 |
| int size() | 集合的長度,也就是集合中鍵值對的個數 |
//創建集合物件
Map<String, String> map = new HashMap<>();
//添加元素
map.put("張無忌","趙敏");
map.put("郭靖","黃蓉");
map.put("楊過","小龍女");
//System.out.println(map.remove("郭靖"));//黃蓉 {楊過=小龍女, 張無忌=趙敏}
//System.out.println(map.remove("郭襄"));//null {楊過=小龍女, 張無忌=趙敏}
//map.clear();// {}慎重使用
//System.out.println(map.containsKey("郭靖"));//true
//System.out.println(map.containsKey("郭襄"));//false
//System.out.println(map.containsValue("小龍女"));//true
//System.out.println(map.containsValue("郭芙"));//false
System.out.println(map.isEmpty());//false
System.out.println(map.size());//3
//輸出集合物件
System.out.println(map);
Map集合的獲取功能
| 方法名 | 說明 |
|---|---|
V get(Object key) |
根據鍵獲取值 |
Set<K> keySet() |
獲取所有鍵的集合 |
Collection<V> values() |
獲取所有值的集合 |
Set<Map.Empty<K,V>> entrySet() |
獲取所有鍵值對物件的集合 |
//創建集合物件
Map<String, String> map = new HashMap<>();
//添加元素
map.put("張無忌","趙敏");
map.put("郭靖","黃蓉");
map.put("楊過","小龍女");
System.out.println(map.get("張無忌"));//趙敏
System.out.println(map.get("張三豐"));//null
Set<String> keyset = map.keySet();
for(String key:keyset){
System.out.println(key); //楊過 郭靖 張無忌
}
Collection<String> values = map.values();
for (String value:values){
System.out.println(value); //小龍女 黃蓉 趙敏
}
Map集合的遍歷
-
方式1
我們剛才存盤的元素時成對出現的,所以可以把Map看成是一個夫妻對的集合
遍歷思路
- 把所有的丈夫集中起來
- 遍歷丈夫的集合,獲取到每一個丈夫
- 根據丈夫去找對應的妻子
轉換為Map集合中的操作:
- 獲取所有鍵的集合,用keySet()方法實作
- 遍歷鍵去找值,獲取到每一個鍵,用增強for實作
- 根據鍵去找值,用get(object key)方法實作
//創建集合物件 Map<String, String> map = new HashMap<>(); //添加元素 map.put("張無忌","趙敏"); map.put("郭靖","黃蓉"); map.put("楊過","小龍女"); Set<String> keySet = map.keySet(); for (String key:keySet){ String value = https://www.cnblogs.com/hackertyper/p/map.get(key); System.out.println(key+","+value); } -
方式2
我們剛才存盤的元素時成對出現的,所以可以把Map看成是一個夫妻對的集合
遍歷思路
- 獲取所有結婚證的集合
- 遍歷結婚證的集合,獲取到每一個結婚證
- 根據結婚證去找對應的丈夫妻子
轉換為Map集合中的操作:
-
獲取所有鍵值對物件的集合,用entrySet()方法實作
Set<Map.entry<K,V>> entrySet():獲取所有鍵值對物件的結合 -
遍歷鍵值對物件的集合,獲取到每一個鍵每一個鍵值對物件
用增強for實作,得到每一個Map.Entry
-
根據鍵值對物件獲取值
- 用getKey()得到鍵
- 用getValue()得到值
//創建集合物件 Map<String, String> map = new HashMap<>(); //添加元素 map.put("張無忌", "趙敏"); map.put("郭靖", "黃蓉"); map.put("楊過", "小龍女"); Set<Map.Entry<String, String>> entrySet = map.entrySet(); for (Map.Entry<String, String> s : entrySet) { String key = s.getKey(); String value = https://www.cnblogs.com/hackertyper/p/s.getValue(); System.out.println(key +"," + value); }
HashMap(實作類)
實體:鍵是Student 值是String
HashMap<String,Student> hm=new HashMap<>();
Student s1= new Student("林青霞",30);
Student s2= new Student("張曼玉",35);
Student s3= new Student("王祖賢",36);
hm.put("001",s1);
hm.put("002",s2);
hm.put("003",s3);
Set<String> keySet = hm.keySet();
for(String key:keySet){
Student value=https://www.cnblogs.com/hackertyper/p/hm.get(key);
System.out.println(key+","+value.getName()+','+value.getAge());
}
System.out.println("---------");
Set<Map.Entry<String, Student>> entries = hm.entrySet();
for (Map.Entry<String,Student> me:entries){
String key=me.getKey();
Student value=https://www.cnblogs.com/hackertyper/p/me.getValue();
System.out.println(key+","+value.getName()+','+value.getAge());
}
實體:鍵是String 值是Student
public class HashMapDemo {
public static void main(String[] args) {
HashMap<Student, String> hm = new HashMap<>();
Student s1 = new Student("林青霞", 30);
Student s2 = new Student("湯家鳳", 35);
Student s3 = new Student("張曼玉", 36);
Student s4 = new Student("張曼玉", 36);
hm.put(s1, "西安");
hm.put(s2, "北京");
hm.put(s3, "重慶");
hm.put(s3, "重慶");
hm.put(s4, "上海");
Set<Student> keySet = hm.keySet();
for (Student key : keySet) {
String value = https://www.cnblogs.com/hackertyper/p/hm.get(key);
System.out.println(key.getName() +',' + key.getAge() + ',' + value);
}
}
}
public class Student {
private String name;
private int age;
public Student(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;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
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;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/492931.html
標籤:Java
