数据结构概述
数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率
栈数据结构
特点:后进先出,先进后出,数据进入栈模型的过程称为:压/进栈。数据离开栈模型的过程称为:弹/出栈
队列数据结构
特点:先进先出,后进后出。数据从后端进入队列模型的过程称为:入队列。数据从前端离开队列模型的过程称为:出队列
数组
数组的数据结构模型:
特点:
1 查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
2 删除效率低:要将原始数据删除,同时后面每个数据前移。
3 添加效率极低:添加位置后的每个数据后移,再添加元素。
链表
链表种类包括单链表和多链表模型,其数据结构模型如下:
二叉树
二叉查找树又称二叉排序树或者二叉搜索树,其特点为:
1,每一个节点上最多有两个子节点
2,左子树上所有节点的值都小于根节点的值
3,右子树上所有节点的值都大于根节点的值
其目的是:提高检索数据的性能,一般数据模型如下:
集合
集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性调用即可实现各种复杂操作,大大提高软件的开发效率。
集合知识体系
集合特点
List系列集合:添加的元素是有序、可重复、有索引。
ArrayList、LinekdList :有序、可重复、有索引。
Set系列集合:添加的元素是无序、不重复、无索引。
HashSet: 无序、不重复、无索引;
LinkedHashSet: 有序、不重复、无索引。
TreeSet:按照大小默认升序排序、不重复、无索引
遍历
遍历就是一个一个的把(集合)容器中的元素访问一遍。
方式一:迭代器
方式二:foreach/增强for循环
方式三:lambda表达式
迭代器遍历
迭代器在Java中的代表是Iterator,迭代器是集合的专用遍历方式
List<String> list = new ArrayList();
list.add("a");
list.add("c");
list.add("b");
Iterator iterator =list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
增强for循环
语法结构:
for(元素数据类型 变量名 : 数组或者Collection集合) {
//在此处使用变量即可,该变量就是元素
}
代码示范
List<String> list = new ArrayList();
list.add("a");
list.add("c");
list.add("b");
for (String s : list) {
System.out.println(s);
}
Lambda表达式遍历
得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式
示例代码:
List<String> list = new ArrayList();
list.add("a");
list.add("c");
list.add("b");
lists.forEach(new Consumer<String>() {
@Override public void accept(String s) {
System.out.println(s); }});
list.forEach(s -> {
System.out.println(s);
});
List集合
List系列集合特点
ArrayList、LinekdList :有序,可重复,有索引。
有序:存储和取出的元素顺序一致
有索引:可以通过索引操作元素
可重复:存储的元素可以重复
List集合方法
List集合因为支持索引,所以多了很多索引操作的独特api(方法),其他Collection的功能List也都继承了。
List的实现类的底层原理
1 ArrayList底层是基于数组实现的,根据索引查询元素快,增删相对慢。
ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作。 第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组。
2 LinkedList底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API。
示范代码:
LinkedList<String> list = new LinkedList();
list.add("a");
list.add("c");
list.add("b");
list.removeFirst();
list.forEach(s -> {
System.out.println(s);
});
ArrayList与LinkedList的区别
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。(LinkedList是双向链表,有next也有previous)
2.对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
Set系列集合
Set系列集合特点
HashSet : 无序、不重复、无索引。
LinkedHashSet:有序、不重复、无索引。
TreeSet:排序、不重复、无索引。
HashSet底层原理:
HashSet集合底层采取哈希表存储的数据。 哈希表是一种对于增删改查数据性能都较好的结构
哈希表的组成 JDK8之前的,底层使用数组+链表组成 JDK8开始后,底层采用数组+链表+红黑树组成。
哈希表的详细流程:
哈希表的详细流程
创建一个默认长度16,默认加载因子为0.75的数组,数组名table
根据元素的哈希值跟数组的长度计算出应存入的位置
判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素, 则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组。
当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍
示例代码
Set hashSet = new HashSet<>();
hashSet.add("x");
hashSet.add("a");
hashSet.add("a");
hashSet.add("b");
hashSet.add("v");
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
LinkedHashSet集合特点
有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
LinkedHashSet原理
底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
示例代码
Set linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("x");
linkedHashSet.add("a");
linkedHashSet.add("a");
linkedHashSet.add("b");
linkedHashSet.add("v");
Iterator iterator = linkedHashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
TreeSet特点
不重复、无索引、可排序
可排序:按照元素的大小默认升序(由小到大)排序。
TreeSet底层原理
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。
示例代码
Set<Integer> hashSet = new TreeSet<>((o1, o2) ->
o2-o1
);
hashSet.add(7);
hashSet.add(1);
hashSet.add(2);
hashSet.add(3);
hashSet.add(3);
hashSet.add(4);
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
自定义排序
对于数值类型:Integer , Double,官方默认按照大小进行升序排序。 对于字符串类型:默认按照首字符的编号升序排序。想要使用TreeSet存储自定义类型,需要制定排序规则,代码如下
Set<Integer> hashSet = new TreeSet<>((o1, o2) ->
o2-o1
);
Set<Double> apples = new TreeSet<>(new Comparator<Double>() {
@Override
public int compare(Double o1, Double o2) {
return Double.compare(o1 , o2);
}
});
Set<Apple> apps = new TreeSet<>(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return Double.compare(o1.getPrice() , o2.getPrice());
}
});
Map集合体系
定义
Map集合是一种双列集合,每个元素包含两个数据。 Map集合的每个元素的格式:key=value(键值对元素)。 Map集合也被称为“键值对集合”。Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , ...}
特点
HashMap:元素按照 键是无序,不重复(键),无索引,值不做要求。
LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。
TreeMap:元素按照建是排序,不重复,无索引的,值不做要求。
Map API
Map集合的遍历
方式一:键找值的方式遍历:先获取Map集合全部的键,再根据遍历键找值。
方式二:键值对的方式遍历,把“键值对“看成一个整体,难度较大。
方式三:JDK 1.8开始之后的新技术:Lambda表达式。
Map集合的遍历方式一:键找值
先获取Map集合的全部键的Set集合。 遍历键的Set集合,然后通过键提取对应值。
示例代码
Map<String,String > map = new HashMap<>();
map.put("key01","a");
map.put("key02","b");
map.put("key03","c");
map.put("key04","d");
map.put("key05","e");
map.put("key06","f");
//map.put("key03","d");
Set<String> strings = map.keySet();
for (String key : strings) {
System.out.println("key="+key);
System.out.println("val="+map.get(key));
}
Map集合的遍历方式二:键值对
先把Map集合转换成Set集合,
Set集合中每个元素都是键值对实体类型了。
遍历Set集合,然后提取键以及提取值。
示例代码
Map<String,String > map = new HashMap<>();
map.put("key01","a");
map.put("key02","b");
map.put("key03","c");
map.put("key04","d");
map.put("key05","e");
map.put("key06","f");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("key="+entry.getKey());
System.out.println("val="+entry.getValue());
}
Map集合的遍历方式三:Lambda
得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。
示例代码
Map<String,String > map = new HashMap<>();
map.put("key01","a");
map.put("key02","b");
map.put("key03","c");
map.put("key04","d");
map.put("key05","e");
map.put("key06","f");
map.forEach((k,v)->{
System.out.println(k);
System.out.println(v);
});
LinkedHashMap集合概述和特点
由键决定:有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序
TreeMap集合概述和特点
由键决定特性:不重复、无索引、可排序
可排序:按照键数据的大小默认升序(有小到大)排序。只能对键排序。
注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序 TreeMap跟TreeSet一样底层原理是一样的。