集合的理解和优点
- 1)可以动态保存任意多个对象,使用比较方便!
- 2)提供了一系列方便的操作对象的方法: add、remove、 set、 get等
- 3)使用集合添加,删除新元素的示意代码-
Java集合的分类
Java的集合类很多,主要分为两大类,如图:
- 1. 集合主要是两组(单列集合 , 双列集合)
- 2. Collection 接口有两个重要的子接口 ListSet, 他们的实现子类都是单列集合
- 3. Map 接口的实现子类 是双列集合,存放的 K-V
//Collection
//Map
ArrayList arrayList = new ArrayList();
arrayList.add("jack");
arrayList.add("tom");
HashMap hashMap = new HashMap();
hashMap.put("NO1", "北京");
hashMap.put("NO2", "上海");
Collection接口和常用方法
Java - Collection 接口及主要实现类_collections有什么实现-CSDN博客
基本介绍
Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是 java.util.List 与 java.util.Set。其中:
- List 的特点是有索引、存取有序、可重复。
- Set 的特点是无索引、存取无序(LinkedHashSet除外)、不可重复。
而两个子接口又分别有各自对应的实现类。
List 接口的主要实现类包括 java.util.ArrayList 和 java.util.LinkedList;
Set 接口的主要实现类有 java.util.HashSet、java.util.LinkedHashSet 和 java.util.TreeSet。
可用iterator迭代器
1、iterator
public class CollectionIterator{
@SuppressWarnings({"all"})
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
//System.out.println("col=" + col);
//现在希望能够遍历 col集合
//1. 先得到 col 对应的 迭代器
Iterator iterator = col.iterator();
//2. 使用while 循环遍历
//快捷键,快速生成 while=>itit
//显示所有的快捷键的的快捷键 ctrl+j
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
//3. 当退出while 循环后 , 这时iterator迭代器,指向最后的元素
// iterator.next();//NoSuchElementException
//4. 如果希望再次遍历,需要重置我们的迭代器
}
}
2、增强for循环
List
ArrayList
- ArrayList是线程不安全的,没有synchornized
- 1) permits all elements, including null , ArrayList 可以加入nul,并且多个
- 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倍。
ArrayList的基本使用
List list = new ArrayList();
//add:添加单个元素
list.add("jack");
list.add(10);//list.add(new Integer(10))
list.add(true);
System.out.println("list=" + list);
//remove:删除指定元素
list.remove(0);//删除第一个元素
list.remove(true);//指定删除某个元素
System.out.println("list=" + list);
//contains:查找元素是否存在
System.out.println(list.contains("jack"));//T
//size:获取元素个数
System.out.println(list.size());//2
// isEmpty:判断是否为空
System.out.println(list.isEmpty());//F
// clear:清空
list.clear();
System.out.println("list="+list);
// addAll:添加多个元素
ArrayListlist2=newArrayList();
list2.add("红楼梦");
list2.add("三国演义");
list.addAll(list2);
System.out.println("list="+list);
// containsAll:查找多个元素是否都存在
System.out.println(list.containsAll(list2));//T
// removeAll:删除多个元素
list.add("聊斋");
list.removeAll(list2);
System.out.println("list="+list);//[聊斋]
Vector
Vector 的基本介绍
- 1) Vector类的定义说明
- 2) Vector底层也是一 个对象数组,protected Object[] elementData;
- 3) Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized
public synchronized E get(int index) { if (index > = elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index); }
- 4)在开发中,需要线程同步安全时,考虑使用Vector
Vector和ArrayList的比较
LinkedList
LinkedList 的全面说明
- 1) LinkedList底层实现了双向链表和双端队列特点
- 2)可以添加任意元素(元素可以重复),包括null
- 3)线程不安全,没有实现同步
LinkedList 的底层操作机制
- 1) LinkedList底层维护了一个双向链表
- 2) LinkedList中维护了两个属性first和last分别指向首节点和尾节点
- 3)每个节点(Node对象) ,里面又维护了prev、next、 item三个属性,其中通过prev指向前一个, 通过next指向后一个节点。最终实现双向链表.
- 4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
Set 接口和常用方法
Set 接口基本介绍
无序(添加和取出的顺序不致),不允许重复元素,所以最多包含一个null
Set接口的常用方法
和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样.
Set接口的遍历方式
同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。
- 1.可以使用迭代器
- 2.增强for
- 3.不能使用索引的方式来获取.
以 Set 接口的实现类 HashSet 来讲解Set 接口的方法
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 接口对象,不能通过索引来获取
}
}
HashSet
HashSet 的全面说明
- 1) HashSet实际上是HashMap,看下源码.
- 2)可以存放null值,但是只能有一一个null
- 3) HashSet不保证元素是有序的,取决于hash后,再确定索引的结果。(即, 不保证存放元素的顺序和取出顺序一致)
- 4) 不能有重复元素/对象. 在前面Set接口使用已经讲过
分析HashSet底层是HashMap, HashMap底层是(数组+链表+红黑树)
- 1. HashSet底层是HashMap
- 2.添加一个元素时,先得到hash值会转成->索引值
- 3.找到存储数据表table ,看这个索引位置是否已经存放的有元素
- 4.如果没有,直接加入
- 5.如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后
- 6.在Java8中,如果一条链表的元素个数到达TREEIFY THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64), 就会进行树化(红黑树)
0521_韩顺平Java_HashSet源码解读1_哔哩哔哩_bilibili视频解释0521_韩顺平Java_HashSet源码解读1_哔哩哔哩_bilibili
LinkedHashSet
LinkedHashSet 的全面说明
- 1) LinkedHashSet是HashSet的子类
- 2) LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表
- 3) LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。
- 4) LinkedHashSet不允许添重复元素
1. LinkedHashSet 加入顺序和取出元素/数据的顺序一致
2. LinkedHashSet 底层维护的是一个LinkedHashMap(是HashMap的子类)
3. LinkedHashSet 底层结构 (数组table+双向链表)
4. 添加第一次时,直接将 数组table 扩容到 16 ,存放的结点类型是 LinkedHashMap$Entry
5. 数组是 HashMap$Node[] 存放的元素/数据是 LinkedHashMap$Entry类型
TreeSet
Map 接口和常用方法
Map 接口实现类的特点(JDK8)
- 1) Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
- 2) Map中的key和value 可以是任何引用类型的数据,会封装到HashMap$Node对象中
- 3) Map中的key不允许重复,原因和HashSet 一样,分析过源码.
- 4) Map中的value可以重复
- 5) Map的key可以为null, value也可以为null,注意key为null,只能有一个,value为null ,可以多个.
- 6)常用String类作为Map的key
- 7) key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
1.Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)
2.Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
3.Map中的key不允许重复,原因和HashSet一样,前面分析过源码.当有相同的k,相当于替换。
4.Map中的value可以重复
5.Map的key可以为null,value也可以为null,注意key为null,只能有一个,value 为null,可以多个
6. 常用String 类作为Map的 key
7. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
Map接口常用方法
@SuppressWarnings({"all"})
public class MapMethod{
public static void main(String[] args){
//演示map接口常用方法
Map map = newHashMap();
map.put("邓超",newBook("",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
}
}
Map 接口遍历方法
- 1.containsKey:查找键是否存在
- 2.keySet:获取所有的键
- 3.entrySet:获取所有关系k-v
- 4.values:获取所有的值
public class MapFor {
public static void main(String[] args) {
Map map=newHashMap();
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();
//向下转型 Map.Entry
//System.out.println(next.getClass());
//HashMap$Node-实现-> Map.Entry (getKey,getValue)
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
}
}
HashMap 小结
Java - Collection 接口及主要实现类_collections有什么实现-CSDN博客
java集合超详解_java集合使用-CSDN博客