【前言】Java语法的系列学习已经结束了,现在开始数据结构集合类的学习,这里学习的数据结构是基于Java的数据结构,下图是本次数据结构的学习内容大纲,仅供参考。有计划,有目标,才有方向;不放弃,不懈怠,才有结果。
文章目录
【提示】:主要还是看代码示例:细节知识点都是都藏在代码注释里呢。
集合框架及背后的数据结构
数据结构:是组织数据的一种方式。
集合及其背后的数据结构:在java当中,Java把很多的数据结构全部都封装起来了,封装成一个一个的现成的类。只需要拿过来使用就行了,但是在使用的时候需要知道其底层原理。这个底层原理就是我们所说的数据结构。集合类就是把这些数据结构已经封装成一个一个独有的类了,可以拿过来直接使用。
简单介绍
官方教程
Java 集合框架 (Java Collection Framework) ,又被称为容器 container ,是定义在 java.util 包下的一组接口 (interfaces )和其实现类( classes) 。其主要表现为将多个元素 (element) 置于一个单元中,用于对这些元素进行快速、便捷的存储 (store)、检索(retrieve)、管理( manipulate) ,即平时我们俗称的增删查改 (CRUD )。
例如,一副扑克牌(一组牌的集合)、一个邮箱(一组邮件的集合)、一个通讯录(一组姓名和电话的映射关系)等。
类和接口总览
对上图的文字分析叙述:
- Iterable接口:顶层接口 Iterable(可迭代的),它用于遍历。
- 迭代:通过若干个有限的步骤,逐步逼近最终结果。在集合类里面它所代表的具体含义就是:能够进行从前到后的遍历,取出每个元素。
接下来所介绍的集合类,只要实现了Iterable接口,就可以进行这样的遍历过程。
Collection接口:它是一个集合,收集很多元素放在一起。它不仅可以遍历和可以进行增删改查操作。它的表示形式有以下三种:他们三个实现了Collection接口
List接口:它表示一个列表,它里面的元素是相对有序的,可以中间位置插入删除。它的表示形式有以下三种,它们三个实现了List接口
- Vector类:它也是一个顺序表,只不过是旧版本的顺序表,现在很少用了。
ArrayList类:顺序表的实现
LinkedList类:链表的实现
Stack类:它是一个栈(后进先出)
Queue接口:队列(先进先出),它里面的元素也是相对有序的,只能头插/头删,尾插/尾删。
- Deque接口:双向队列(既可以从头进从头出,也可以从尾进从尾出),他还有一个具体的类LinkedList
- LinkedList类:LinkedList也实现了Queue接口
- PriorityQueue:优先队列,它是一种特殊的队列,里面的元素是具有优先级的,他不是简单的先进先出,而是按照优先级的高低决定谁先出谁后出,它底层的数据结构是对应到堆上的
Set接口:Set和List、Queue有一定的区别,List接口里面要求元素之间相对取得有序的,Queue接口里面要求的不光是有序还更加限制了操作接口,而Set里面不要求元素有序(即:认为1,2,3和3,2,1是相同的)。
- SotredSet接口:
- Set接口具体的实现一个是TreeSet类(基于二叉搜索树的实现);
- 一个是HashSet类(基于哈希表的实现)。
Map接口:它里面存储的是”键值对“,它有两种具体的实现。
- HashMap:基于哈希表的实现(重中之重),哈希这种思想方法是当前互联网分布式系统的理论基础。
- TreeSet:基于二叉搜索树的实现
从上面这个图中要知道两个东西,一个是他们之间关系,另一个是他们背后的数据结构。
- 关系
接口和接口之间的关系:一个接口可能有一个功能,它要拓展另外一个接口,就需要extends(继承)这个接口,所以接口和接口之间是extends(继承)的关系。
类和接口的关系:是实现implements。
- 背后的数据结构:如类和接口总览
Java 集合框架的优点及作用
- 使用成熟的集合框架,有助于我们便捷、快速的写出高效、稳定的代码
- 学习背后的数据结构知识,有助于我们理解各个集合的优缺点及使用场景
为什么会有这么多的数据及结构?
因为组织数据的方式不一样,所以才有这么多的数据结构来提供使用,既然有这么多的数据结构,那么必然每一种数据结构都有自己使用的场景以及它的优缺点。
笔试及面试题
集合在面试和笔试的时候占有非常大的比例,所以要十分注意!
腾讯-Java后台开发面经
- HashMap 了解不,介绍一下,如果一个对象为 key 时,hashCode 和 equals 方法的用法要注意什么?
- HashSet 和 HashMap 的区别是什么?
- HashMap 是线程安全的么?那需要线程安全需要用到什么?
阿里巴巴-Java后台开发面经
- ArrayList 和 LinkedList 的区别是什么?(即顺序表和链表的区别或数组和链表的区别)
- 有了解过 HashMap 的具体实现么?
- HashMap 和 ConcurrentHashMap 哪个效率更高?
今日头条-Java后台开发面经
- 编程题:判断一个链表是否是一个回文链表。
- Redis 的 zset 类型对应到 java 语言中大致是什么类型?
- hashCode 主要是用来做什么用的?
接口interfaces
基本关系说明
1、Collection :用来存储管理一组对象 (objects) ,这些对象一般被成为元素( elements)
List : 线性结构
Queue : 队列
Set : 元素不能重复,背后隐含着查找/搜索的语义
Deque : 双端队列
SortedSet : 一组有序的不能重复的元素
2、Map : 键值对 Key-Value-Pair ,背后隐含着查找****/搜索的语义
SortedMap : 一组有序的键值对
Collection 接口说明
打开帮助手册我们就能看到更多更详细的关于Collection的方法
Collection常用方法说明
方法签名 | 说明 |
---|---|
boolean add(E e) | 将元素e放入集合中 |
void clear() | 删除集合中的所有元素 |
boolean isEmpty() | 判断集合是否没有任何元素,俗称空集合 |
boolean remove(object e) | 如果元素e出现在集合中,删除其中一个 |
int size() | 返回集合中的元素个数 |
object[] toArray() | 返回一个装有所有集合中元素的数组 |
- E:代表的就是Collection 这里指定的字符串类型
- Collection的核心操作是增删改查。
代码示例:Collection常用方法的使用
public class TestDemo1 {
public static void main(String[] args) {
/**
*注意:
* (1)、Collection 需要导包
* (2)、Collection是一个接口,定义引用的时候不能new Collection ,应该new一个来自于Collection 的具体的类
* ,如:new ArrayList()、new LinkedList()等,他们都实现了Collection 接口,也可以发生向上转型。
* (3)、根据ArrayList()来举例,学习各个方法的使用*/
//《1、创建Collection》
Collection<String> collection1=new ArrayList<>();//这个意思表示collection1它所引用的是一个顺序表
//这个顺序表里面只能放String(字符串)
//Collection collection=new LinkedList();
//《2、使用add方法:将元素e放入集合中》
collection1.add("hehe");//add中的参数类型必须和泛型参数类型匹配
collection1.add("学习Java");
/*collection1.add(2);error:这样写就错了,因为Collection已经指定放一个字符串,所以不能放整型,必须放字符串。
如果想要放整型,就需要让Collection指定Integer包装类(如下),即需要放什么就指定什么
Collection<Integer> collection2=new ArrayList<>();*/
System.out.println("将元素e放入集合中:"+collection1);//打印集合里的东西
//《3、使用clear方法:删除集合中的所有元素》
collection1.clear();//因为ArrayList实现了collection接口,所以调用clear的时候,调用的不是collection中的clear,而是ArrayList重写clear这个方法
System.out.println("删除集合中的所有元素:"+collection1);
//《4、使用isEmpty方法:判断集合是否没有任何元素,俗称空集合》
System.out.println("判断集合是否没有任何元素:"+collection1.isEmpty());
//《5、使用remove方法:如果元素e出现在集合中,删除其中一个》
Collection<String> collection2=new ArrayList<>();
collection2.add("哈哈");
collection2.add("好好学习Java");
System.out.println("没删除元素之前:"+collection2);
collection2.remove("哈哈");
System.out.println("删除其中一个元素之后:"+collection2);
//《6、使用size方法:返回集合中的元素个数》
System.out.println("collection1的长度:"+collection1.size());
System.out.println("collection2的长度:"+collection2.size());
//《7、使用toArray方法:返回一个装有所有集合中元素的数组》
Collection<String> collection3=new ArrayList<>();
collection3.add("计算机工程学院");
collection3.add("计算机科学与技术");
collection3.add("班级:计本1801班");
collection3.add("学号:001");
collection3.add("备注");
System.out.println(collection3);
collection3.remove("计算机科学与技术");
System.out.println("删除其中一个元素之后:"+collection3);
//通过collection3去调用toArray就会把collection3里面所有的东西变成一个数组,toArray的返回值为Object[]类型的,一个数组,所以定义一个变量,接收一下,然后将这个数组打印出来。
Object[] objects=collection3.toArray();
System.out.println(Arrays.toString(objects));
}
}
打印结果:
也可使用for each打印,代码示例如下:
public static void main(String[] args) {
Collection<String> collection1=new LinkedList<>();
collection1.add("123");
collection1.add("小红");
collection1.add("小明");
//也可使用for each 进行打印,来遍历集合中的元素
//一般能用for each的就是它继承了Iterable接口
for (String s:collection1) {//s 就会分别指向collection中的每一个元素
System.out.println(s);
}
collection1.clear();
System.out.println(collection1);
}
//打印结果:
123
小红
小明
[]
代码句析1:
注意事项1:length和size的区别和使用格式
- 获取数组元素个数:使用.length 不带括号的
- 获取字符串字符个数:使用.length() 带括号的
- 获取集合元素个数:使用.size()
Map常用方法说明
方法签名 | 说明 |
---|---|
V get(Object k) | 根据指定的K查找对应的V |
V getOrDefault(Object k, V defaultValue) | 根据指定的 k 查找对应的 v,没有找到用默认值代替 |
V put(K key, V value) | 将指定的k-v放入map |
boolean containkey(Object key) | 判断是否包含key值 |
boolean containsValue(object value) | 判断是否包含 value |
Set<Map.Entry<k,v>> entrySet() | 将所有键值对返回 |
boolean isEmpty() | 判断是否为空 |
int size() | 返回键值对的数量 |
- Map是键值对<key,value>的形式写的,通过key来找到对应的value
- key可能是一个字符串,value也可能是一个字符串;
- 同Collection一样,Map是一个接口,定义引用的时候不能new Map ,应该new一个来自于Map 的具体的类
- new实体类,可以new HashMap或者TreeMap.
- Map的核心操作是增删改查以及get和put
代码示例:Map 常用方法的使用
public static void main(String[] args) {
//《1、创建Map实例》:它的泛型参数有两个,一个参数是key的类型,第二个参数是value的类型
Map<String,String> map=new HashMap<>();//哈希表
//2、put方法:《将指定的 k-v 放入 Map》
/*注意1:key值如果重复,value值必然是最新的那个
注意2:哈希表在打印数据的时候,打印的顺序不一定就是存储的顺序
注意3:key值尽量不要重复,value值可以重复*/
map.put("主持人","撒贝宁");
map.put("歌手","薛之谦");
map.put("演员","任嘉伦");
map.put("作家","鲁迅");
map.put("作品","《狂人日记》");
map.put("作品","《呐喊》");//key值如果重复,value值必然是最新的那个
System.out.println(map);//打印map里面的所有元素
//3、get方法:《根据指定的K查找对应的V》
String s= map.get("歌手");//get方法的返回值是一个V,对应Map里面的<K,V>,因为这里V是String,所以get的返回值就是String类型
//所以就可以通过String来接收,并打印
System.out.println(s);//歌手对应的value值是薛之谦
String s1=map.get("歌手1");//找歌手1所对应的value值,如果找不到则返回为null
System.out.println(s1);
//4、getOrDefault方法:《根据指定的 k 查找对应的 v,没有找到用默认值代替》
String s2= map.getOrDefault("歌手1","许嵩");//找歌手1所对应的value值,如果找不到默认值就给一个许嵩
System.out.println(s2);
//5、containsKey方法:《是否包含key值》
System.out.println(map.containsKey("作家"));//返回值是boolean类型
//6、containsValue方法:《判断是否包含 value》
System.out.println(map.containsValue("许嵩"));
//containsKey的执行效率比、containsValue的执行效率高,所以更推荐使用containsKey
//7、entrySet()方法:《将所有键值对返回》
Set<Map.Entry<String,String>> set=map.entrySet();//entrySet()方法的返回值是Set
//Entry:表示一个“条目”,也就是一个键值对
//map.entrySet():表示获取到所有的键值对
System.out.println(set);//将集合当中的元素打印出来
for (Map.Entry<String,String> entry:set) {//也可使用for each方式打印,打印出一个一个集合
/* entry.getKey();//拿到key值
entry.getValue();//拿到value值*/
System.out.println(entry.getKey()+"=="+entry.getValue());
}
//8、isEmpty方法《判断是否为空》
System.out.println(map.isEmpty());
//9、《返回键值对的数量》使用size获取到元素的个数,这里的个数指的是键值对的个数
System.out.println(map.size());
}
打印结果:
- 对Set<Map.Entry<K,V>> entrySet(),这个方法的解释:
实现Classes
这张图中表示的是每一个接口是由哪些类进行实现的。
interface | 顺序表 | 链表 | 堆 | 红黑树 | 哈希表 |
---|---|---|---|---|---|
Set | TreeSet | HashSet | |||
List | ArrayList | LinkedList | |||
Queue | LinkedList | PriorityQueue | |||
Deque | LinkedList | ||||
Map | TreeMap | HashMap |
除此之外,还会学习java中的栈stack。
注意重点内容
- Java 集合框架中接口、之间的关系及其含义。
- Java 集合框架中接口和其各自对应的常见实现类之间的关系。