1.集合
*集合分为:单列集合、双列集合
*Collection 接口有两个重要子接口 List Set,实现子类为单列集合
*Map接口实现子类为双列集合,存放的King–Value
*集合体系图
1.1 Collection接口
1.接口实现类特点
1.collection实现子类可以存放多个元素,每个元素可以为Object
2.有些Collection的实现类,可以存放重复的元素,有些不可以
3.有些Collection实现类,有些为有序的(List),有些不是有序(Set)
4.Collection接口没有直接实现子类,而是通过,Set和List来实现的
2.Collection接口和常用方法
1.add
//添加单个元素
List list = new ArrayList();
list.add("jack");
list.add(10);
list.add(true);
System.out.println(list);//[jack,10,true]
2.remove
//删除指定元素
list.remove(0);//删除第一个元素
list.remove("jack");//指定删除某个元素
3.contains
//查找元素是否存在
list.contains("jack");//boolean返回值
4.size
//获取元素个数
list.size();//返回集合元素个数
5.isEmpty
//判断是否为空
list.isEmpty();//返回boolean类型
6.clear
//清空
list.clear();
7.addAll
//添加多个元素
ArrayList list2 = new ArrayList();
list2.add(10);
list2.add(20);
list.addAll(list2);
8.containsAll
//查找多个元素是否都存在
list.containsAll(list2);//返回boolean类型
9.removeAll
//删除多个元素
list.removeAll(list2);//删除和list2中元素相同的元素
3.Collection接口遍历元素方式
*使用Iterator(迭代器)
1.Iterator对象称为迭代器,主要用于遍历Collection中的元素
2.所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器
3.Iterator仅用于遍历集合,Iterator本身并不存放对象
1.迭代器执行原理
Iterator iterator = coll.iterator();//得到一个集合的迭代器
//hasNext():判断是否还有下一个元素
while(iterator.hasNext()){
//next():1.下移 2.将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
Collection col = new ArrayList();
col.add(new Book("三国演义","罗贯中",10.1));
col.add(new Book("小李飞刀","古龙",5.1));
//1.先得到col对应的迭代器
Iterator iterator = col.iterator();
//使用while循环遍历
while(iterator.hasNext()) {//判断是否还有数据
//返回下一个元素,类型为Object
Object next = iterator.next();
}
//如果需要再次遍历,需要重置迭代器
iterator = col.iterator();//重置迭代器
2.for循环增强
*增强for循环,可以代替Iterator迭代器
*特点:增强for就是简化版的iterator,本质一样,只能用于遍历集合或数组
*基本语法
for(元素类型 元素名:集合名或数组名) {
访问元素
}
for(Object book : col) {
System.out.println("book=" + book);
}
4.List接口常用方法
1.List集合类中的元素有序(即添加顺序和取出顺序一致)。
2.List集合中每个元素都有其对应的顺序索引,即支持索引
3.List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
List list = new ArrayList();
list.add("jack");
list.add("marry");
//1.添加和取出顺序一致
System.out.println(list);//"jack""marry
//2.List集合中每个元素都有其对应的顺序索引,即支持索引
System.out.println(list.get(2));//索引从0开始,返回2号位置的元素
1.add
//list.add(int index ,Object ele)在index位置插入ele元素
List list = new ArrayList();
list.add(1,"jack");
2.addAll
//list.addAll(int dex, Collection eles);//在index位置开始将eles中的所有元素都添加进来
list.addAll(1,list2);
3.get
//get(int index) //获取指定位置的元素
4.indexOf
//int indexOf(Object obj) //返回obj在集合中首次出现的位置
int a = list.indexOf("Tom");
5.lastIndexOf
//int lastIndexOf(Object obj) //返回obj在当前集合中末次出现的位置
6.remove
//Object remove(int index) //移除指定index位置的元素,并返回此元素
list.remove(0);//删除0号位置的元素
7.set
//Object set(int index , Object ele) //设置指定index未知的元素为ele,相当于是替换
list.set(0,"jack");//替换0号位置为jack
8.subList
//List subList(int formIndex, int toIndex) //返回从fromIndex到toIndex位置的子集合
List list3 = list.subList(0,2);
//实际上返回0-1的字串,为左闭右开[0,2)
5.List的三种遍历方式
1.方式一:使用iterator
Iterator iter = col.iterator();
while(iter.hasNext()) {
Object o = iter.next();
System.out.println(o);
}
2.方式二:使用增强for
for(Object o:col) {
}
3.方式三:使用普通for
for(int i =0;i<list.size();i++) {
Object ob = list.get(i);
System.out.println(ob);
}
6.List接口
1.ArrayList注意事项
1.ArrayList容器可以放null(空值),并且可以放多个
ArrayList arraylist = new ArrayList();
arraylist.add(null);
2.ArrayList是由数组来实现数据存储的
3.ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高),多线程下,不建议使用
2.ArrayList底层操作机制源码分析
1.ArrayList中维护了一个Object类型的数组elementData
transient Object[] elementData;//transit 表示瞬间,表示该属性不会被序列号
2.当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍
3.如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍
3.Vector基本介绍
*Vector和ArrayList比较
4.LinkedList
1.LinkedList底层实现了双向链表和双端队列特点
2.可以添加任意元素(包括null)
3.线程不安全,没有实现同步
*LinkedList底层操作机制
1.LinkedList底层维护了一个双向链表
2.LinkedList中维护了两个属性
*first //首节点
*last //尾结点
3.每个节点(Node对象),里面又维护了
*prev //指向前一个
*next //指向后一个节点
最终实现双向链表
4.LinkedList的元素添加和删除,不是通过数组完成的,相对来说效率较高
class Node {
public Object item; //真正存放数据的地方
public Node next;
public Node pre;
public Node(Object name) {
this.item = name;
}
public String toString() {
return "Node name =" + item;
}
}
public class test01 {
public static void main(String[] args) {
Node jack = new Node("jack");
Node tom = new Node("tom");
Node hsp = new Node("老韩");
//连接三个节点,形成双向链表
//jack -> tom -> hsp
jack.next = tom;
tom.next = hsp;
hsp.pre = tom;
tom.pre = jack;
Node first = jack;//让first引用指向Jack,就是双向链表的头结点
Node last = hsp;//让lats引用指向hsp,就是双向链表的尾节点
//添加对象至链表
//1.先创建一个Node结点,name就是smith
Node smith = new Node("smith");
tom.next = smith;
smith.next = hsp;
hsp.pre = smith;
smith.pre = tom;
}
}
public class test01 {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(1);
linkedList.add(2);
System.out.println(linkedList);
//删除结点
linkedList.remove();//默认删除第一个结点
//修改某个结点对象
linkedList.set(1,999);//把1位置的值改为999
//得到某个结点对象
Object o = linkedList.get(1);//得到999;
//因为LinkedList实现了List接口,变量是为
Iterator iterator = linkedList.iterator();
while(iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
}
}
5.ArrayList和LinkedList比较
7.Set接口
1.无序(添加和取出的顺序不一致),没有索引
2.不允许重复元素,最多包含一个null
*Set常用方法和Collection接口一样
*Set接口遍历方式
同Collection遍历方式一样,因为Set接口是Collection接口子接口
1.使用迭代器Iterator
2.使用增强for
3.不能使用索引方式来获取
public class test01 {
public static void main(String[] args) {
Set set = new HashSet();
set.add("john");
set.add("lucy");
set.add("john");//重复
set.add(null);
System.out.println(set);
//遍历
Iterator iterator = linkedList.iterator();
while(iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
for(Object o : set) {
System.out.println(o);
}
//删除
set.remove(null); //删除指定元素
}
}
1.HashSet
*HashSet底层是HashMap,HashMap底层为(数组+链表+红黑树)
class Node {//结点,存放数据,可以指向下一个结点,从而形成链表
Object item;//存放数据
Node next;//指向下一个结点
}
public class test01 {
public static void main(String[] args) {
Node john = new Node("john",null);
table[2] = john;
Node jack = new Node("jack",null);
john.next = jack;//将Jack结点挂载到john
Node rose = new Node("Rose",null);
jack.next = rose;//将rose结点挂载到jack
Node lucy = new Node("lucy",null);
table[3] = lucy;//把lucy放到table表的索引为3的位置
}
}
2.LinkedHashSet
1.LinkedHashSet是HashSet子类
2.LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+ 双向链表
3.LinkedHashSet根据元素的hashCode值来决定元素存储位置,同时用链表维护元素的次序,这是跌元素看起来是以插入顺序保存的
4.不允许添加重复元素
3.TreeSet
Tree treeSet = new TreeSet();
//添加数据
treeSet.add("jack");
treeSet.add("tom");
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).compareTo((String) o2);
}
});//匿名内部类
8.Map接口
1.Map接口的特点
1.Map与Collection并列存在,用于保存具有映射关系的数据:Key - Value(双列元素)
Map map = new HashMap();
map.put("1","黄区");;//k-v
System.out.println(map);//{1=黄区}
2.Map中的Key和Value可以是任何引用类型的数据,会封装到HashMap$Node对象中
3.Map中的Key不允许重复,原因和HashSet一样,如果添加相同的key,则会覆盖原来的Key-val,等同于修改
4.Map中的Value可以重复
5.Map中的Key可以为Null,Value也可以为null,但是key为空只能有一个,Value为null,可以有多个
6.常用String类作为Map的key
7.key和value之间存在单向一对一关系,即通过指定的Key总能找到对应的value
//通过get方法,传入key,会返回对应的value
System.out.println(map.get("1"));//黄区
8.Map存放数据key-value示意图,一对k-v是放在一个Node中的,又因为Node实现了Entry接口
9.HashMap没有实现同步,线程不安全,方法没有做同步互斥,就是没有synchronized
2.Map接口和常用方法
*Map接口常用方法
1.put
//添加
Map map = new HashMap();
map.put("邓超",new Book("",100));
map.put("邓超","孙俪");
map.put("王宝强","马蓉");
2.remove
//根据键删除映射关系
map.remove("王宝强");//删除王宝强-马蓉
3.get
//根据键获取值
Object val = map.get("王宝强");//返回马蓉
4.size
//获取元素个数
map.size();
5.isEmpty
//判断个数是否为0
map.isEmpty();
6.clear
//清除
map.clear();
7.containsKey
//查找键是否存在
boolean is = map.containsKey("王宝强");//返回boolean类型
3.Map接口遍历方法
1.containsKey:查找键是否存在
2.keySet:获取所有的键
3.entrySet:获取所有关系
4.values:获取所有的值
Map map = new HashMap();
map.put("邓超",new Book("",100));
map.put("邓超","孙俪");
map.put("王宝强","马蓉");
//第一组:先取出所有的Key,通过key去除对应的value
Set keyset = map.keySet();
//1.增强for
for(Object key : keyset)
{
System.out.println(key + "-" map.get(key))
}
//2.通过迭代器
Iterator iterator = keyset.iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
//第二组:把所有的value取出
Collection values = map.values();
//这里可以使用所有的Collection使用的遍历方法
//1.增强for
for(Object value : values) {
System.out.println(value);
}
//2.迭代器
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,b>>
//1.增强for
for(Object entry : entrySet) {
//将entry转成Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" +m.getValue());
}
//2.迭代器
Iterator iterator3 = entrySet.iterator();
hwile(iterator3.hasNext()) {
Obejct entry = iterator3.next();
//向下转型 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" +m.getValue());
}
4.HashMap
*扩容与HashSet扩容机制一致
1.HashMap底层维护了Node类型的数组table,默认为Null
2.当创建对象时,将加载因子(LoadFactor)初始化为0.75
3.第一次添加,需要扩容table容量为16,临界值(threshold)为12
4.以后再扩容,则需要扩容table容量为原来的2被,临界值为原来的两倍,即24
5.Java8中,如果一条链表的元素个数超过8(TREEIFY_THRESHOLD),并且table大小大于或等于64(MIN_TREEIFY_CAPACITY),就会进行树化(红黑树)
5.HashTable
1.基本介绍
1.存放的元素是键值对:K-V
2.hashtable的键和值都不能为null,否则会抛出NullPointerException
3.hashTable的使用方法基本上和HashMap一样
4.hashTable是线程安全的(synchronized),hashMap是线程不安全的
*Hashtable和HashMap对比
6.Properties
1.Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据
2.他的使用特点和Hashtable类似
3.Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
//增加
//继承了HashTable
Properties properties = new Properties();
properties.put("john", 100);//k-v
properties.put("lucy", 100);
//通过k获取对应值
Object o = properties.get("lucy");//返回100
7.TreeMap
TreeMap treeMap = new TreeMap(new Comparator) {
@Override
public int compare(Object o1,Object o2) {
//按照传入的k(String)的大小进行排序
return ((String) o2).compareTo((String) o1);
}
});
treeMap.put("jack","杰克");
treeMap.put("tom","汤姆");
8.开发中如何选择集合实现类
9.Collections工具类
*Collections是一个操作Set、List和Map等集合的工具类
*Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改
*排序操作(均为static方法)
1.reverse(List)
:反转List中元素的顺序
List list = new ArrayList();
list.add("tom");
list.add("smith");
list.add("king");
//反转List中元素的顺序
Collections.reverse(list);
2.shuffle(List)
:对List集合元素进行随机排序
Collections.shuffle(list);
3.sort(List)
:根据元素的自然顺序对指定List集合元素按升序排序
Collections.sort(list);
4.sort(List, Comparator)
:根据指定的Comparator产生的顺序对List集合元素进行排序
Collections.sort(list,new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String)o1).length() - ((String)o2).length();
}
});
5.swap(List, int, int)
:将指定list集合中的i处元素和j处元素进行交换
Collections.swap(list,0,1);//交换0、1位置的元素
*查找,替换
1.Object max(Collection)
:根据元素的自然顺序,返回给定集合中最大的元素
System.out.println("自然顺序最大元素" + Collections.max(list));
2.Object max(Collection, Comparator)
:根据Comparator指定的顺序,返回给定集合中的最大元素
//返回长度最大的元素
Collections.max(list, new Comparator() {
@Override
public int compare(Object o1, Obejct o2)
{
return ((String)o1).length() - ((String)o2).length()
}
});
3.Object min(Collection) //类似最大
System.out.println("自然顺序最小元素" + Collections.min(list));
4.Object min(Collection,Comparator)
5.int frequency(Collection, Object)
:返回指定集合中指定元素的出现次数
System.out.println("tom出现的次数:" + Collections.frequency(list,"tom");)
6.void copy(List dest,List src)
:将src中的内容复制到dest中
ArrayList dest = new ArrayList();
//为了完成一个完整拷贝,我们需要先给dest赋值,大小和list.size()一样
for(int i =0;i<list.size();i++)
{
dest.add("");
}
//拷贝
Collections.copy(dest,list);
7.boolean replaceAll(List list, Object oldVal, Object newVal)
:使用新值替换List对象的所有旧值
Collections.replaceAll(list,"tom","汤姆");替换list中的tom为汤姆