Java Collection 学习
定义:Java 作为面向对象语言,对象的操作必比然是重中之重。要操作一个对象容易,如果需要存储多个对象,则需要一个容器,存储多个对象可以使用数组,但是数组的长度是不可变的。所以有了集合的概念。Collection 集合,就是为了方便操作处理对象而诞生的。
本文基于 JDK 1.8 版本
Collection :来源与 Java.util 包,先看看 Collection 的全家福类图
Collection 可以主要分为 set、List 、Queue 三种类型。这里 Map 是不属于 Collection 的,Map 是一个独立的数据结构。但是 Collention 又和 Map 的实现上又互相依赖。先说说 Collection 。
Collection 是一个的接口,是高度抽象出来的集合,包含了集合的基本操作和属性
红色框是Collection的基本方法(removeif 是1.8 出现的方法),蓝色框是 JDK 8后添加的新方法。
一、Collection 基本方法
Collection基本方法:
1、添加方法
boolean add(Object obj) : 添加一个对象
boolean addAll(Collection c) : 添加一个集合的对象
2、删除方法
void clear() 移除所有对象
boolean remove(Object) 移除一个对象
boolean removeAll(Collection c) 移除一个集合的对象,只要有一个对象移除了,就返回true
3、判断方法
boolean contains(Object o) 判断集合是否包含该对象
boolean containsAll(Collection c) 判断集合中是否包含指定的集合对象,只有包含所有的对象,才返回 true。
boolean isEmpty() 判断集合是否为空。
4、获取方法
Iterator<E> iterator() 迭代器
5、长度功能
int size() 对象个数
6.交集功能
boolean retainAll(Collection c) 移除此 Collection 中未包含在指定Collection 中的所有对象,简单说就是,集合 1 和集合 2 进行对比,最终结果保存在集合 1 ,返回值表示的是 A是否发生变化。
Java 8 新方法:
boolean removeif(Predicate filter) 按照一定规则过滤集合中的对象。Predicate 用于判断对象是否符合某个条件,例:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("123");
list.add("12");
list.add("1");
list.removeIf(s -> s.equals("123"));
list.forEach(s -> System.out.println(s));
}
二、迭代器(Iterator)
在说迭代器之前先说说 Collection 继承的 Iterable 这个接口
解释一下这个 Iterable 是啥
如果一个集合对象要表明自己支持迭代,可以使用foreach语句的特权,就必须实现Iterable接口,表明这个集合对象是可迭代的!然而实现Iterable接口,就必需为foreach语句提供一个迭代器来进行 foreach 操作。
也就是 迭代器(Iterator),所以 Iterable 接口要有 Iterator() 这个方法返回一个实现了 Iterator 迭代器接口的对象。
那为什么要用这个接口而不直接实现 Iterator 接口呢?我们带着疑问去看看!
另外提一下 spliterator 方法,返回一个 spliterator 接口。叫做可分割迭代器(splitable iterator),Spliterator就是为了并行遍历元素而设计的一个迭代器,jdk1.8中的集合框架中的数据结构都默认实现了spliterator。这里只做一个简单的介绍。
带着疑问首先来看看 List 接口的 源代码
可以看到 List 接口也有 Iterator 方法,下面我们看看 List 集合的实现类ArrayList
看到这里,可以解释为什么 Collection 不直接实现 Iterator 接口了:
List 集合族 与 Set 集合族 ,都是实现了 Iterable 接口 ,但都不是直接实现 Iterator 接口,为什么要这样做?
因为在 Iterator 接口的核心方法 next()或者 hasNext ()都是依赖于迭代器当前的迭代的位置。
如果 Collection 实现了 Iterator 接口,肯定会导致集合对象中包含当前迭代位置的数据(指针)。
当集合在不同方法间被传递的时候,由于当前迭代的位置是不可以预置。那么 next 方法的结果会变成不可预知。
这样看使用 Iterable 接口就不会有这样问题,每一次调用都是返回一个新的迭代器。迭代器之间是互不干扰的。
看上图 ArrayList 的 Iterator()方法就很直观了。
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("123");
list.add("12");
list.add("1");
Iterator<String> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
当我们使用迭代器时, 就是调用 list 实现的具体的 iterator 方法,每次使用迭代器的都是一个新的迭代器。
三、List 集合
List 接口的特点:有序集合,可以精确控制列表中每个元素的位置插入。 用户可以通过整数索引访问元素,并搜索列表中的元素。简单来说就是 顺序存储,顺序取出。可以重复。
List 还对 Iterator 作了实现 , ListIterator 接口。
ListIterator 接口比 Iterator 要多了几个方法。
hasPrevious() 和 previous() 方法都可以实现逆向遍历。
add()和 set()方法可以向List 中添加和修改对象。
List 集合的常用子类
ArrayList
ArrayList 是基于数组的, ArrayList 是无序的,它按照添加的先后顺序排列。如果要对 ArrayList 进行排序,可以调用它的 sort()方法。并提供一个 Comparator 比较器。
ArrayList 是线程不安全的。
LinkedList
LinkedList 是基于链表的,它是一个双向链表,每个节点维护了一个 prev 和 next 指针。同时这个链表维护了 first 和 last指针,分别指向第一个元素和最后一个元素。
它也是一个无序列表,也是按照插入的先后顺序排序。
LInkedList 对与快速访问元素不如 ArrayList 快,因为 ArrayList 访问元素是随机的。
LinkedList 也是线程不安全的。
Vector
Vector 和 ArrayList 非常类似,但Vector 是同步的。
由 Vector 创建的 Iterator ,虽然和 ArrayList 创建的 Iterator 是同一个接口,但是由于其同步的特性,当Vector 创建一个 Iterator 并使用时,另一个线程改变了 Vector 的状态,比如说添加或者删除了一些元素, 这时再调用 Iterator的方法则会抛出异常。
Stack 类继承与 Vector 类,是一个堆栈,Stack 提供的5个额外的方法 使 vector 可以当做堆栈使用。
四、Set 集合
Set 集合的特点
无序,不可重复。
Set 集合中常用的子类
HashSet
底层数据结构是哈希表(一个元素为链表的数组)
HashSet 是基于 HashMap 实现的,有点像是对 HashMap 做了封装,而且只是用了 HashMap 的 key 来实现其特性。
HashSet 不允许重复,如果出现重复就覆盖,允许为空。
HashSet 是线程不安全的。
TreeSet
底层数据结构是红黑树 (一个自平衡的二叉树)
TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。
TreeSet的性能比HashSet差但是我们在需要排序的时候可以用TreeSet因为他是自然排序也就是升序
LinkedHashSet
底层数据结构是由哈希表和链表组成。
LinkedHashSet 是不重复的,按插入的顺序排序。
LinkedHashSet 是线程不安全的。
五、Map 集合
为什么 Map 不继承 Collection?
首先 Map 提供的是键值对映射,而 Collection 是集合接口,提供的是一组数据。如果 Map 继承了 Collection 接口,那么所有 Map 的实现类到底是使用键值对还是使用 Collection 来存放数据呢?所以既然是两种数据结构,那也就没有必要去继承 Collection接口了,同时还不违反接口隔离原则。假如有实现类需要使用的 Collection 接口,也不该是 Map 去继承 Collection 接口。
六、总结
了解了以上的这些集合后,实际工作功能该如何选择呢?
如果涉及到堆栈,队列等操作,应该考虑使用 List ,对于需要快速插入,删除元素,应该使用 LinkedList 。需要快速随机访问元素,则使用 ArrayList。
如果程序在单线程环境中,或者访问仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程则考虑 **同步 **的类。
要注意对哈希表的操作。作为 key 的对象要正确复写 equals 和 hashCode 方法
感谢您的观看,如果发现错误欢迎指出,谢谢!
Java Collection 学习的更多相关文章
- ------------------java collection 集合学习 ----小白学习笔记,,有错,请指出谢谢
<!doctype html>java对象集合学习记录 figure:first-child { margin-top: -20px; } #write ol, #write ul { p ...
- Java设计模式学习资源汇总
本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...
- java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...
- 转:深入Java集合学习系列:HashSet的实现原理
0.参考文献 深入Java集合学习系列:HashSet的实现原理 1.HashSet概述: HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set 的迭代顺序:特 ...
- java后端学习记录2019
学习计划 2019年计划 1.学习计算机基础,并加以实践.包括LeetCode刷题.数据库原理(索引和锁.Sql优化等).网络协议(Http.Tcp).操作系统(加深Linux).<Http权威 ...
- 2019/3/4 java集合学习(二)
java集合学习(二) 在学完ArrayList 和 LinkedList之后,基本已经掌握了最基本的java常用数据结构,但是为了提高程序的效率,还有很多种特点各异的数据结构等着我们去运用,类如可以 ...
- Java多线程学习(六)Lock锁的使用
系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...
- Java技术学习路线
转载 作者:David 链接:https://www.zhihu.com/question/25255189/answer/86898400来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...
- Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库
参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 ...
随机推荐
- HDU2732一个让我debug了一晚上的题目
思路都理解了,清晰了,就是代码不对,还是有些小地方自己注意不到,即使就在你的眼前也不易发现的那种 Description: 也是一个最大流的构图,没相出来,或者说想简单了也是标记点1 至 n * m是 ...
- Maven的依赖管理
我们知道dependencies是可以被继承的,这个时候我们就想到让我们的发生了共用的依赖元素转移到parent中,这样我们又进一步的优化了配置.可是问题也随之而来,如果有一天我创建了一个新的模块,但 ...
- java数据库编程(未整理完,待续)
java使用数据库可以借助jdbc这个中间媒介.本文将介绍如何使用jdbc连接数据库,数据库的基本操作和jdbc的事物处理. 1 连接数据库 一般java连接数据库,都有几个步骤: 0.导入相应的驱动 ...
- Java框架知识点总结
一.Struts1的运行原理 在启动时通过前端总控制器ActionServlet加载struts-config.xml并进行解析,当用户在jsp页面发送请求被struts1的核心控制器ActionSe ...
- iOS Document Interaction(预览和打开文档) 编程指南
原文:http://developer.apple.com/library/ios/#documentation/FileManagement/Conceptual/DocumentInteracti ...
- .net图表之ECharts随笔01-最简单的使用步骤
找了几种绘制图表的办法,后面选定了ECharts.下载链接如下,好像不同的ECharts有不同的用法,要下对. https://gitee.com/Tuky/SomeWebFrame/tree/mas ...
- Android---------------ContentProvider的学习
1.Uri uri = Intent.getData()------------->可以获得Uri的地址 2.Cursor cursor = getContentResolver().quer ...
- 自定义SpringBoot控制台输出的图案
pringboot启动的时候,控制台输出的图案叫banner banner?啥玩意儿?相信有些人,一定是一脸懵逼... ——这个就不陌生了吧,这个是我们启动springboot的时候,控制台输出的.. ...
- redis 在 Linux下的安装
redis 和 nginx 一样,都是C语言编写的,所以我们的准备gcc 环境, 之前已经准备好了 没有准备的话(CentOs 有自带):yum install gcc-c++ 解压redis : ...
- 转---30 分钟学会 Flex 布局
正文从这开始- Flex 基本概念: 在 flex 容器中默认存在两条轴,水平主轴(main axis) 和垂直的交叉轴(cross axis),这是默认的设置,当然你可以通过修改使垂直方向变为主轴, ...