Java學習之集合篇
Java學習之集合篇
0x00 前言
上篇文章的常用類,其實就已經講到了,這個ArrayList集合,但是ArrayList只是集合中的其中一種,那這篇文章就來講講關於集合的一些物件。
0x01 集合概念
先來了解一些什麼是集合,
下面來貼一段集合的描述。
集合:java中的一種容器,可以用來儲存多個數據。
在這裡要理清楚的一個概念,陣列的長度是固定的,一旦定義了就無法改名,而集合是可以改變的。
集合儲存的都是物件,物件的型別可以不一樣,但是陣列只能儲存基本資料型別。
集合架構
集合按照儲存的結構可以分為兩類,分別是單列集合(java.util.Collection)和雙列集合(java.util.Map),這裡就先來講講collection集合。
collection是單列集合類的根介面,用於儲存符合某種規則的元素,他有兩個主要的子介面,分別是java.util.List
和java.util.Set
。
來說說這兩個子介面的區別,List的特點是儲存的元素有序,元素可以重複。而set的特點是元素無序、儲存的元素不可重複。List的介面主要實現類有ArrayList 和LinkedList,Set介面的主要實現類有HashSet和TreeSet
0x02 Collection
Collection是所有單列集合的父介面,也就是說collection是所有單列集合的最頂層的。因此在Collection中定義了單列集合(List和Set)通用的一些方法,這些方法可用於操作所有的單列集合。
* `public boolean add(E e)`: 把給定的物件新增到當前集合中 。 * `public void clear()` :清空集合中所有的元素。 * `public boolean remove(E e)`: 把給定的物件在當前集合中刪除。 * `public boolean contains(E e)`: 判斷當前集合中是否包含給定的物件。 * `public boolean isEmpty()`: 判斷當前集合是否為空。 * `public int size()`: 返回集合中元素的個數。 * `public Object[] toArray()`: 把集合中的元素,儲存到陣列中。
這裡使用一下這幾個方法
public class Input {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("123");
list.add("321");
list.remove("123");
boolean a = list.isEmpty();
System.out.println(a);
System.out.println(list);
}
}
0x03 迭代器
在我們想要遍歷的時候,通常都會用到for迴圈。但是這裡遍歷集合,java給我們提供了Iterator介面,也就是迭代器,該介面也是集合的一種。
首先來了解迭代的概念:
Collection集合元素的通用獲取方式。在取元素之前先要判斷集合中有沒有元素,如果有,就把這個元素取出來,繼續在判斷,如果還有就再取出出來。一直把集合中的所有元素全部取出。這種取出方式專業術語稱為迭代。
常用方法:
public E next():返回迭代的下一個元素。
public boolean hasNext():如果仍有元素可以迭代,則返回 true。
程式碼例項:
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("123");
list.add("321");
list.add("baidu");
list.add("google");
Iterator<String> is = list.iterator();
while (is.hasNext()){
String i = is.next();
System.out.println(i);
}
}
這裡使用while迴圈的條件是判斷集裡面是否有值,然後再讀取值賦值給i。程式碼的整體還是比較簡單的。
0x04 增強for迴圈
增強for迴圈是我們在遍歷集合裡面,用的最多的,語法簡單。他的他的內部原理其實也是個Iterator迭代器。
格式:
for(元素的資料型別 變數 : Collection集合or陣列){
...
}
通常只進行遍歷元素,增強for裡面不能做增刪的操作。
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("123");
list.add("321");
list.add("baidu");
list.add("google");
for (String s : list) {
System.out.println(s);
}
}
在使用IDEA編寫的時候普遍會有提示。
0x05 泛型
泛型是一種未知的資料型別,如果我們不知道什麼資料型別的時候就可以使用泛型。
程式碼格式:
修飾符 class 類名<代表泛型的變數> { }
含有泛型的類:
public class Demo11<R> {
private R r;
public R getR() {
return r;
}
public void setR(R r) {
this.r = r;
}
}
main方法程式碼:
public class DemoMain {
public static void main(String[] args) {
Demo11<String> str = new Demo11<>();
str.setR("123");
System.out.println(str.getR());
}
}
含有泛型的方法:
類:
public <R> void method(R r){
System.out.println(r);
}
}
main方法程式碼:
public static void main(String[] args) {
Demo11 abc = new Demo11();
abc.method("abc");
}
呼叫方法時,確定泛型的型別
含有泛型的介面:
程式碼例項:
定義格式:
修飾符 interface介面名<代表泛型的變數> { }
public interface MyInterface<R> {
public abstract void add(R r);
public abstract R getR();
}
實現介面類:
public class MyInterfaceimpl implements MyInterface<String> {
@Override
public void add(String s) {
System.out.println(s);
}
@Override
public String getR() {
return null;
}
}
這裡是在實現接口裡面,確定泛型型別。
如果說始終無法確定型別,也可以在建立物件的時候來確定該型別。
實現類:
public class MyInterfaceimpl<R> implements MyInterface<R> {
@Override
public void add(R r) {
System.out.println(r);
}
@Override
public R getR() {
return null;
}
}
main方法程式碼:
public static void main(String[] args) {
MyInterfaceimpl<String> str = new MyInterfaceimpl<>();
str.add("123");
}
在建立物件的時候,確定了型別為string型別。
0x06 List 介面
List介面是Collection的子介面,
List接口裡面允許出現重複元素得,在程式中可以通過索引來訪問。
List介面儲存的資料是有序的。
public class DemoMain {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("狗子");
list.add("二狗");
list.add("狗蛋");
list.add(1,"狗蛋子");
list.remove(1);
System.out.println(list);
}
}
0x07 set介面
set介面也是繼承了Collection介面,也是單列集合。
set介面中元素無序,並且都會以某種規則保證存入的元素不出現重複。
set介面的實現類有:
AbstractList、 AbstractSequentialList、 ArrayList, AttributeList、 CopyOnWriteArrayList、 LinkedList, RoleList、 RoleUnresolvedList、Stack、 Vector。
Hashset
Hashset所儲存的元素是不可重複的,並且元素都是無序的(即存取順序不一致)。
這就來用hashset這個實現類來演示
public static void main(String[] args) {
HashSet<String> list = new HashSet<>();
list.add("123");
list.add("785");
list.add(new String("23"));
for (String s : list) { System.out.println(s);
}
}
LinkHashSet
hashset是為了保證元素唯一性,如果想要有序這時候就需要用到LinkedHashSet。
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.add("123");
set.add("12");
set.add("12999");
set.add("1453");
set.add("543");
for (String s : set) {
System.out.println(s);
}
}
可變引數
這裡來穿插一點關於可變引數的小知識點。
如果我們定義一個方法需要接受多個引數,並且多個引數型別一致。
定義格式:
修飾符 返回值型別 方法名(引數型別... 形參名){ }
public static void main(String[] args) {
int[] arr = {1,2,3,4};
method(1,1,1,1);//使用可變引數方法
method1(arr);//不使用可變引數方法
}
private static void method1(int[] args) {
for (int arg : args) {
System.out.println(arg);
}
}
private static void method(int... args) {
System.out.println(args);
}
這裡可以看到2種定義方式,一個是使用了可變引數的方式,這裡就可以直接省去先定義一個數組再對其傳入的麻煩。
注意:如果在方法書寫時,這個方法擁有多引數,引數中包含可變引數,可變引數一定要寫在引數列表的末尾位置。
0x08 collections 類
這個和前面講到的collection的是2個東西,conetcion是一個單列集合的介面,而conections是集合的工具類。
該類是個靜態類,可以直接使用類名來呼叫。
常用方法:
- 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> )`:將集合中元素按照指定規則排序。
程式碼示例:
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 123, 1243, 1354, 123);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
以往的集合都是通過add一個一個的去新增資料,但是collections可以一次新增多個數據。
0x09 Map集合
在collection的一些協和,元素都是單獨存在的,想集合儲存一個個元素的方式存在。
而map中的集合,元素是成對存在的。每個元素都由鍵和值組成,通過鍵可以找到對應的值。
已知實現類:
AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable, IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings, TabularDataSupport, TreeMap, UIDefaults, WeakHashMap
下面就來看最常用的幾個實現類
Hashmap
HashMap:儲存資料採用的雜湊表結構,元素的存取順序不能保證一致。由於要保證鍵的唯一、不重複,需
要重寫鍵的hashCode()方法、equals()方法。
map介面中的方法:
public V put(K key, V value) : 把指定的鍵與指定的值新增到Map集合中。
public V remove(Object key) : 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的
值。
public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
public Set<K> keySet() : 獲取Map集合中所有的鍵,儲存到Set集合中。
public Set<Map.Entry<K,V>> entrySet() : 獲取到Map集合中所有的鍵值對物件的集合(Set集合)
Map介面中的集合都有兩個泛型變數,在使用時,要為兩個泛型變數賦予資料型別。兩個泛型變數的數
據型別可以相同,也可以不同。
程式碼:
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("小明","18");
map.put("小j","48");
map.put("小x","88");
map.put("小g","98");
System.out.println(map.get("小明"));
}
使用put方法時,若指定的鍵(key)在集合中沒有,則沒有這個鍵對應的值,返回null,並把指定的鍵值新增到集合中。指定的鍵(key)在集合中存在,則返回值為集合中鍵對應的值(該值為替換前的值),並把指定鍵所對應的值,替換成指定的新值。
map集合遍歷
map裡面提供了一個獲取所以鍵值的方法keyset。供我們遍歷使用。
public static void main(String[] args) {
HashMap<String,Integer> map = new HashMap<>();
map.put("狗子",18);
map.put("二狗",17);
map.put("狗蛋",16);
Set<String> keys = map.keySet();
for (String key : keys) {
Integer value = map.get(key);
System.out.println(value);
}
}
遍歷鍵值對
Entry將鍵值對的對應關係封裝成了物件。即鍵值對物件,這樣我們在遍歷Map集合時,就可以從每一個鍵值對(Entry)物件中獲取對應的鍵與對應的值。
既然是鍵值的物件,那麼肯定會提供獲取的方法。
public K getKey():獲取Entry物件中的鍵。
public V getValue()`:獲取Entry物件中的值。
程式碼:
public static void main(String[] args) {
// 建立Map集合物件
HashMap<String, String> map = new HashMap<String,String>();
// 新增元素到集合
map.put("狗子", "18");
map.put("狗蛋", "17");
map.put("二狗", "16");
// 獲取 所有的 entry物件 entrySet
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry); //遍歷
System.out.println("key"+entry.getKey());
System.out.println("value"+entry.getValue());
}
}
LinkedHashMap
Hashmap的存放是無序的,如果需要有序儲存資料的話,就需要用到LinkedHashMap。
public static void main(String[] args) {
LinkedHashMap<String,String> list = new LinkedHashMap<>();
list.put("狗子","18");
list.put("二狗","17");
list.put("狗蛋","16");
Set<Map.Entry<String, String>> entries = list.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
}
0x10 結尾
關於集合的一些東西也寫完了,其實當中還有集合的一些資料結構沒有寫進去,打算把資料結構這個東西單獨提取出來寫一篇文章。