Java学习笔记——浅谈数据结构与Java集合框架(第一篇、List)
横看成岭侧成峰,远近高低各不同。
不识庐山真面目,只缘身在此山中。
——苏轼
这一块儿学的是云里雾里,咱们先从简单的入手。逐渐的拨开迷雾见太阳。本次先做List集合的三个实现类的学习笔记
List特点:有序,元素可重复。其实它的本质就是一个线性表(下面会说到)
先上图,Java集合有Collection体系和Map体系:
然后简单介绍一下数据结构和算法:
数据结构就是数据和数据之间的关系,好比分子结构,晶体结构。碳原子按照一定的方式组合在一起形成碳分子,碳分子再按照一定方式形成晶体。
算法是对解题步骤的描述,体现在计算机上就是指令的有限序列
数据结构分为逻辑结构和物理结构。
逻辑结构:
物理结构:
顺序存储结构和链式存储结构。
顺序存储结构:在内存中开辟若干的连续空间,将每个空间存入数据,数据关联与其地址一致。比如数组。
上代码:
- public class Test01 {
- public static void main(String[] args) {
- Integer[] arr = new Integer[];
- //向数组中插入元素
- for (int i = ; i < arr.length; i++) {
- arr[i] = i;
- }
- //将其中一个元素变为null;
- arr[] = null;
- //出现碎片
- for (Integer item : arr) {
- System.out.println(item);
- }
- System.out.println("===========");
- arr[] = ;//存取方便,可直接赋值或取值
- //删除第X个元素,但要避免碎片产生:
- int x = ;
- arr[x-]=null;//第二个元素引用变为null,该步骤可以省略,因为下面又更改了arr[x-1]的引用。写上仅为便于理解
- //第X个元素之后的元素前移,代码表现为把后面的值依次赋给前面,从第X个开始
- for (int i = x-; i < arr.length-; i++) {
- arr[i] = arr[i+];
- }
- //length-1,需要新建数组来保存原数组
- Integer[] newArr = new Integer[arr.length-];
- for (int i = ; i < newArr.length; i++) {
- newArr[i]=arr[i];
- System.out.println(newArr[i]);
- }
- System.out.println("============");
- //第Y个位置插入一个元素
- int y = ;
- //需要后移,所以先创建数组length+1
- Integer [] newArr2 = new Integer[newArr.length+];
- for (int i = ; i < newArr.length; i++) {
- newArr2[i] = newArr[i];
- }
- //后移
- for (int i = newArr2.length-; i > y- ; i--) {
- newArr2[i]=newArr2[i-];
- }
- //插入
- newArr2[y-] = ;
- //遍历输出
- for (int i = ; i < newArr2.length; i++) {
- System.out.println(newArr2[i]);
- }
- }
- }
出结论:
顺序存储结构:
优点:1无需为表示表中元素之间的逻辑关系而添加空间
2可以快速地存取表中任意位置的元素
缺点:1插入和删除操作需要移动大量元素
2需要考虑索引越界为题
3扩容空间可能会造成空间浪费,缩小空间又可能会索引越界
4null值会造成空间“碎片”
链式存储结构:每个元素只记住它下一个元素是谁(地址)。
链式存储结构有多种,这里只介绍Java的链式存储结构:双向链表
上代码:
- public class MyLinkedListDemo {
- public static void main(String[] args) throws Exception {
- MyLinkList<String> list = new MyLinkList<>();
- list.addFist("张三");
- list.addFist("李四");
- list.addLast("张三");
- list.addLast("李四");
- list.print();
- System.out.println("===========");
- list.add(,"王五");
- list.print();
- System.out.println("===========");
- list.add(,"王五");
- System.out.println(list.getSize());
- list.add(,"王五");//这里会抛出空指针异常
- }
- }
- public class MyLinkList<E> {
- Node<E> first;
- Node<E> last;
- public void addFist(E e){
- if (first == null) {
- final Node<E> newNode = new Node<E>(null, e, null);//第一次加入数据,为first,last赋初值
- first = newNode;
- last = newNode;
- }else{//否则把first的prev指向newNode,把newNode的next指向first,最后把newNode变为first
- final Node<E> newNode = new Node<E>(null, e, first);
- first.prev = newNode;
- first = newNode;
- }
- }
- public void addLast(E e){
- if (last == null) {
- final Node<E> newNode = new Node<E>(null, e, null);//第一次加入数据,为first,last赋初值
- first = newNode;
- last = newNode;
- }else{//否则把last的next指向newNode,把newNode的prev指向last,最后把newNode变为last
- final Node<E> newNode = new Node<E>(last, e, null);
- last.next = newNode;
- last = newNode;
- }
- }
- public void add (int index,E e) throws Exception{//下标超出链表长度会空指针,因为超出长度的部分prev和next都是null
- if(index == ){
- addFist(e);
- }else if (index == getSize()) {
- addLast(e);
- }else {
- //这里画张图想一下,我要在1处插入x,就要把x的prev指向0,next指向1,把0的next指向x,把1的prev指向x
- //这里的1和0就是index和index-1,通过循环Node.next获取index对应的Node
- //先拿到0和1
- Node<E> tempNodeNext = first;
- for (int i = ; i < index; i++) {
- tempNodeNext = tempNodeNext.next;
- }
- Node<E> tempNodePrev = tempNodeNext.prev;
- //这里改指向
- final Node<E> newNode = new Node<E>(tempNodePrev, e, tempNodeNext);
- tempNodeNext.prev = newNode;
- tempNodePrev.next = newNode;
- }
- }
- public int getSize (){
- Node<E> temp = first;
- int i = ;
- while(temp != null){
- temp = temp.next;
- i++;
- }
- return i;
- }
- //由于不实现Iterable,只能提供打印方法
- public void print() {
- Node<E> temp = first;
- while(temp != null){
- System.out.println(temp.item);
- temp = temp.next;
- }
- }
- private static class Node<E>{
- Node<E> prev;
- E item;
- Node<E> next;
- Node(Node<E> prev, E item, Node<E> next) {
- super();
- this.prev = prev;
- this.item = item;
- this.next = next;
- }
- }
- }
出结论:
链式存储结构:
优点:插入和删除操作只需改变节点next和prev成员的指向即可,无需移位,无需扩容
缺点:失去了直接存取表中任意位置元素的能力
顺序存储结构和链式存储结构的对比:
1、存储分配方式:
顺序存储结构使用一段连续的存储单元依次存储线性表元素
链式存储结构使用任意存储单元存放线性表的元素
2、时间性能:
查找:
顺序存储结构O(1)
链式存储结构O(n)
插入和删除:
顺序存储结构O(n)
链式存储结构O(1)
3、空间性能:
顺序存储结构:空间分大了浪费,分小了上溢,还得扩容
链式存储结构:有空间就能分配,元素个数不受限制
言归正传。
ArrayList是顺序存储的线性表,LinkedList是链式存储的线性表
它们的特点都是有序,元素值可以重复。区别是底层算法不同。
Vector,这里我简单浏览了一下源代码,Vector底层算法和ArrayList是一样的
这里就不赘述了,直接说区别:
1、Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法线程不安全,由于线程的同步必然要影响性能,因此ArrayList的性能比Vector好。
2、Vector扩容时容量翻倍,而ArrayList只增加50%的大小,(直接查它们的grow()方法)这样,ArrayList就有利于节约内存空间。
总之ArrayList比Vector在性能方面(无论时间性能还是空间性能)都是能省则省。
List就说到这里。下一篇说说队列
Java学习笔记——浅谈数据结构与Java集合框架(第一篇、List)的更多相关文章
- Java学习笔记——浅谈数据结构与Java集合框架(第二篇、Queue、Set)
江南好,何处异京华. 香散翠帘多在水,绿残红叶胜于花.无事避风沙. --<纳兰词> 诗词再好,大图不能忘 上大图: 先说说栈和队列: 栈就好比手枪的弹匣,你往里面压入子弹,最先压入的子弹就 ...
- Java学习笔记——浅谈数据结构与Java集合框架(第三篇、Map)
桃李春风一杯酒,江湖夜雨十年灯 --寄黄几复 之前图上写错了,是Hashtable类.t是小写的,它是个很古老的类,以至于命名都没有那么规范.. HashMap HashMap就是存储key-valu ...
- java设计模式学习笔记--浅谈设计模式
设计模式的目的 编写软件的过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战.设计模式为了让程序具有更好的 1.代码重用性(即:相同功能的代码,不用多次编写) ...
- 疯狂Java学习笔记(84)----------大约 Java 对象序列化,你不知道 5 事
几年前,.当一个软件团队一起用 Java 书面申请.我认识比一般程序猿多知道一点关于 Java 对象序列化的知识所带来的优点. 关于本系列 您认为自己懂 Java 编程?其实,大多数程序猿对于 Jav ...
- 疯狂Java学习笔记(70)-----------挚爱Java
与大家分享! 挚爱Java 10个使用Java最广泛的现实领域 写好Java代码的30条经验总结 Java字符串的substring真的会引起内存泄露么? Java内存的原型及工作原理深度剖析 Jav ...
- Java学习笔记(十六)——Java RMI
[前面的话] 最近过的好舒服,每天过的感觉很充实,一些生活和工作的技巧注意了就会发现,其实生活也是可以过的如此的有滋有味,满足现在的状况,并且感觉很幸福. 学习java RMI的原因是最近在使用dub ...
- 0031 Java学习笔记-梁勇著《Java语言程序设计-基础篇 第十版》英语单词
第01章 计算机.程序和Java概述 CPU(Central Processing Unit) * 中央处理器 Control Unit * 控制单元 arithmetic/logic unit /ə ...
- Java学习笔记(十四)——Java静态工厂
[前面的话] 每天过的还行,对我来说,只要让自己充实,生活就会是好的. 学习Java工场方法的原因是最近在使用Spring框架做一个系统,其中有一个注入的方法是使用静态工场方法注入,所以学习一下,基础 ...
- 零基础学Java之Java学习笔记(一):Java概述
什么是Java? Java是一门面向对象编程语言,可以编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序. Java特点有哪些? 1.Java语言吸收了C++语言的各种优点,具有功能强大 ...
随机推荐
- 分块编码(Transfer-Encoding: chunked)
参考链接: HTTP 协议中的 Transfer-Encoding 分块传输编码 一.背景: 持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界:而对于持续连接,这种 ...
- 基于CDIF实现的——API在线自动化测试
传统的测试工具在测试一个API的时候,必须手动填写这个API所需要接收的所有信息,比如一个查询航班动态的API,他接收两个输入字段,一个叫flight, 一个叫date,那么测试这个API的用户,需要 ...
- Object-C开发常用宏定义
Object-C开发中宏会将经常用到的系统常量进行封装,方便使用: 1.获取通知中心 #define EYNotificationCenter(name, object, userInfo) [[NS ...
- adobe edge animate 和 adobe animate cc 有啥区别?
经常有人问这两款软件的区别,每次都要打字好烦,特此总结发帖如下: 一.首先各自软件介绍 ①adobe edge animate 是adobe公司早期推出的一款网页互动工具.通过HTML+CSS+Jav ...
- POPTEST老李分享session,cookie的安全性以及区别 3
如何查看服务器端输送到我们电脑中的这些Cookie信息: 点开IE浏览器或其他浏览器,在菜单栏中有工具选项,点开有InterNet选项: Cookie名称.来源.文件格式( ...
- 手机自动化测试:搭建appium手机自动化测试开发环境
手机自动化测试:搭建appium手机自动化测试开发环境 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大 ...
- C++11 新特性总结
前言 转载请注明出处,感谢! C++11 的新特性 1 变量和基本类型 1.1 long long 类型 扩展精度浮点数,10位有效数字 1.2 列表初始化 初始化的几种不同形式,其中用花括号来初始化 ...
- 《c#入门经典第五版》简介及pdf电子书网盘下载地址(收藏)
<C#入门经典(第5版)>全面讲解C# 2010和.net架构编程知识,为您编写卓越C# 2010程序奠定坚实基础.C#入门经典系列是屡获殊荣的C#名著和超级畅销书.最新版的<C#入 ...
- Vxlan与网卡offload性能
背景 由于数据链路层MTU的限制,发送端TCP/UDP数据在交付到IP层时需要与MTU相匹配,TCP数据不能超过mss,较长的UDP需要分片(Fragmentation)以满足MTU要求:接收端协议栈 ...
- 自行扩展 FineUIMvc 通知对话框(多个并排显示不重叠,支持最新的显示在最上方)
声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 这篇文章我们将改造 FineUIMvc 默认的通知对话框,使得同时显示多个也不会重叠.并提前出一个公共的JS文件,供大家使用. ...