1 容器的基本概念
圖解
- List有序可重復
- Set無序不可重復,相同的會被覆蓋
- Map鍵值對,通過一個對象找另一個對象
容器的概念
在Java當中,如果有一個類專門用來存放其它類的對象,這個類就叫做容器,或者就叫做集合,集合就是將若干性質相同或相近的類對象組合在一起而形成的一個整體
容器和數組的區別
- 數組的容量是有限制的,而Collection庫沒有這樣的限制,它的容量是可以自動調節的
2 collection接口
- collection是容器的根接口
- 定義了一些規則,這時候就體現了接口的意義
- 下面舉出幾個常用的方法,這些方法在其子類中都是擁有的
Collection<String> collection = new ArrayList<>();
// 添加一個元素
collection.add("zhaodi1");
collection.add("zhaodi2");
// 集合的大小
System.out.println(collection.size());
//集合是否為空
System.out.println(collection.isEmpty());
// 集合是否包含某個對象
System.out.println(collection.contains("zhaodi"));
// 集合轉化成數組
Object object[]=collection.toArray();
System.out.println(Arrays.toString(object));
// 從容器移除這個對象,記住這是移除不是刪除
collection.remove("zhaodi1");
System.out.println(collection.size());
3 List接口
ArrayList,LinkedList,Vector
- ArrayList 查詢速度快,修改,刪除,插入速度很慢,因為底層是數組實現的
- LinkedList 查詢速度慢,修改,刪除,插入速度很快,因為底層是鏈表
- Vector 線程安全,效率低
- 可以重復
package com.zhao.collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
/**
* ArrayList 查詢速度快,修改,刪除,插入速度很慢,因為底層是數組實現的
* LinkedList 查詢速度慢,修改,刪除,插入速度很快,因為底層是鏈表
* Vector 線程安全,效率低
* @author zhao_di
*
*/
public class Demo01 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("zhaodi");
list.add("is");
list.add("good");
list.add("man");
list.add(new Date());
list.remove("is");
//清空容器
list.clear();
list.add(1234);//1234被自動裝箱成Integer!!!!
System.out.println(list.get(1));//is
System.out.println(list.size());//
// 獲取元素,返回值是Object
Object string = list.get(0);
// 某個位置設置一個元素
list.set(list.size()-1, "dd");
}
}
自己實現ArrayList,LinkedList
ArrayList
package com.demo.utils.Test_Collection;
/**
* @author zhaod
* @description
* 模仿實現ArrayList,底層是數組實現的,具體的操作依賴System.copy這個方法
* 1、add 新增一個元素
* 2、get 獲取指定index的元素
* 3、remove 更具index刪除元素
* 4、set 指定index出賦值
*
* @date 2018/5/9 11:15
*/
public class ArrayListDemo {
/**
* 容器的大小
*/
private int size;
/**
* 數組元素
*/
private Object[] elementData;
public ArrayListDemo() {
this(10);
}
public ArrayListDemo(int initialCapacity) {
if (initialCapacity > 0) {
elementData = new Object[initialCapacity];
}
}
/**
* 容器的大小
*
* @return
*/
public int size() {
return size;
}
/**
* 添加元素
*
* @param object
* @return
*/
public boolean add(Object object) {
if (size >= elementData.length) {
Object[] newElementDatas = new Object[size * 2];
System.arraycopy(elementData, 0, newElementDatas, 0, elementData.length);
elementData = newElementDatas;
}
elementData[size] = object;
size++;
return true;
}
/**
* 獲取元素
*
* @param index 索引,從0開始
* @return
*/
public Object get(int index) {
if (index >= size || index < 0) {
throw new RuntimeException("index is wrong");
}
return elementData[index];
}
/**
* 刪除元素
*
* @param index
* @return
*/
public Object remove(int index) {
if (index >= size || index < 0) {
throw new RuntimeException("index is wrong");
}
System.arraycopy(elementData, index + 1, elementData, index, size - index - 1);
// gc 回收垃圾
elementData[--size] = null;
return elementData[index];
}
/**
* 修改index 對應元素的值
*
* @param index
* @param element
* @return
*/
public Object set(int index, Object element) {
if (index >= size || index < 0) {
throw new RuntimeException("index is wrong");
}
elementData[index] = element;
return element;
}
public static void main(String[] args) {
ArrayListDemo list = new ArrayListDemo(1);
list.add("11111");
list.add("22222");
list.set(0, "0000");
System.out.println(list.get(0));
}
}
LinkedList
package com.demo.utils.Test_Collection;
/**
* @author zhaod
* @description LinkedList 主要是采用鏈表實現的
* @date 2018/5/9 15:32
*/
/**
* 節點類
*/
class Node {
// 前一個節點
public Node previous;
// 改節點存儲的數據
public Object object;
// 下一個節點
public Node next;
public Node() {
}
public Node(Node previos, Object object, Node next) {
super();
this.previous = previos;
this.object = object;
this.next = next;
}
}
public class LinkedListDemo {
private Node first;
private Node last;
private int size;
public int size() {
return size;
}
/**
* 添加元素
* @param object
*/
public void add(Object object) {
if (first == null) {
Node n = new Node();
n.previous = null;
n.object = object;
n.next = null;
first = n;
last = n;
} else {
Node n = new Node();
n.previous = last;
n.object = object;
n.next = null;
last.next = n;
last = n;
}
size++;
}
/**
* 獲取元素
* @param index
* @return
*/
public Object get(int index) {
// 帶查找的節點
Node temp = null;
if (first == null) {
return null;
} else {
temp = first;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp.object;
}
}
/**
* 刪除元素
* @param index
* @return
*/
public Object remove(int index) {
// 待刪除的節點
Node temp = null;
if (first != null) {
temp = first;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
}
if (temp != null) {
// 刪除節點的上一個節點
Node up = temp.previous;
// 待刪除節點的下一個節點
Node down = temp.next;
up.next = down;
down.previous = up;
temp = null;
size--;
}
return null;
}
public static void main(String[] args) {
LinkedListDemo linkedLis = new LinkedListDemo();
linkedLis.add("one");
linkedLis.add("two");
linkedLis.add("three");
linkedLis.remove(0);
for (int i = 0; i < linkedLis.size(); i++) {
System.out.println(linkedLis.get(i));
}//
}
}
4 Map接口
HashMap,HashTable
- HashMap效率高,線程不安全,HashTable線程安全,效率低
- 實現Map接口的類用來存儲鍵key值value對
- Map接口的實現類有HashMap和TreeMap
- Map類中存儲使用鍵標識,所以鍵不可以重復哦
package com.zhao.collection;
import java.util.HashMap;
import java.util.Map;
/**
* Map
* @author zhao_di
*
*/
public class Demo02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map map = new HashMap();
// 放置元素
map.put("1", "zhaodi");
// 如果鍵重復 那么會覆蓋之前的值
map.put("1", "zhaodi2");
// 根據鍵獲取元素
String str = (String)map.get("1");
map.size();
// 移除
// map.remove("1");
// 是否包含鍵
System.out.println(map.containsKey("1"));
// 是否包含值
System.out.println(map.containsValue("zhaodi2"));
// 清楚容器
map.clear();
System.out.println(map.get("1"));
}
}
自己實現HashMap,HashTable
HashMap
- 采用數組實現
package com.demo.utils.Test_Collection;
/**
* @author zhaod
* @description 自定義實現Map功能1.0
* 采用數組實現的效率很低,下個版本采用hash表實現
* @date 2018/5/10 9:17
*/
public class HashMapDemo {
Entry[] entries = new Entry[1000];
int size;
/**
* 存鍵值對key-value
*
* @param key
* @param value
*/
public void put(Object key, Object value) {
Entry entry = new Entry(key, value);
// 重復的鍵覆蓋值
for (int i = 0; i < size; i++) {
if (entries[i].key.equals(key)) {
entries[i].value = value;
}
}
entries[size++] = entry;
}
/**
* 根據key獲取value
*
* @param key
* @return
*/
public Object get(Object key) {
for (int i = 0; i < size; i++) {
if (entries[i].key.equals(key)) {
return entries[i].value;
}
}
return null;
}
/**
* map是否包含指定的key
*
* @param key
* @return
*/
public boolean containKey(Object key) {
for (int i = 0; i < size; i++) {
if (entries[i].key.equals(key)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
HashMapDemo map = new HashMapDemo();
map.put("1", "one");
map.put("2", "two");
System.out.println(map.get("2"));
}
}
class Entry {
public Object key;
public Object value;
public Entry(Object key, Object value) {
this.key = key;
this.value = value;
}
}
- 采用數組+鏈表(hash表實現)
package com.demo.utils.Test_Collection;
import java.util.LinkedList;
/**
* @author zhaod
* @description 采用hash表實現hashMap,
* 效率高
* @date 2018/5/10 15:42
*/
public class HashMapDemo2 {
LinkedList[] array = new LinkedList[1000];
int size;
/**
* 存值
* @param key
* @param value
*/
public void put(Object key, Object value) {
int a = key.hashCode() % 1000;
Entry entry = new Entry(key, value);
if (array[a] == null) {
LinkedList list = new LinkedList();
list.add(entry);
array[a] = list;
} else {
LinkedList list = array[a];
for(int i=0;i<list.size();i++){
Entry e = (Entry) list.get(i);
if(entry.key.equals(key)){
e.value = value;
return;
}
}
array[a].add(entry);
}
}
public Object get(Object key) {
//return entries[key.hashCode()%1000].value;
int a = key.hashCode()%1000;
if(array[a]!=null){
LinkedList list = array[a];
for(int i=0;i<list.size();i++){
Entry entry = (Entry) list.get(i);
if(entry.key.equals(key)){
return entry.value;
}
}
}
return null;
}
public static void main(String[] args) {
HashMapDemo2 map = new HashMapDemo2();
map.put(1, 1);
map.put(2, 2);
map.put(2, 3);
System.out.println(map.get(1));
System.out.println(map.get(2));
}
}
5 Set
- Set接口是Collection接口的子接口,Set接口沒有提供額外的方法
- Set接口的特性是容器類中的元素是沒有順序的,而且不可以重復哦
- 常用的實現類有HashSet,TreeSet,底層是HashMap實現的
HashSet
public static void main(String[] args) {
Set set = new HashSet();
set.add("22");
set.add("22");// 重復
String string = new String("22");
String string2 = new String("22");
set.add(string);// 重復
set.remove("22");
System.out.println(string==(string2));
System.out.println(set.size());//2
}
自己實現HashSet
package com.demo.utils.Test_Collection;
import java.util.HashMap;
/**
* @author zhaod
* @description 1、Set是collection接口的子接口,和list的同一級別
* <p>
* 2、Set的特點就是無序,不可重復
* <p>
* 3、常用的實現類有HashSet,treeSet
* 4、底層就是采用map實現的,set的值存在map的key位置上,value處賦值static final Object
* @date 2018/5/11 10:39
*/
public class HashSetDemo {
private HashMap map;
/**
* map中的value
*/
private static final Object PRESENT = new Object();
/**
* 構造方法
*/
public HashSetDemo() {
map = new HashMap();
}
/**
* 添加元素,set的值存放在map的key上面
* @param object
*/
public void add(Object object) {
map.put(object, PRESENT);
}
/**
* 獲取set的大小
* @return
*/
public int size(){
return map.size();
}
public static void main(String[] args) {
//Set<String> set = new HashSet<String>();
HashSetDemo set = new HashSetDemo();
set.add("zhaodi");
set.add("tom");
set.add("rose");
set.add("jack");
}
}
6 遍歷容器
- 所有實現了collection接口的容器類都有一個iterator方法用以返回一個實現了Iterator接口的對象
- Iteration對象叫做迭代器,用以方便的對實現對容器內元素的便利操作
遍歷List
1、通過索引
- 可以刪除集合中的元素
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
arrayList.add("4");
// for循環
for(int i=0;i<arrayList.size();i++){
arrayList.remove(i);
//arrayList.removeAll(arrayList);
System.out.println(arrayList.get(i));
}
2、通過增強for循環
- 底層還是迭代器實現的,不提供方法刪除集合中的元素
for(String str: arrayList){
System.out.println(str);
}
3、通過迭代器
- 迭代器相當於給集合上了鎖,在此期間只可以通過迭代器的remove()刪除元素
- 不可以通過集合提供的remove刪除元素
Iterator<String> iterator = arrayList.iterator();
while(iterator.hasNext()){// 判斷是否有元素沒有被遍歷
String string = iterator.next();
//System.out.println(iterator.next());// 返回游標當前位置的元素並將游標移動到下一個位置
/*if(string.equals("2")){
iterator.remove();
}*/
iterator.remove();// 刪除游標左邊的元素,在執行完next之后該操作只可以執行一次
}
4、lambda遍歷
。。。。
List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add("hello_" + i);
}
list.forEach(s -> {
System.out.println(s);
});
。。。。
遍歷Map
1、增強for循環遍歷
- 這種方式不可以刪除map里面的數據
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(1, "1");
map.put(2, "2");
map.put(3, "3");
map.put(4, "4");
// 方式一 :這是最常見的並且在大多數情況下也是最可取的遍歷方式。在鍵值都需要時使用。
for(Map.Entry<Integer, String> entry : map.entrySet()){
System.out.println(entry.getKey() + entry.getValue());
}
// 方法二: 如果只需要map中的鍵或者值,你可以通過keySet或values來實現遍歷,而不是用entrySet。
// 性能稍微好點 快10%
for(Integer key : map.keySet()){
System.out.println("key:"+key);
}
for(String val: map.values()){
System.out.println("value:"+val);
}
2、迭代器遍歷
- 可以進行刪除元素
Iterator<Map.Entry<Integer, String>> entries = map.entrySet().iterator();
while(entries.hasNext()){
Map.Entry<Integer, String> entry = entries.next();
System.out.println("3key:"+entry.getKey()+";3value:"+entry.getValue());
if(entry.getKey() == 1){
entries.remove();
}
}
Iterator<Map.Entry<Integer, String>> entries1 = map.entrySet().iterator();
while(entries1.hasNext()){
//如果這里的entries1不換個名字,那么接着上面的hasNext,會出現指針在最后一個位置
Map.Entry<Integer, String> entry = entries1.next();
System.out.println("4key:"+entry.getKey()+";3value:"+entry.getValue());
}
- 總結
- 迭代器遍歷可提供了方法刪除元素
- 增強for循環的底層就是迭代器,不可以采用集合本身的remove刪除元素