概述
集合的关系
集合结构
- 单列集合 Collection
- List 可以重复:ArrayList、LindkedList
- Set 不可以重复:HashSet、TreeSet
- 双列集合 Map : HashMap、TreeMap
接口粗体 ,实现类斜体
集合图解:
以下图自网络(见水印)
Collection 接口
-Collection接口中的方法
方法名 | 说明 |
---|---|
int size() | 返回集合中元素的个数 |
boolean isEmpty() | 判断集合是否为空 |
boolean add(Object o) | 添加元素 |
boolean addAll(Collection c) | 添加集合中的元素 |
boolean remove(Object o) | 删除元素 |
boolean removeAll(Object o) | 删除集合中的元素 |
boolean retainAll(Collection o) | 删除集合中不在参数集合中的元素 |
boolean contains(Object o) | 判断集合中是否包含某个元素 |
Iterator iterator() | 获得迭代器,用于遍历所有元素。 |
Object[] toArray() | 把容器中元素转化成Object数组 |
List接口
特点:
-
有存放顺序 ( 有序 )
-
元素可重复
方法名 | 说明 |
---|---|
void add(int index ,Object obj) | 在指定位置插入元素 |
boolean addAll(int index,Collection c) | 在指定位置插入集合 |
Object set(int index,Object obj) | 修改指定位置的元素 |
Object get(int index) | 获取指定位置的元素 |
boolean remove(int index) | 删除指定位置的元素,后面的元素前移 |
int indexOf(Object obj) | 返回第一个匹配的元素的索引,没有匹配的元素返回-1 |
int lastIndexOf(Object obj) | 返回最后一个匹配的元素的索引,没有匹配的元素返回-1 |
List subList(int fromIndex,int toIndex) | 取出集合中的子集合 |
ListIterator listIterator() | 为ListIterator接口实例化 |
1. ArrayList集合
-数组结构 -改查快 增删慢
特点:
-
底层动态数组 查询快 增删满
-
线程不安全 效率高
1.8之前创建时,会初始容量为10容量的数组,扩容为1.5倍
1.8之后是初始容量为0,存储第一个数据时,会扩容到10,存满时扩容为1.5倍
底层是数组内存地址是连续的,所以查询快 增删慢 线程不安全
方法名 | 说明 |
---|---|
boolean add(E e) | 将指定元素追加到集合的末尾 |
boolean addAll(E Object) | 用于将指定集合中所有元素添加到当前集合中 |
boolean remove(Object o) | 删除指定元素,成功则返回true |
E remove(int index) | 删除指定索引位置的元素,返回被删除的元素 |
E set(int index,E e) | 修改指定索引位置的元素,返回修改前的元素 |
E get(int index) | 获取指定索引位置的元素 |
int size() | 返回及合中元素个数 |
2. LinkedList集合中的方法
-双链表结构 增删块 改查慢
特点:
-
底层是动态数组 查询快 增删慢
-
线程不安全 效率高
底层是一个双向链表, 线程不安全
Vector 线程安全的,底层也是数组
方法名 | 说明 |
---|---|
void addFirst(Object o) | 在链表头部添加元素 |
void addLast(Object o) | 在链表尾部添加元素 |
offerFirst(Object o) | 在链表头部添加元素,返回true或false |
offerLast(Object o) | 在链表尾部添加元素,返回true或false |
E getFirst() | 获取链表头部元素,空则报异常 |
E getLast() | 获取链表尾部元素,空则报异常 |
peekFirst() | 获取链表头部元素,空则返回null |
peekLast() | 获取链表尾部元素,空则返回null |
pollFirst() | 获取链表头部元素,空则返回null |
pollLast() | 获取链表尾部元素,空则返回null |
E removeFirst() | 移除链表头部元素,空则报异常 |
E removeLast() | 移除链表尾部元素,空则报异常 |
pop() | 弹出链表头部元素,空则报异常 |
push(Object o) | 压入链表头部元素 |
removeFirstOccurrence(Object o) | 移除链表中第一次出现的指定元素,返回布尔值 |
removeLastOccurrence(Object o) | 移除链表中最后一次出现的指定元素,返回布尔值 |
3.Vector
特点:
-
底层是数组 查询快 增删慢
-
线程安全 效率低
方法和ArrayList几乎一模一样
2-Set
特点
-
没有存放顺序
-
不可重复
-
没有索引的,所以就不能使用普通for循环进行遍历
1.HashSet
特点:
-
底层是哈希表 ( 底层hashMap )
-
哈希表唯一依赖两个方法
-
hashCode()
-
equals()
-
-
-
向HashSet集合放入新元素执行顺序:
-
调用Hashcode()函数,判断是否已有相同的哈希值
-
没有则放入该新元素,有则调用equals()函数逐个对比 ,没有则放入,有则不执行添加
-
练习:双色球
/**
* 双色球 - Set版
*/
public class Demo03 {
public static void main(String[] args) {
Random rd = new Random();
int blueBall = rd.nextInt(16)+1;
//创建HashSet集合用来存储红球
HashSet<Integer> redBalls = new HashSet<>();
//TreeSet集合自带排序功能
//TreeSet<Integer> redBalls = new TreeSet<>();
while (redBalls.size() < 6){
//将随机数添加到集合中
redBalls.add(rd.nextInt(10));
}
System.out.println("红球:" + redBalls + "篮球:[" + blueBall+"]");
}
}
HashSet去重原理
先看代码:
//学生类
public class Student {
private String name ;
private int age ;
//省略 setter/getter 无参/有参构造 toStriing 方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
/**
* HashSet去重原理
*/
public class HashSetTest {
public static void main(String[] args) {
HashSet<Student> set = new HashSet<Student>();
set.add(new Student("111",11));
set.add(new Student("222",22));
set.add(new Student("333",55));
set.add(new Student("444",44));
set.add(new Student("333",55));
//从程序底层来讲,两个333不是同一个对象,都有自己的存储对象,所以可以存储。
for (Student stu :
set) {
System.out.println(stu);
}
}
}
先对比hashCode如果相同,再去对比equals的内容。这两个方法经常需要在实体类中进行重写,帮助我们解决逻辑上的去重关系。
-LinkedHashSet
特点:
-
底层哈希表 (不可重复 ) + 链表 (有序)
-
有序指的是存入集合的顺序
-
-
用法和HashSet几乎一模一样
2-TreeSet
特点:
-
底层红黑树 自然平衡二叉树 升序排列
-
因为二叉树结构所以集合内元素自动按升序排列
-
-
元素不可重复
-
TreeSet是对Set集合的实现,而Set集合都是不可重复的
-
TreeSet自动排序,添加元素会调用compareTo(Object o)方法,遇到重复不添加
-
-
两种排序方法
-
自然排序 ( 默认升序 )
-
定制排序 ( 需重写方法 )
-
3-Queue
特点:
-
是一个队列 先进先出
Map接口
1-Map
特点:
-
双列集合 键值对组成 ( 键 + 值 成对储存 ),键完全和List集合的特点相同(底层一样),值依附于每一个键上,不守规则影响(如TreeMap的键不可重复,但值可重复)
方法名 | 说明 |
---|---|
Object put(Object key, Object value) | 存放键值对 |
get(Object key) | 通过键对象获取到值对象 |
Object remove(Object key) | 通过键对象删除键值对 |
boolean containsKey(Object key) | 判断是否包含键对象对应的键值对 |
boolean containsValue(Object value) | 判断是否包含值对象对应的键值对 |
values() | 获取所有的值对象 |
int size() | 获取键值对的个数 |
boolean isEmpty() | 判断是否为空 |
void clear() | 清空所有的键值对 |
2-HashMap
-查找 删除 修改 效率很高
继承 AbstractMap< K , V >
实现 Map< K , V >
特点:
-
JDK1.8之前 底层是哈希表 (哈希表的本质是 数组 + 链表 )
-
数组初始化长度16 ,负载因子是0.75 ,当储存的元素 * 0.75 大于数组的长度,需要将数组扩容2倍.
-
其储存数据时判断key是否重复的标准是key的hashCode必须相同,equals方法比较时必须返回true
-
-
JDK1.8之后 底层是 ( 数组+链表+红黑二叉树 )
-
当一个链表存储的数据大于8时,链表会自动转换为红黑二叉树,当数据少于6时,再会自动转化为链表
-
注意:
-
底层会调用equals和hasnCode方法比较是否相等
-
所以一般创建对象要重写 equals 和 hashCode 方法
方法名 | 说明 |
---|---|
V put(K key,V value) | 往集合中推送一对映射关系,若键存在,则把新的值赋值,并返回老的值 |
V remove(K key) | 根据键删除一对隐射关系,返回键对应的值 |
boolean remove(Object key, Object value) | 根据传入的键和值删除元素,并返回删除是否成功 |
void clear() | 清空集合中所有的隐射关系 |
V get(Object key) | 根据传入的键获取值 |
boolean containsKey(Object key) | 判断传入的键是否存在 |
boolean containsValue(Object value) | 判断传入的值是否存在 |
boolean isEmpty() | 判断集合是否为空 |
Set<K> keySet() | 获取集合中所有的键 |
Collection<V> values() | 获取集合中所有的值 |
int size() | 获取集合中有多少对隐射关系 |
-LinkedHashMap
继承 HashMap<K,V> 实现 Map<K,V>
特点:
-
底层是哈希表 (哈希表的本质是 数组 + 链表 ) 和链表
-
链表可以维护 插入节点 的顺序
-
-
存于取的顺序一致
HashMap<K,V> : 元素存取无序的双列集合
LinkedHashMap<K,V> : 元素存取有序的双列集合
创建对象和增删改查都一模一样
3-Hashtable
特点:
-
底层是哈希表(哈希表本质是 数组 + 链表 ) 类似HashMap
-
与HashMap唯一区别 线程安全 效率低
-
Hashtable 线程安全 效率低 不允许null键null值
-
HashMap 线程不安全,效率高,允许null值null键
-
用法与HashMap几乎一样
4-TreeMap
特点:
-
底层是红黑树 自然平衡二叉树
-
键的储存类似TreeSet 每个键都附带了其各自的值
-
-
自动排序
注意:
-
TreeMap在比较key时,使用的时自己实现Comparable 接口的compareTo方法
-
这个方法就是判断key是否时一样的方法
-
-
返回0说明两者相等 ( 一般不会出现这种业务逻辑 )
-
在某些业务情况下,不能随意返回0,需要使用equals和hashCode方法进行比较后在判断
-
方法参考Map接口方法
比较器
1-内部比较器
源码:
public interface Comparable<T> {
/**
* 比较this和obj的大小。
* 如果this大于obj,则返回正数
* 如果this小于obj,则返回负数
* 吐过this等于obj,则返回零即可
*/
public int compareTo(T obj);
}
当compareTo方法返回值为负数,表示放在红黑树的左边,即逆序(降序)输出。
当compareTo方法返回值为零,表示元素相同,仅存放第一个元素(保证元素的唯一)。
当compareTo方法返回值为正数,表示放在红黑树的右边,即顺序(升序)输出。
对于Java提供的类(String Integer等) 都默认实现了 Comparable 接口
- 自定义排序
自定义类中必须继承 Comparable 接口,并重写compareTo方法
示例:声明自定义Student类,按照老师的年龄升序排序
public class Student implements Comparable<Student> {
// 成员变量
String name;
int age;
double score;
// 构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
/**
* 比较this.age和stu.age的大小,按照学生年龄升序排序
* 如果this大于stu,则返回正数
* 如果this小于stu,则返回负数
* 如果this等于stu,则返回零
*/
@Override
public int compareTo(Student stu) {
return this.age - stu.age;
}
@Override
public String toString() {
return "Student{name=" + name + ", age=" + age + ", score=" + score + "}";
}
}
因为TreeMap要对元素进行排序,那你排序的依据是什么,姓名还是年龄还是其它的,得告诉它,怎么告诉?需要让Student类实现Comparable接口并重写compareTo()方法。
-
当compareTo方法返回值为负数,表示放在红黑树的左边,即逆序(降序)输出。
-
v 当compareTo方法返回值为零,表示元素相同,仅存放第一个元素(保证元素的唯一)。
-
当compareTo方法返回值为正数,表示放在红黑树的右边,即顺序(升序)输出。
2-外部比较器
如果某个类想实现多种排序规则,那么就必须采用外部比较器java.util.Comparator接口来实现。
要想改变TreeMap的自然排序操作,我们还可以在其构造方法中传入一个Comparator比较器,那么TreeMap就会按照外部比较器中的规则进行排序,TreeMap的比较器构造方法如下:
public TreeMap(Comparator<? super K> comparator){
this.comparator = comparator ;
}
因此,我们使用外部比较器实现TreeMap的排序时,必须创建一个Comparator的实现类对象,在实现类中重写int compare(T o1, T o2)方法,返回的int值的正负表示两个对象的大小,其返回值规则和Comparable接口中的compareTo()方法保持一致。
示例:声明自定义Student类
public class Student {
// 成员变量
String name;
int age;
double score;
// 构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{name=" + name + ", age=" + age + ", score=" + score + "}";
}
}
接下来,我们使用Comparator接口,先实现按照学生的年龄升序排序,然后在按照学生的成绩降序排序,具体的代码实现请看以下示例代码。
示例:使用Comparator比较器,实现按照学生的年龄升序排序
public class Test01 {
public static void main(String[] args) {
// 创建一个TreeMap对象
Map<Student, String> map = new TreeMap<>(new Comparator<Student>() {
/**
* 比较o1.age和o2.age对象的大小,按照学生年龄升序排序
* 如果o1大于o2,则返回正数
* 如果o1小于o2,则返回负数
* 如果o1等于o2,则返回零即可
*/
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
});
// 添加键值对
map.put(new Student("张三", 38, 99.5), "武汉");
map.put(new Student("李四", 20, 58), "北京");
map.put(new Student("王五", 27, 77), "上海");
map.put(new Student("赵六", 18, 100), "南京");
map.put(new Student("王五", 27, 89), "重庆");
map.put(new Student("刘七", 29, 90), "深圳");
// 遍历map
Iterator<Student> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Student key = iterator.next();
System.out.println("key:" + key + ", value:" + map.get(key));
}
}
}
示例:使用Comparator比较器,实现按照学生的成绩降序排序
public class Test01 {
public static void main(String[] args) {
// 创建一个TreeMap对象
Map<Student, String> map = new TreeMap<>(new Comparator<Student>() {
/**
* 比较o1.score和o2.score对象的大小,按照学生成绩降序排序
* 如果o1大于o2,则返回负数
* 如果o1小于o2,则返回正数
* 如果o1等于o2,则返回零即可
*/
@Override
public int compare(Student o1, Student o2) {
//三元运算符写法
//return o1.score>o2.score?-1:o1.score<o2.score?1:0;
if (o1.score > o2.score){
return -1;
else if (o1.score < o2.score)
return 1;
else
return 0;
}
}
});
// 添加键值对
map.put(new Student("张三", 38, 99.5), "武汉");
map.put(new Student("李四", 20, 58), "北京");
map.put(new Student("王五", 27, 77), "上海");
map.put(new Student("赵六", 18, 100), "南京");
map.put(new Student("王五", 27, 89), "上海");
map.put(new Student("刘七", 29, 90), "深圳");
// 遍历map
Iterator<Student> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Student key = iterator.next();
System.out.println("key:" + key + ", value:" + map.get(key));
}
}
}
使用TreeMap要点
1、由于是二叉树,需要对元素做内部排序。所以要么实现Comparable接口,要么实现Comparator接口,否则会抛出java.lang.ClassCastException异常。
2、TreeMap的key不能为null,否则抛出java.lang.NullPointerException异常
Iterator迭代器
1-Iterator
方法名 | 说明 |
---|---|
boolean hasNext() | 判断集合中是否有下一个元素可以迭代,如果有,则返回 true。 |
Boject next() | 返回迭代的下一个元素,并把指针向后移动一位。 |
void remove() | 将迭代器当前返回的元素删除(可选操作)。 |
2-ListIterator
Iterator的子接口,比Iterator更强大,是它的扩展
方法名 | 说明 |
---|---|
boolean hasNext(); | 以正向遍历列表时,判断迭代器后面是否还有元素。 |
Object next() | 返回列表中ListIterator指向位置后面的元素。 |
boolean hasPrevious(); | 以逆向遍历列表,判断迭代器前面是否还有元素。 |
Object previous(); | 返回列表中ListIterator指向位置前面的元素。 |
void remove(); | 从列表中删除next()或previous()返回的最后一个元素。 |
void set(Object e); | 从列表中将next()或previous()返回的元素更改为指定元素。 |
void add(Object e); | 将指定的元素插入列表,插入位置为迭代器当前位置之前。 |
3-keySey()
Set<K> keySet()方法,该返回此映射中包含的键的Set视图将map中所有的键存入到Set集合,因为set具备迭代器,所有迭代方式取出所有的键再根据get()方法,获取每一个键对应的值。
4-entrySet()
entrySet()方法,该方法取出的是关系(Set<Map.Entry<K, V>>),关系中包含key和value。其中Map.Entry<K,V>来表示这种数据类型,即将Map集合中的映射关系存入到Set集合中,这个关系的数据类型为Map.Entry接口。
Map.Entry接口在java.util包中,它是Map接口中的一个内部接口,getKey()和getValue()是接口Map.Entry<K,V>中的方法,返回对应的键和对应的值。
方法名 | 说明 |
---|---|
getKey() | 取出键 |
getValue() | 取出值 |
并发性修改异常
public class Demo05 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("JavaSE");
list.add("MySql");
list.add("Linux");
list.add("Redis");
/*//创建迭代器,迭代器会有一个预期的迭代个数
Iterator<String> it = list.iterator();
//判断下一个位置是否有元素
while (it.hasNext()){
//获取下一个位置的元素存储到str变量中
String str = it.next();
//当遍历到MySql时,添加数据
if (str.equals("MySql")){
list.add("JDBC");
}
}//ConcurrentModificationException,并发性修改异常*/
//解决办法一:不使用迭代器
/*for (int i = 0; i < list.size(); i++) {
if ("MySql".equals(list.get(i))){
list.add(i + 1,"JDBC");
}
}*/
//解决办法二:ListIterator
//创建迭代器对象,可以修改集合预期的迭代个数
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()){
if ("MySql".equals(lit.next())){
//通过自己的add方法添加元素到集合中
lit.add("JDBC");
}
}
System.out.println(list);
}
}
Collections工具类
方法名 | 说明 |
---|---|
void sort( List<T> list ) | 按照 T 类型排序 |
void sort( List<T> list , Comparator< ? super T > c) | 使用外部比较器排序 |
void shuffle(List<?> list) | 打乱顺序( 混排 ) |
void reverse(List<?> list) | 顺序的反向排序(反转) |
void fill(List<? super T> list, T obj) | 替换所有的元素为 T |
boolean addAll(Collection<? super T> c, T... elements) | 添加所有 |
以上就是目前整理的集合相关的笔记,集合在javase中还是很重要的,每个集合都有各自的特点,还是要根据实际的业务来选择!
集合图解中部分图源自网络,作者见水印!
最后
以上就是兴奋篮球为你收集整理的JavaSE - 集合(笔记) - 集合总结集合的关系Collection 接口Map接口比较器Iterator迭代器Collections工具类的全部内容,希望文章能够帮你解决JavaSE - 集合(笔记) - 集合总结集合的关系Collection 接口Map接口比较器Iterator迭代器Collections工具类所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复