Java链表基本操作和Java.util.ArrayList

今天做了一道《剑指offer》上的一道编程题“从尾到头打印链表”,具体要求如下:

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

一开始我想的是通过两次遍历链表,第一次遍历得到链表元素的个数count。然后定义一个ArrayList 变量,由于ArrayList是动态数组,不能在未初始化的情况下对任意位置进行插入指定的值。所以只能先对其进行初始化,将count个ArrayList元素赋值为初始值0。随后第二次遍历链表,将遍历得到的值,按照倒序计算出位置i,将ArrayList对应位置i的值设定为该遍历值。后来发现别人大多都是用递归来做的,因为递归的原理是堆栈,先进后出,所以最后实现的堆栈输出顺序正好是从尾到头的顺序。时间复杂度比我的方法要优。

通过今天的做题,发现自己对于Java对单链表的操作以及java.ArrayList()的一些特性不太熟悉,所以想把今天收集到的资料记录一下,让自己能够记得清楚一些。

Java对于单链表的基本操作:

链表是一种常见的数据结构,链表不同于数组,其存储的位置可能不是连续的。所以当我们想要在链表中查找指定位置的结点时,只能去对链表进行遍历。而数组则直接能够通过位置找到相应的元素结点,时间复杂度为O(1)。

单链表的结构如下图所示:

下面定义Java链表的实体类Node:

package com.algorithm.link;

public class Node {

Node next = null;

int val; //节点中的值public Node(int val) //Node的构造函数

{

this.val = val;

}

}

Java中对单链表的常见操作:

package com.algorithm.link;

public class MyLinkedList{

Node head = null; //定义头结点指针

/*-------------链表添加结点------------*/

public void addNode(int val)

{

Node NewNode = new Node(val);//创建要添加的结点

if(head==null) //当链表为空时

{

head=NewNode;

return;

}

else { //当链表不为空时,则先找到链表的尾结点,然后插入待插入的结点

Node tmp = head;

while(tmp.next!=null)

{

tmp=tmp.next;

}

tmp.next=NewNode;//此时tmp为链表的尾结点

}

}

/*------------链表删除结点----------*/

public boolean deleteNode(int index)

{

if(index==1)//说明删除的是头节点

{

head=head.next;

return true;

}

int i=2;

//因为链表不止两个结点,所以定义一个前结点,一个当前结点,分别指向目标结点的前结点和目标结点

Node preNode = head;

Node curNode = head.next;

while(curNode!=null)

{

if(index==i)//找到要删除的结点了,此时curNode指向该结点

{

preNode.next=curNode.next;//删除结点

return true;

}

//preNode和curNode结点分别向后移动一位

preNode=preNode.next;

curNode=curNode.next;

i++;

}

return true;//按照前面的一定能够找到待删除的结点,这句语句不会执行,只是为了程序能够通过编译。

}

}

Java.util.ArrayList:

ArrayList是一种动态数组,可以根据元素增加的情况动态的重新分配空间,是Array的复杂版本。

ArrayList相对于Array有以下几个优点:

可以动态的增加或减少元素

实现了ICollection和IList接口

可以灵活的设置数组的大小

首先构建一个ArrayList,其提供了三种构造方法:

public ArrayList();

默认的构造器,将会以默认(16)的大小来初始化内部的数组

public ArrayList(ICollection);

用一个ICollection对象来构造,并将该集合的元素添加到ArrayList

public ArrayList(int);

用指定的大小来初始化内部的数组

在构造ArrayList时,可以指定ArrayList的类型,例:ArrayList a = new ArrayList();或ArrayList b = new ArrayList();但指定的类型必须为构造器类型(component type)

对ArrayList的基本操作:

add() 增加元素

remove(Object o) 遍历ArrayList,删除遇到的第一个指定的元素o

例: a.remove(new Integer(8)) //删除第一个元素值为8的元素

remove(index i) 根据下标来删除ArrayList中指定位置的元素

