目录
集合的特点:
Collection集合:
Collection集合体系:
Collection的遍历方式
迭代器
增强for循环
lambda表达式
List
List系列集合特点
List遍历方式:
lineklist集合特有的功能
小结:
set集合
1.HashSet集合
LinkedHashSet集合概述和特点
TreeSet集合概述和特点
TreeSet集合默认的规则
map集合
Map集合概述和使用
Map集合整体格式:
Map集合的使用场景之一:购物车系统
Map接口实现类的特点[很实用]
Map集合体系特点
Map集合实现类特点
map的方法
map的遍历方式
HashMap
特点:
LinkedHashMap集合概述和特点
TreeMap集合概述和特点
数组: 数组定义完成并启动后,类型确定、长度固定。
适合元素的个数和类型确定的业务场景,不适合做需要增删数据操作。
集合:集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。集合更像气球。
集合非常适合做元素的增删操作。
集合的体系特征:
Collection:单列 例如:
张三 |
王五 |
李四 |
。。。 |
Map:双列 例如:
张三 |
律师 |
王五 |
程序员 |
李四 |
矿老板 |
API(set和list都可以使用,继承自collection):
add:添加单个元素;
remove:删除指定元素
contains:查找元素是否存在
size:获取元素个数
isEmpty:判断是否为空
clear:清空
package 集合;
import sun.rmi.log.LogInputStream;
import java.util.*;
public class Text01 {
public static void main(String[] args) {
List col = new ArrayList();
ArrayList arrayList = new ArrayList();
col.add("海绵hong");
col.add("学Java");
col.add("学的好吗");
System.out.println("add:" + col);
// col.remove(2);
col.remove("学的好吗");
System.out.println("remove:" + col);
System.out.println("contains:" + col.contains("学Java"));
System.out.println("size:"+col.size());
System.out.println("isEmpty:"+col.isEmpty());
col.clear();
System.out.println("clear:"+col);
ArrayList arr1 = new ArrayList();
arr1.add("javase");
arr1.add("javaee");
col.addAll(arr1);
System.out.println(col);
System.out.println(col.containsAll(arr1));
}
}
迭代器遍历:
遍历就是一个一个的把容器中的元素访问一遍。
迭代器在Java中的代表是Iterator,迭代器是集合的专用遍历方式。
Collection集合获取迭代器
Iterator |
返回集合中的迭代器对象,该迭代器对象默认指向当前集合的0索引 |
Iterator中的常用方法:
boolean hasNext() |
询问当前位置是否有元素存在,存在返回true ,不存在返回false |
E next() |
获取当前位置的元素,并同时将迭代器对象移向下一个位置,注意防止取出越界。 |
迭代器执行流程:
“海绵宝宝” |
“派大星” |
“章鱼哥” |
“珊迪” |
“蟹老板” |
Iterator it = lists.iterator();//先得到所对应的迭代器此例是lists的迭代器
while(it.hasNext()){//判断是否还有数据
Object ele = it.next();//使用next()方法获取,返回为Object类型
System.out.println(ele);
}//在此例中编译类型是Object但是运行类型是String
package 集合;
import java.util.ArrayList;
import java.util.Iterator;
public class Text02 {
public static void main(String[] args) {
ArrayList arr = new ArrayList();
arr.add("海绵宝宝");
arr.add("派大星");
arr.add("章鱼哥");
arr.add("珊迪");
arr.add("蟹老板");
// Iterator it=arr.iterator();
// while (it.hasNext()) {
// Object next = it.next();
// System.out.println(next);
// }
for (Object it:arr) {
System.out.println(it);
}
}
}
注:可以使用itit快速建立while循环
提示:在调用iterator.next()方法之前必须要调用iterator.hasNext()进行检测。若不调用,且下一条记录无效,直接调用iterator.next()会抛出NoSuchElementException异常
for(元素数据类型 变量名 : 数组或者Collection集合) {
//在此处使用变量即可,该变量就是元素
}
增强for循环:既可以遍历集合也可以遍历数组。
for(Objectit:arr){ System.out.println(it); } |
快捷方式:I就可以快速建立foreach
前面博客有详解
ArrayList、LinekdList :有序,可重复,有索引。
有序:存储和取出的元素顺序一致
有索引:可以通过索引操作元素(索引从0开始)
可重复:存储的元素可以重复(添加的数据可以重复)
1、List集合继承了Collection集合的全部功能,"同时因为List系列集合有索引",
2、因为List集合多了索引,所以多了很多按照索引操作元素的功能:
3、ArrayList实现类集合底层基于数组存储数据的,查询快,增删慢!
- public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
- public E get(int index):返回集合中指定位置的元素。
- public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
- public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回更新前的元素值。
-public int indexof(objeect obj)返回obj在集合中首次出现的位置
小结:
ArrayList集合的底层是基于数组存储数据。查询快,增删慢!(相对的)
linekdlist:集合的底层是基于链表存储数据。查询慢,增删快!
List系列集合的遍历方式有:4种。
List系列集合多了索引,所以多了一种按照索引遍历集合的for循环。
(1)for循环。(独有的,因为List有索引)。
(2)迭代器。
(3)foreach。
(4)JDK 1.8新技术。
LinkedList也是List的实现类:底层是基于双链表的,增删比较快,查询慢!!
LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的
所以LinkedList除了拥有List集合的全部功能还多了很多操作首尾元素的特殊功能:
- public void addFirst(E e):将指定元素插入此列表的开头。
- public void addLast(E e):将指定元素添加到此列表的结尾。
- public E getFirst():返回此列表的第一个元素。
- public E getLast():返回此列表的最后一个元素。
- public E removeFirst():移除并返回此列表的第一个元素。
- public E removeLast():移除并返回此列表的最后一个元素。
- public E pop():从此列表所表示的堆栈处弹出一个元素。
- public void push(E e):将元素推入此列表所表示的堆栈。
LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的。
所以提供了很多操作首尾元素的特殊API可的实以做栈和队列现。
如果查询多而增删少用ArrayList集合。(用的最多的)
如果查询少而增删首尾较多用LinkedList集合。
系列集合特点:
不包含重复元素的集合
没有带索引的方法所以无法使用普通for循环遍历
集合实现类特点:
HashSet : 无序、不重复、无索引。
LinkedHashSet:有序、不重复、无索引。
TreeSet:排序、不重复、无索引。
HashSet底层原理
HashSet集合底层采取哈希表存储的数据。
哈希表是一种对于增删改查数据性能都较好的结构。
哈希表的组成
JDK8之前的,底层使用数组+链表组成
JDK8开始后,底层采用数组+链表+红黑树组成。
package 集合;
import java.util.HashSet;
import java.util.Set;
public class Text03 {
public static void main(String[] args) {
// 看看Set系列集合的特点: HashSet LinkedHashSet TreeSet
//
Set sets = new HashSet<>(); // 一行经典代码 无序不重复,无索引
// Set sets = new LinkedHashSet<>(); // 有序 不重复 无索引
sets.add("MySQL");
sets.add("MySQL");
sets.add("Java");
sets.add("Java");
sets.add("HTML");
sets.add("HTML");
sets.add("SpringBoot");
sets.add("SpringBoot");
System.out.println(sets);
}
}
HashSet底层原理
1. HashSet底层是HashMap
2.添加一个元素时,先得到hash值会
转成->索引值
3.找到存储数据表table,看这个索引
位置是否已经存放的有元素
4.如果没有,直接加入
5.如果有,调用equals比较,如果
相同,就放弃添加,如果不相同,则
添加到最后
6.在Java8中,如果条链表的元素个数
超过TREEIFY THRESHOLD(默认
是8),并且table(数组元素)的大小>=
MIN TREEIFY CAPACITY(默认64),
就会进行树化(红黑树)
有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
不重复、无索引、可排序
可排序:按照元素的大小默认升序(有小到大)排序。
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。
对于数值类型:Integer , Double,官方默认按照大小进行升序排序。
对于字符串类型:默认按照首字符的编号升序排序。
对于自定义类型如Student对象,TreeSet无法直接排序。
Map集合是一种双列集合,每个元素包含两个数据。
Map集合的每个元素的格式:key=value(键值对元素)。
Map集合也被称为“键值对集合”。
Collection集合的格式: [元素1,元素2,元素3..]
Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , ...}
购物车提供的四个商品和购买的数量在后台需要容器存储。
每个商品对象都一一对应一个购买数量。
把商品对象看成是Map集合的建,购买数量看成Map集合的值。
注意:这里讲的是JDK8的Map接口特点 Map java
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
Map集合的特点都是由键决定的。
Map集合的键是无序,不重复的,无索引的,值不做要求(可以重复)。
Map集合后面重复的键对应的值会覆盖前面重复键的值。
Map集合的键值对都可以为null。
HashMap:元素按照键是无序,不重复,无索引,值不做要求。(与Map体系一致)
LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。
TreeMap:元素按照建是排序,不重复,无索引的,值不做要求。
方法名称 |
说明 |
V put(K key,V value) |
添加元素 |
V remove(Object key) |
根据键删除键值对元素 |
void clear() |
移除所有的键值对元素 |
boolean containsKey(Object key) |
判断集合是否包含指定的键 |
boolean containsValue(Object value) |
判断集合是否包含指定的值 |
boolean isEmpty() |
判断集合是否为空 |
int size() |
集合的长度,也就是集合中键值对的个数 |
package 集合;
import java.util.*;
public class Text04 {
public static void main(String[] args) {
// 1.添加元素: 无序,不重复,无索引。
Map maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",100);// Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
// {huawei=100, 手表=10, 生活用品=10, iphoneX=100, 娃娃=20}
System.out.println(maps);
// 2.清空集合
// maps.clear();
// System.out.println(maps);
// 3.判断集合是否为空,为空返回true ,反之!
System.out.println(maps.isEmpty());
// 4.根据键获取对应值:public V get(Object key)
Integer key = maps.get("huawei");
System.out.println(key);
System.out.println(maps.get("生活用品")); // 10
System.out.println(maps.get("生活用品2")); // null
// 5.根据键删除整个元素。(删除键会返回键的值)
System.out.println(maps.remove("iphoneX"));
System.out.println(maps);
// 6.判断是否包含某个键 ,包含返回true ,反之
System.out.println(maps.containsKey("娃娃")); // true
System.out.println(maps.containsKey("娃娃2")); // false
System.out.println(maps.containsKey("iphoneX")); // false
// 7.判断是否包含某个值。
System.out.println(maps.containsValue(100)); //
System.out.println(maps.containsValue(10)); //
System.out.println(maps.containsValue(22)); //
// {huawei=100, 手表=10, 生活用品=10, 娃娃=20}
// 8.获取全部键的集合:public Set keySet()
Set keys = maps.keySet();
System.out.println(keys);
System.out.println("------------------------------");
// 9.获取全部值的集合:Collection values();
Collection values = maps.values();
System.out.println(values);
// 10.集合的大小
System.out.println(maps.size()); // 4
// 11.合并其他Map集合。(拓展)
Map map1 = new HashMap<>();
map1.put("java1", 1);
map1.put("java2", 100);
Map map2 = new HashMap<>();
map2.put("java2", 1);
map2.put("java3", 100);
map1.putAll(map2); // 把集合map2的元素拷贝一份到map1中去
System.out.println(map1);
System.out.println(map2);
}
}
方式一:键找值的方式遍历:先获取Map集合全部的键,再根据遍历键找值。
方式二:键值对的方式遍历,把“键值对“看成一个整体,难度较大。
方式三:JDK 1.8开始之后的新技术:Lambda表达式。
键找值”的方式遍历Map集合。
1.先获取Map集合的全部键的Set集合。
2.遍历键的Set集合,然后通过键找值。
小结:
代码简单,需要记住!
package 集合;
import java.util.*;
public class Text05 {
public static void main(String[] args) {
Map maps = new HashMap<>();
// 1.添加元素: 无序,不重复,无索引。
maps.put("娃娃",30);
maps.put("iphoneX",100);
maps.put("huawei",1000);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
// maps = {huawei=1000, 手表=10, 生活用品=10, iphoneX=100, 娃娃=30}
// 1、键找值:第一步:先拿到集合的全部键。
Set keys = maps.keySet();
// 2、第二步:遍历每个键,根据键提取值
for (String key : keys) {
int value = maps.get(key);
System.out.println(key + "===>" + value);
}
}
}
键值对”的方式遍历:
1.把Map集合转换成一个Set集合:Set
2.此时键值对元素的类型就确定了,类型是键值对实体类型:Map.Entry
3.接下来就可以用foreach遍历这个Set集合,类型用Map.Entry
package 集合;
import java.util.*;
public class Text05 {
public static void main(String[] args) {
Map maps = new HashMap<>();
// 1.添加元素: 无序,不重复,无索引。
maps.put("娃娃",30);
maps.put("iphoneX",100);
maps.put("huawei",1000);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
// maps = {huawei=1000, 手表=10, 生活用品=10, iphoneX=100, 娃娃=30}
/**
maps = {huawei=1000, 手表=10, 生活用品=10, iphoneX=100, 娃娃=30}
使用foreach遍历map集合.发现Map集合的键值对元素直接是没有类型的。所以不可以直接foreach遍历集合。
可以通过调用Map的方法 entrySet把Map集合转换成Set集合形式 maps.entrySet();
Set> entries = maps.entrySet();
[(huawei=1000), (手表=10), (生活用品=10), (iphoneX=100), (娃娃=30)]
entry
此时可以使用foreach遍历
*/
// 1、把Map集合转换成Set集合
Set> entries = maps.entrySet();
// 2、开始遍历
for(Map.Entry entry : entries){
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key + "====>" + value);
}
}}
JDK 1.8开始之后的新技术:Lambda表达式。 前面博客有详细解释
HashMap是Map里面的一个实现类。
特点都是由键决定的:无序、不重复、无索引 没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
HashMap跟HashSet底层原理是一模一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已。
由键决定:有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
由键决定特性:不重复、无索引、可排序
可排序:按照键数据的大小默认升序(有小到大)排序。
只能对键排序。 注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序 TreeMap跟TreeSet一样底层原理是一样的。