集合:
1)可以动态保存任意多个对象,使用比较方便!2)提供了一系列方便的操作对象的方法:add、remove、set、get等3)使用集合添加,删除新元素的示意代码-简洁了
集合的框架体系:
Java
的集合类很多,主要分为两大类,如图 :
[
背下来
]:
package com.hspedu.collection_;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author 韩顺平
* @version 1.0
*/
public class Collection_ {
@SuppressWarnings({"all"})
public static void main(String[] args) {
//老韩解读
//1. 集合主要是两组(单列集合 , 双列集合)
//2. Collection 接口有两个重要的子接口 List Set , 他们的实现子类都是单列集合
//3. Map 接口的实现子类 是双列集合,存放的 K-V
//4. 把老师梳理的两张图记住
//Collection
//Map
ArrayList arrayList = new ArrayList();
arrayList.add("jack");
arrayList.add("tom");
HashMap hashMap = new HashMap();
hashMap.put("NO1", "北京");
hashMap.put("NO2", "上海");
}
}
Collection
接口遍历对象方式
2-for
循环增强
List
接口和常用方法:
List
接口基本介绍:
List
接口的常用方法:
package com.hspedu.list_;
import java.util.ArrayList;
import java.util.List;
/**
* @author 韩顺平
* @version 1.0
*/
public class ListMethod {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三丰");
list.add("贾宝玉");
// void add(int index, Object ele):在 index 位置插入 ele 元素
//在 index = 1 的位置插入一个对象
list.add(1, "韩顺平");
System.out.println("list=" + list);
// boolean addAll(int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来
List list2 = new ArrayList();
list2.add("jack");
list2.add("tom");
list.addAll(1, list2);
System.out.println("list=" + list);
// Object get(int index):获取指定 index 位置的元素
//说过
// int indexOf(Object obj):返回 obj 在集合中首次出现的位置
System.out.println(list.indexOf("tom"));//2
// int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置
list.add("韩顺平");
System.out.println("list=" + list);
System.out.println(list.lastIndexOf("韩顺平"));
// Object remove(int index):移除指定 index 位置的元素,并返回此元素
list.remove(0);
System.out.println("list=" + list);
// Object set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换. list.set(1, "玛丽");
System.out.println("list=" + list);
// List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合
// 注意返回的子集合 fromIndex <= subList < toIndex
List returnlist = list.subList(0, 2);
System.out.println("returnlist=" + returnlist);
}
}
List
的三种遍历方式
[ArrayList, LinkedList,Vector]:
Listror.Java1)方式一:使用iteratorIterator iter = col.iterator();while(iter.hasNext())(Object o = iter.next();132)方式二:使用增强forfor(Object o:col)(3)方式三:使用普通forfor int i=0;i<list.sizeD;i++){Object object = list.get(i);System.out.println(object);说明:使用LinkedList完成使用方式和ArrayList一样
ArrayList
底层结构和源码分析:
ArrayList
的注意事项:
1)permits all elements,including null,ArrayList 可以加入null,并且多个2)ArrayList 是由数组来实现数据存储的[后面老师解读源码]3)ArrayList 基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码.在多线程情况下,不建议使用ArrayList
ArrayList
的底层操作机制源码分析
(
重点,难点
.):
1)ArrayList中维护了一个Object类型的数组elementData.[debug看源码]transient Object[] elementData;//transient 表示瞬间,短暂的,表示该属性不会被序列号2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。老师建议:自己去debug一把我们的ArrayList的创建和扩容的流程.
Vector
底层结构和源码剖析:
1 Vector
的基本介绍:
1)Vector类的定义说明
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
2)Vector底层也是一个对象数组,protected Object[]elementData;
3) Vector 是线程同步的,即线程安全,Vector类的操作方法带有
public synchronized E get(int index) (if (index >= elementCount)throw new ArraylndexOutOfBoundsException(index);
return elementData(index);
4)在开发中,需要线程同步安全时,考虑使用Vector
Vector
和
ArrayList
的比较:
LinkedList
底层结构:
LinkedList
的全面说明:
1)LinkedList底层实现了双向链表和双端队列特点2)可以添加任意元素(元素可以重复),包括null3)线程不安全,没有实现同步
LinkedList
的底层操作机制:
ArrayList
和
LinkedList
比较:
Set
接口和常用方法:
Set
接口基本介绍 :
Set
接口的常用方法:
和
List
接口一样
, Set
接口也是
Collection
的子接口,因此,常用方法和
Collection
接口一样
.
Set
接口的遍历方式:
同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。1.可以使用迭代器2.增强for3.不能使用索引的方式来获取
package com.hspedu.set_;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@SuppressWarnings({"all"})
public class SetMethod {
public static void main(String[] args) {
//解读
//1. 以 Set 接口的实现类 HashSet 来讲解 Set 接口的方法
//2. set 接口的实现类的对象(Set 接口对象), 不能存放重复的元素, 可以添加一个 null
//3. set 接口对象存放数据是无序(即添加的顺序和取出的顺序不一致)
//4. 注意:取出的顺序的顺序虽然不是添加的顺序,但是他的固定. Set set = new HashSet();
set.add("john");
set.add("lucy");
set.add("john");//重复
set.add("jack");
set.add("hsp");
set.add("mary");
set.add(null);//
set.add(null);//再次添加 null
for(int i = 0; i <10;i ++) {
System.out.println("set=" + set);
}
//遍历
//方式 1: 使用迭代器
System.out.println("=====使用迭代器====");
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
set.remove(null);
//方式 2: 增强 for
System.out.println("=====增强 for====");
for (Object o : set) {
System.out.println("o=" + o);
}
//set 接口对象,不能通过索引来获取
}
}
Set
接口实现类
-HashSet:
HashSet
的全面说明:
1)HashSet实现了Set接口2)HashSet实际上是HashMap,看下源码.(图)public HashSet(){map = new HashMap<>();3)可以存放null值,但是只能有一个null4)HashSet不保证元素是有序的,取决于hash后,再确定索引的结果.(即,不保证存放元素的顺序和取出顺序一致)5)不能有重复元素/对象.在前面Set接口使用已经讲过
Set
接口实现类
-LinkedHashSet:
LinkedHashSet
的全面说明:
1)LinkedHashSet是HashSet的子类LinlcedHashSet«E»2)LinkedHashSet 底层是一个LinkedHashMap,底层维护了一个数组+双向链表3)LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。4)LinkedHashSet 不允许添重复元素
Map
接口常用方法:
package com.hspedu.map_;
import java.util.HashMap;
import java.util.Map;
/**
* @author
* @version 1.0
*/
@SuppressWarnings({"all"})
public class MapMethod {
public static void main(String[] args) {
//演示 map 接口常用方法
Map map = new HashMap();
map.put("邓超", new Book("", 100));//OK
map.put("邓超", "孙俪");//替换-> 一会分析源码
map.put("王宝强", "马蓉");//OK
map.put("宋喆", "马蓉");//OK
map.put("刘令博", null);//OK
map.put(null, "刘亦菲");//OK
map.put("鹿晗", "关晓彤");//OK
map.put("hsp", "hsp 的老婆");
System.out.println("map=" + map);
// remove:根据键删除映射关系
map.remove(null);
System.out.println("map=" + map);
// get:根据键获取值
Object val = map.get("鹿晗");
System.out.println("val=" + val);
// size:获取元素个数
System.out.println("k-v=" + map.size());
// isEmpty:判断个数是否为 0
System.out.println(map.isEmpty());//F
// clear:清除 k-v
//map.clear();
System.out.println("map=" + map);
// containsKey:查找键是否存在
System.out.println("结果=" + map.containsKey("hsp"));//T
}
}
class Book {
private String name;
private int num;
public Book(String name, int num) {
this.name = name;
this.num = num;
}
}
Map
接口遍历方法:
>Map遍历方式案例演示MapFor.java1)containsKey:查找键是否存在2)keySet:获取所有的键3)entrySet:获取所有关系k-v4)values:获取所有的值
package com.hspedu.map_;
import java.util.*;
@SuppressWarnings({"all"})
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("邓超", "孙俪");
map.put("王宝强", "马蓉");
map.put("宋喆", "马蓉");
map.put("刘令博", null);
map.put(null, "刘亦菲");
map.put("鹿晗", "关晓彤");
//第一组: 先取出 所有的 Key , 通过 Key 取出对应的 Value
Set keyset = map.keySet();
//(1) 增强 for
System.out.println("-----第一种方式-------");
for (Object key : keyset) {
System.out.println(key + "-" + map.get(key));
}
//(2) 迭代器
System.out.println("----第二种方式--------");
Iterator iterator = keyset.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
//第二组: 把所有的 values 取出
Collection values = map.values();
//这里可以使用所有的 Collections 使用的遍历方法
//(1) 增强 for
System.out.println("---取出所有的 value 增强 for----");
for (Object value : values) {
System.out.println(value);
}
//(2) 迭代器
System.out.println("---取出所有的 value 迭代器----");
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
Object value = iterator2.next();
System.out.println(value);
}
//第三组: 通过 EntrySet 来获取 k-v
Set entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//(1) 增强 for
System.out.println("----使用 EntrySet 的 for 增强(第 3 种)----");
for (Object entry : entrySet) {
//将 entry 转成 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
//(2) 迭代器
System.out.println("----使用 EntrySet 的 迭代器(第 4 种)----");
Iterator iterator3 = entrySet.iterator();
while (iterator3.hasNext()) {
Object entry = iterator3.next();
//System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
//向下转型 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
}
Map
接口实现类
-HashMap:
1 HashMap
小结:
1)Map接口的常用实现类:HashMap、Hashtable和Properties。2)HashMap是Map接口使用频率最高的实现类。3)HashMap是以key-val对的方式来存储数据(HashMap$Node类型)[案例Entry]4) key 不能重复,但是值可以重复,允许使用null键和null值。5)如果添加相同的key,则会覆盖原来的key-val,等同于修改.(key不会替换,val会替换)6)与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.(jdk8的hashMap 底层数组+链表+红黑树)7)HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有svnchronized
HashMap
底层机制及源码剖析:
扩容机制[和HashSet相同]1) HashMap底层维护了Node类型的数组table,默认为null+2)当创建对象时,将加载因子(loadfactor)初始化为0.75.3)当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key和准备加入的是否等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,做山应处理。如果添加时发现容量不够,则需要扩容。4)第1次添加,则需要扩容table容量为16,临界值(threshold)为12(16*0.75)5)以后再扩容,则需要扩容table容量为原来的2倍(32),临界值为原来的2倍,即24,依次类推6)在Java8中,如果一条链表的元素个数超过TREEIFY THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)
Map
接口实现类
-Hashtable:
HashTable
的基本介绍:
1)存放的元素是键值对:即K-V2)hashtable的键和值都不能为null,否则会抛出NullPointerException3)hashTable使用方法基本上和HashMap一样4)hashTable是线程安全的(synchronized),hashMap是线程不安全的5)简单看下底层结构HashTable的应用案例//下面的代码是否正确,如果错误,为什么? HashTableExercise.javaHashtable table = new Hashtable();//oktable.put("john", 100);//oktable.put(null,100);//异常table.put("john",null);//异常table.put("lucy", 100);//oktable.put("lic", 100);//oktable.put("lic",88);//替换System.out.println(table);
Hashtable
和
HashMap
对比:
Map
接口实现类
-Properties:
1.Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。2.他的使用特点和Hashtable类似3.Properties 还可以用于从 xxx.properties 文件中,加载数据到Properties类对象,并进行读取和修改4.说明:工作后 xxx.properties 文件通常作为配置文件,这个知识点在IO流举例,有兴趣可先看文章4httos://www.cnblogs.com/xudong-bupt/p/3758136.html
总结
-
开发中如何选择集合实现类
(
记住
):
Collections
工具类:
1)Collections是一个操作 Set、List 和Map等集合的工具类2)Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等
排序操作:(均为
static
方法
):
1)reverse(List):反转 List 中元素的顺序2)shuffle(List):对List 集合元素进行随机排序3) sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序4)sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序5)swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
排序操作:(均为
static
方法
)