clear() 清除ArrayList中的所有元素

contains(Object o) 判断ArrayList中是否存在指定值的元素

将ArrayList 转换为Array数组:

ArrayList提供 public T[] toArray(T[] a) 方法能够将ArrayList类型数组转换为普通Array数组,例如我们定义了一个Integer 类型的ArrayList数组: ArrayList a = new ArrayList() 并在其上通过循环,add了10个元素。此时,我们若想将其转换成为数组可以这样去转换:

Integer[] value=(Integer[])a.toArray(new Integer[a.size()]);

上述返回的数组的长度大小正好为a数组的大小,我们也可以指定new Integer[]里面的数字,当该长度容纳不下待转换的ArrayList元素个数时,该方法会重新依据ArrayList的大小重新分配一个数组,将ArrayList a 中的元素复制到里面并返回。当指定的数目大于a中的元素个数时,也就是数组的空间有剩余。此时,toArray()方法会将剩余的数组部分的元素值都置为 null。

将数组转换为ArrayList:

String数组 array;

List list=Arrays.asList(array); //将String数组array转化成List

但上述的转化方法返回的list无法对其进行修改和增加元素,仿佛是静态固定的。[解释] 所以还可以通过以下的方法去将数组转换成ArrayList:

ArrayList c = new ArrayList(Arrays.asList(array));

此时返回的ArrayList数组可以正常地对其进行操作。

关于数组扩容对ArrayList效率的影响问题:

当我们以默认不带指定大小的构造器去构造一个ArrayList时,默认会将其大小初始化分配为16。在我们使用增加元素的方法之前,例如使用add()、addAll()等,都会首先检查内部数组的大小是否够用,如果不够用,则会以当前容量的两倍来重新构建一个数组,并将旧数组的元素copy到新数组中,并丢弃掉旧数组。这种在临界点进行扩容的操作,会比较影响效率。

比如,一个可能有200个元素的数据动态添加到一个以默认16个元素大小创建的ArrayList中,将会经过: 16*2*2*2*2 = 256 四次的扩容才会满足最终的要求,那么如果一开始就以: ArrayList List = new ArrayList( 210 ); 的方式创建ArrayList,不仅会减少4次数组创建和Copy的操作,还会减少内存使用。

另外一种可能发生的情况是,比如我们定义了一个ArrayList数组,且其大小为30,但我们却有31个元素要添加进去,该ArrayList数组则会经过一个扩容容量变为60,这样最后便会有29个元素的存储空间是浪费掉的。此时,我们可以通过 trimToSize 方法去让当前数组的大小变为实际元素个数的大小,还可以提前大致预测一下数组的大小,然后在数组创建之时就指定好大小,这样能够避免去浪费更多的空间。

java.util.Arrays()、java.util.ArrayList()、java数组之间的关系:

Arrays()实现了对数组的一系列操作方法,而ArrayList是动态数组,其大小可以动态变化。

参考文章

java实现单链表操作 : https://www.cnblogs.com/bjh1117/p/8335108.html

java.util.ArrayList() :

https://www.cnblogs.com/qingchunshiguang/p/6103731.html

