- Collection集合概述
1.1数组和集合的区别【理解】
- 相同点:都是容器,可以存储多个数据
- 不同点 - 数组的长度是不可变的,集合的长度是可变的
- 数组可以存基本数据类型和引用数据类型
集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类
collection- 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
- JDK 不提供此接口的任何直接实现.它提供更具体的子接口(如Set和List)实现
- 创建Collection集合的对象
- 多态的方式
- 具体的实现类ArrayList
方法名称 | 说明 |
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
public boolean remove(E e) | 把给定的对象在当前集合中删除 |
public boolean contains(Object obj) | 判断当前集合中是否包含给定的对象 |
public boolean isEmpty() | 判断当前集合是否为空 |
public int size() | 返回集合中元素的个数/集合的长度 |
迭代器遍历
迭代器在Java中的类是Iterator,迭代器是集合专用的遍历方式。
方法名称 | 说明 |
Iterator<E> iterator() | 返回迭代器对象,默认指向当前集合的0索引 |
方法名称 | 说明 |
boolean hasNext() | 判断当前位置是否有元素,有元素返回true,没有元素返回false |
E next() | 获取当前位置的元素,并将迭代器对象移向下一个位置。 |
细节注意点
1,报错NoSuchElementException
2,迭代器遍历完毕,指针不会复位
3,循环中只能用一次next方法
4,迭代器遍历时,不能用集合的方法进行增加或者删除
增强for遍历
增强for的底层就是迭代器,为了简化迭代器的代码书写的。它是JDK5之后出现的,其内部原理就是一个lterator迭代器所有的单列集合和数组才能用增强for进行遍历。
格式:
for (元素的数据类型变量名:数组或者集合){
System.out.printIn(变量名)
}
增强for的细节
数组或者集合.for 快速创建
修改增强for中的变量,不会改变集合中原本的数据。
Lambda表达式遍历
得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。
方法名称 | 说明 |
default void forEach(Consumer<? super T> action): | 结合lambda遍历集合 |
遍历小结
1. Collection是单列集合的顶层接口,所有方法被List和Set系列集合共享
2.常见成员方法:
add、clear、remove、 contains、 isEmpty、size
3.三种通用的遍历方式:
迭代器:在遍历的过程中需要删除元素,请使用迭代器。增强for、Lambda:
仅仅想遍历,那么使用增强for或Lambda表达式。
三种遍历演示代码
package date12;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class text1 {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("ccc");
coll.add("vvv");
coll.add("bbb");
Iterator<String> iterator = coll.iterator();
//迭代器
while (iterator.hasNext()) {
String next = iterator.next();
System.out.println(next);
}
//增强for
for (String s : coll) {
System.out.println(s);
}
//lambda表达式
coll.forEach(s -> System.out.println(s));
}}
List集合
List集合的特点
有序:存和取的元素顺序一致
有索引:可以通过索引操作元素
可重复:存储的元素可以重复
List集合的特有方法
Collection的方法List都继承了
List集合因为有索引,所以多了很多索引操作的方法
方法名称 | 说明 |
void add(int index, E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index, E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
list集合的遍历方式
list继承了Collection的所有方法所以上面三种便利方式可以用,除此之外list还有两种方式
是,列表迭代器和普通for循环
listIterator列表迭代器比迭代器多了一个方法,在遍历的过程中可以添加元素
package date12;
import java.util.ArrayList;
import java.util.ListIterator;
public class text1 {
public static void main(String[] args) {
ArrayList<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("ccc");
coll.add("vvv");
coll.add("bbb");
ListIterator<String> stringListIterator = coll.listIterator();
while (stringListIterator.hasNext()){
String next = stringListIterator.next();
if ("ccc".equals(next)){
stringListIterator.add("qqq");
}
}System.out.println(coll);
}}
五种遍历方式对比
迭代器遍历
在遍历的过程中需要删除元素,请使用迭代器。
列表迭代器
在遍历的过程中需要添加元素,请使用列表迭代器。
增强for遍历和Lambda表达式
仅仅想遍历,那么使用增强for或Lambda表达式。
普通for
如果遍历的时候想操作索引,可以用普通for.
Set系列集合
Set系列集合
无序:存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
Set集合的实现类
HashSet:无序、不重复、无索引
LinkedHashSet:有序、不重复、无索引
TreeSet:可排序、不重复、无索引
Set接口中的方法上基本上与Collection的API一致。
HashSet底层原理
HashSet集合底层采取哈希表存储数据
哈希表是一种对于增删改查数据性能都较好的结构
哈希表组成
JDK8之前:数组+链表JDK8开始: 数组+链表+红黑树
哈希值
根据hashCode方法算出来的int类型的整数
该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算
一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值
对象的哈希值特点
如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
HashSet底层原理
1.创建一个默认长度16,默认加载因为0.75的数组,数组名table
2.根据元素的哈希值跟数组的长度计算出应存入的位置
3.判断当前位置是否为null,如果是nul直接存入
4.如果位置不为null, 表示有元素,则调用equals方法比较属性值
5.一样:不存 不一样:存入数组,形成链表
JDK8以前:新元素存入数组,老元素挂在新元素下面
JDK8以后:新元素直接挂在老元素下面
LinkedHashSet底层原理
有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
TreeSet的特点
不重复、无索引、可排序
可排序:按照元素的默认规则(有小到大)排序。
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
TreeSet的两种比较方式
方式一:
默认排序/自然排序:Javabean类实现Comparable接口指定比较规则
方式二:
比较器排序:创建TreeSet对象时候,传递比较器Comparator指定规则
方法返回值的特点
负数:表示当前要添加的元素是小的,存左边正数:表示当前要添加的元素是大的,存右边0:表示当前要添加的元素已经存在,舍弃
使用场景
1.如果想要集合中的元素可重复
用ArrayList集合,基于数组的。(用的最多)
2.如果想要集合中的元素可重复,而且当前的增删操作明显多于查询
用LinkedList集合,基于链表的。
3.如果想对集合中的元素去重
用HashSet集合,基于哈希表的。(用的最多)
4.如果想对集合中的元素去重,而且保证存取顺序
用LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet.
5.如果想对集合中的元素进行排序
用TreeSet集合,基于红黑树。后续也可以用List集合实现排序。
双列集合
双列集合的特点
1,双列集合一次需要存一对数据,分别为键和值
2,键不能重复,值可以重复
3,键和值是一—对应的,每一个键只能找到自己对应的值
4,键+值这个整体我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”
Map的常见API
Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的
方法名称 | 说明 |
V put(K key, V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containskey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
Map的遍历方式
Map的遍历方式
键找值
键值对
Lambda表达式
package data17;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class text1 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<>();
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
map.put("欧阳克","穆念慈");
//键找值
// Set<String> strings = map.keySet();
// for (String string : strings) {
// String s = map.get(string);
// System.out.println(s);
// }
//键值对
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"="+value);
}
//Lambda表达式,底层使用了entryset键值对
// map.forEach ((key, Vulie)-> System.out.println(key+"="+Vulie));
}
}
HashMap的特点
HashMap的特点
1,HashMap是Map里面的一个实现类。
2,没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
3,特点都是由键决定的:无序、不重复、无索引
4,HashMap跟HashSet底层原理是一模一样的,都是哈希表结构
小结
1. HashMap底层是哈希表结构的
2.依赖hashCode方法和equals方法保证键的唯一
3.如果键存储的是自定义对象,需要重写hashCode和equals方法
如果值存储自定义对象,不需要重写hashCode和equals方法
LinkedHashMap
由键决定:有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
TreeMap
TreeMap跟TreeSet底层原理一样,都是红黑树结构的。
由键决定特性:不重复、无索引、可排序可排序:对键进行排序。
注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则
代码书写两种排序规则
实现Comparable接口,指定比较规则。
创建集合时传递Comparator比较器对象,指定比较规则。
treemap倒序排列
package data17;
import java.util.Comparator;
import java.util.TreeMap;
public class text4 {
public static void main(String[] args) {
TreeMap<Integer,String>tis= new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
tis.put(3,"食而无味");
tis.put(2,"试试位");
tis.put(5,"道达尔");
tis.put(1,"的额外");
tis.put(4,"阿萨斯");
System.out.println(tis);
}
}