怎么使用java初始化链表_Java链表基本操作和Java.util.ArrayList相关推荐

  1. java初始化实例化_Java对象的创建过程:类的初始化与实例化

    一.Java对象创建时机 我们知道,一个对象在可以被使用之前必须要被正确地实例化.在Java代码中,有很多行为可以引起对象的创建,最为直观的一种就是使用new关键字来调用一个类的构造函数显式地创建对象 ...

  2. java类描述_java笔记2:Java语言中的类和对象的描述

    在Java 语言中,除8 个基本数据类型值之外, 一切都是对象,而对象就是面向对象程序设计的中心. 对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还 ...

  3. java 初始化和清楚_浅谈Java中的初始化和清理

    引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...

  4. java display.getdefault()_java基础(十一 )-----反射——Java高级开发必须懂的

    本文我们通过一个实际的例子来演示反射在编程中的应用,可能之前大家对反射的学习,仅仅是停留在概念层面,不知道反射究竟应用在哪,所以是一头雾水.相信通过这篇教程,会让你对反射有一个更深层次的认知. 概念 ...

  5. java jdk 观察者模式_java观察者模式实现和java观察者模式演化

    简单的观察者模式实现 import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; impo ...

  6. java回收类_Java的内存回收——Java引用的种类

    1.Java引用的种类 Java是面向对象的编程语言,一个Java程序往往需要创建大量的Java类,然后对各Java类创建大量的Java对象,再调用这些Java对象的属性和方法来操作它们. 程序员需要 ...

  7. java范型_Java知识点总结(Java泛型)

    Java知识点总结(Java泛型) @(Java知识点总结)[Java, Java泛型] [toc] 泛型 泛型就是参数化类型 适用于多种数据类型执行相同的代码 泛型中的类型在使用时指定 泛型归根到底 ...

  8. java语言编译_java在线编译-编译,java

    本教程分享:<java在线编译>, java在线编译网站或工具有哪些? 你做了很多了吧!很好,继续学吧! class.forName():加载的是指定的一个类 .class文件是由JAVA ...

  9. java干嘛_java是什么(Java到底能干嘛?)

    我刚开始学习Java的时候,很长一段时间都有这么个疑惑? Java到底是啥?它能干什么? 自己也看过不少的课程和书,大部分都是从Java的发展史开始讲,总之就是那些什么Java历史悠久,Java很优秀 ...

  10. 码出高效:java开发手册_Java 11手册:Java专家分享他们在Java 11方面的最佳和最差的经验

    码出高效:java开发手册 Java 10标志着Java生态系统新时代的开始,但最新版本证明仍有一些里程碑可言. Java 11是Oracle新的六个月周期中的第一个LTS版本. 您可以在此处下载Ja ...

最新文章

  1. Stringtie进行转录本组装和定量
  2. libvirt(virsh命令介绍)
  3. iar烧录程序步骤_STM8入门以及程序编译、烧录、IAR使用方法(扫盲篇...
  4. maven 打包编译_您是否真的想加快Maven的编译/打包速度? 那么takari生命周期插件就是答案。...
  5. Fitness - 05.23
  6. 企业资源计划软件 业务知识点汇编整理
  7. Python类和对象的入门级讲解(简单粗暴)
  8. 阿里影业正式成为阿里集团子公司 俞永福辞任执行董事
  9. 基于python的性能负载测试Locust-6-脚本编写之使用HTTP client
  10. CCF-CSP认证备考要点
  11. Solaris10文件布局
  12. R语言ETL工程:插入与合并(add/bind)
  13. 报表性能优化方案之行引擎执行层式报表
  14. mysql截取身份证号前几位_EXCEL中怎样截取身份证号前六位数字
  15. 原生js页面滚动顶部显示滚动总进度条效果
  16. printf打印二进制数据
  17. 台式计算机摄像头插哪,台式电脑摄像头怎么调试
  18. 组合数学 多重集的排列和组合
  19. 测试qq和微信voip内网穿透
  20. Python-随机生成20位数字

热门文章

  1. IP6826无线充电底座方案IC芯片,兼容WPC Qi v1.2.4
  2. 8位数控分频器的设计_数控分频器的设计实验报告
  3. QQ拼音输入法词库和搜狗输入法词库[相互导入](使用Excel公式)
  4. 黑客社会工程学攻击特别危险,你知道多少?
  5. python 日历控件_PyQt5每天必学之日历控件QCalendarWidget
  6. 有限单元法(The Finite Element Method)
  7. Android异步通信:深入剖析Handler机制源码
  8. 大牛直播SDK-Windows推送端使用说明
  9. 91卫图免费版使用步骤
  10. 2013年最新热门软件分享第一季