Java SE入门及基础(50)& Java实现LinkedList(单向链表、双向链表)& Java实现栈

目录

[List 接口](#List 接口)

[1. 特性描述](#1. 特性描述)

[List 接口常用方法](#List 接口常用方法)

[2. ArrayList](#2. ArrayList)

示例及源码解读

[3. LinkedList](#3. LinkedList)

示例及源码解读

单向链表

双向链表

[4. 栈](#4. 栈)

练习

[Java SE文章参考:Java SE入门及基础知识合集-CSDN博客](#Java SE文章参考:Java SE入门及基础知识合集-CSDN博客)

List 接口

**1.**特性描述

A List is an ordered Collection (sometimes called a sequence). Lists may contain duplicate elements.
列表是有序的集合(有时称为序列)。 列表可能包含重复的元素。
The Java platform contains two general-purpose List implementations. ArrayList, which is usually the better-performing implementation, and LinkedList which offers better performance under certain circumstances.
Java 平台包含两个常用的 List 实现。 ArrayList 通常是性能较好的实现,而 LinkedList 在某些情况下可以提供更好的性能。

List 接口常用方法

E get ( int index ); // 获取给定位置的元素
E set ( int index , E element ); // 修改给定位置的元素
void add ( int index , E element ); // 在给定位置插入一个元素
E remove ( int index ); // 移除给定位置的元素
int indexOf ( Object o ); // 获取给定元素第一次出现的下标
int lastIndexOf ( Object o ); // 获取给定元素最后一次出现的下标
ListIterator < E > listIterator (); // 获取 List 集合专有的迭代器
ListIterator < E > listIterator ( int index ); // 获取 List 集合专有的迭代器,从给定的下标位置开始的迭代器
List < E > subList ( int fromIndex , int toIndex ); // 获取 List 集合的一个子集合

**2.**ArrayList

示例及源码解读

import java . util . ArrayList ;
import java . util . Iterator ;
import java . util . List ;
import java . util . ListIterator ;
public class ArrayListTest {
public static void main ( String [] args ) {
//集合有序是指存储顺序与遍历时取出来的顺序一致
ArrayList < String > list = new ArrayList <> ();
list . add ( "a" ); // 第一次调用 size =0;
list . add ( "a" );
list . add ( "b" );
list . add ( "c" );
list . add ( "d" );
list . add ( 2 , "n" ); // a a b c d => a a b b c d => a a n b c d
String old = list . set ( 1 , "g" );
System . out . println ( old );
System . out . println ( "====================" );
for ( String str : list ){
System . out . println ( str );
}
System . out . println ( "====================" );
Iterator < String > iter = list . iterator ();
while ( iter . hasNext ()){
String s = iter . next ();
System . out . println ( s );
}
System . out . println ( "====================" );
ListIterator < String > listIterator = list . listIterator ();
while ( listIterator . hasNext ()){
String s = listIterator . next ();
System . out . println ( s );
}
System . out . println ( "====================" );
ListIterator < String > prevIterator = list . listIterator ( list . size ());
while ( prevIterator . hasPrevious ()){
String s = prevIterator . previous ();
System . out . println ( s );
}
System . out . println ( "====================" );
List < String > subList = list . subList ( 2 , 4 );
for ( String str : subList ){
System . out . println ( str );
}
System . out . println ( "====================" );
int size = list . size ();
for ( int i = 0 ; i < size ; i ++ ){
String s = list . get ( i );
System . out . println ( s );
}
System . out . println ( "===================" );
ArrayList < Integer > numbers = new ArrayList <> ();
numbers . add ( 1 );
numbers . add ( 2 );
numbers . add ( 3 );
numbers . add ( 4 );
//移除下标为 3 这个位置的元素
numbers . remove ( 3 ); // 这是移除下标为 3 这个位置的元素还是移除 3 这个元素?
//移除 3 这个元素
numbers . remove (( Integer ) 3 );
for ( Integer number : numbers ){
System . out . println ( number );
}
numbers . add ( 2 );
numbers . add ( 2 );
int index1 = numbers . indexOf ( 2 );
int index2 = numbers . lastIndexOf ( 2 );
System . out . println ( index1 );
System . out . println ( index2 );
}
}

  • ArrayList 继承于 AbstractList , AbstractList 继承于 AbstractColletion
  • ensureCapacityInternal(int minCapacity) 确保数组有足够的容量来存储新添加的数据
  • void grow(int minCapacity) 实现数组扩容,扩容至原来的1.5倍
  • ListItr 可以从前到后对集合进行遍历,也可以从后往前对集合进行遍历,还可以向集合中添加元素,修改元素。而 Itr 只能从前到后对集合进行遍历。
    ArrayList底层采用的是数组来存储元素,根据数组的特性, ArrayList 在随机访问时效率极高,在增加 和删除元素时效率偏低,因为在增加和删除元素时会涉及到数组中元素位置的移动。 ArrayList 在扩容 时每次扩容到原来的 1.5

**3.**LinkedList

示例及源码解读

单向链表

package com . wq . list ;
/**
* 自定义单向链表
* @param <T> 泛型变量
*/
public class MyNode < T > {
private T data ; // 链中存储的数据
private MyNode < T > next ; // 下一个链
public MyNode ( T data , MyNode < T > next ) {
this . data = data ;
this . next = next ;
}
public T getData () {
return data ;
}
public void setData ( T data ) {
this . data = data ;
}
public MyNode < T > getNext () {
return next ;
}
public void setNext ( MyNode < T > next ) {
this . next = next ;
}
}
package com . wq . list ;
public class MyNodeTest {
public static void main ( String [] args ) {
MyNode < String > first = new MyNode <> ( " 第一个链 " , null );
MyNode < String > second = new MyNode <> ( " 第二个链 " , null );
first . setNext ( second );
MyNode < String > third = new MyNode <> ( " 第三个链 " , null );
second . setNext ( third );
MyNode < String > fourth = new MyNode <> ( " 第四个链 " , null );
third . setNext ( fourth );
MyNode < String > nextNode = first ;
while ( nextNode != null ){
System . out . println ( nextNode . getData ());
nextNode = nextNode . getNext ();
}
System . out . println ( "===================" );
MyNode < Integer > number4 = new MyNode <> ( 4 , null );
MyNode < Integer > number3 = new MyNode <> ( 3 , number4 );
MyNode < Integer > number2 = new MyNode <> ( 2 , number3 );
MyNode < Integer > number1 = new MyNode <> ( 1 , number2 );
MyNode < Integer > next = number1 ;
while ( next != null ){
System . out . println ( next . getData ());
next = next . getNext ();
}
}
}

双向链表

package com . wq . list ;
/**
* 自定义双向链表
* @param <T>
*/
public class DeNode < T > {
private T data ; // 链中存储的数据
private DeNode < T > prev ; // 前一个链
private DeNode < T > next ; // 后一个链
public DeNode ( T data , DeNode < T > prev , DeNode < T > next ) {
this . data = data ;
this . prev = prev ;
this . next = next ;
}
public T getData () {
return data ;
}
public void setData ( T data ) {
this . data = data ;
}
public DeNode < T > getPrev () {
return prev ;
}
public void setPrev ( DeNode < T > prev ) {
this . prev = prev ;
}
public DeNode < T > getNext () {
return next ;
}
public void setNext ( DeNode < T > next ) {
this . next = next ;
}
}
package com . wq . list ;
public class DeNodeTest {
public static void main ( String [] args ) {
DeNode < Integer > number1 = new DeNode <> ( 1 , null , null );
DeNode < Integer > number2 = new DeNode <> ( 2 , number1 , null );
number1 . setNext ( number2 );
DeNode < Integer > number3 = new DeNode <> ( 3 , number2 , null );
number2 . setNext ( number3 );
DeNode < Integer > number4 = new DeNode <> ( 4 , number3 , null );
number3 . setNext ( number4 );
DeNode < Integer > nextNode = number1 ;
while ( nextNode != null ){
System . out . println ( nextNode . getData ());
nextNode = nextNode . getNext ();
}
System . out . println ( "==================" );
DeNode < Integer > prevNode = number4 ;
while ( prevNode != null ){
System . out . println ( prevNode . getData ());
prevNode = prevNode . getPrev ();
}
}
}

  • LinkedList 继承于 AbstractSequentialList , AbstractSequentialList 继承于 AbstractList , AbstractList 继承于 AbstractColletion
  • void addFirst(E e) 将数据存储在链表的头部
  • void addLast(E e) 将数据存储在链表的尾部
  • E removeFirst() 移除链表头部数据
  • E removeLast() 移除链表尾部数据

package com . wq . list ;
import java . util . LinkedList ;
public class LinkedListTest {
public static void main ( String [] args ) {
LinkedList < String > list = new LinkedList <> ();
list . add ( " 第一个字符串 " );
list . add ( " 第二个字符串 " );
list . addLast ( " 第三个字符串 " );
list . addFirst ( " 第四个字符串 " );
String first = list . removeFirst (); // 将第一个链移除
String last = list . removeLast (); // 将最后一个链移除
System . out . println ( first );
System . out . println ( last );
first = list . getFirst ();
last = list . getLast ();
System . out . println ( first );
System . out . println ( last );
}
}
LinkedList底层采用的是双向链表来存储数据,根据链表的特性可知, LinkedList 在增加和删除元素时 效率极高,只需要链之间进行衔接即可。在随机访问时效率较低,因为需要从链的一端遍历至链的另一 端。

**4.**

package com . wq . list ;
import java . util . ArrayList ;
/**
* 自定义栈:后进先出
*/
public class MyStack < T > extends ArrayList < T > {
public void push ( T t ){
add ( t );
}
public T pop (){
if ( size () == 0 ) throw new IllegalArgumentException ( " 栈里没有数据啦 " );
T t = get ( size () - 1 );
remove ( t );
return t ;
}
}
package com .wq . list ;
public class MyStackTest {
public static void main ( String [] args ) {
MyStack < Integer > stack = new MyStack <> ();
stack . push ( 1 );
stack . push ( 2 );
stack . push ( 3 );
stack . push ( 4 );
stack . push ( 5 );
while ( ! stack . isEmpty ()){
System . out . println ( stack . pop ());
}
}
}

练习

从控制台录入5 位学生信息:姓名,性别,年龄,成绩,并将这些学生信息以 "," 衔接起来,然后存储至文本中。然后再从文本中将这些信息读取至集合中。

package com . wq . list ;
import java . io . * ;
import java . util . ArrayList ;
import java . util . List ;
import java . util . Scanner ;
/**
* 从控制台录入 5 位学生信息:姓名,性别,年龄,成绩,并将这些学生信息以 "," 衔接起来,
* 然后存储至文本中。然后再从文本中将这些信息读取至集合中。
*/
public class Exercise {
public static void main ( String [] args ) {
List < Student > students = new ArrayList <> ();
Scanner sc = new Scanner ( System . in );
for ( int i = 0 ; i < 5 ; i ++ ){
System . out . println ( " 请输入姓名: " );
String name = sc . next ();
System . out . println ( " 请输入性别: " );
String sex = sc . next ();
System . out . println ( " 请输入年龄: " );
int age = sc . nextInt ();
System . out . println ( " 请输入成绩: " );
double score = sc . nextDouble ();
students . add ( new Student ( name , sex , age , score ));
}
saveStudents ( students , "F:\\stu\\stu.txt" );
List < Student > read = readStudents ( "F:\\stu\\stu.txt" );
for ( Student stu : read ){
System . out . println ( stu );
}
}
public static List < Student > readStudents ( String path ){
List < Student > students = new ArrayList <> ();
try ( FileReader reader = new FileReader ( path );
BufferedReader br = new BufferedReader ( reader );){
String line ;
while (( line = br . readLine ()) != null ){
String [] arr = line . split ( "," );
//name + "," + sex +"," + age + "," + score;
String name = arr [ 0 ];
String sex = arr [ 1 ];
int age = Integer . parseInt ( arr [ 2 ]); // Float.parseFloat()
double score = Double . parseDouble ( arr [ 3 ]);
students . add ( new Student ( name , sex , age , score ));
}
} catch ( FileNotFoundException e ) {
e . printStackTrace ();
} catch ( IOException e ) {
e . printStackTrace ();
}
return students ;
}
public static void saveStudents ( List < Student > students , String path ){
File file = new File ( path );
File parent = file . getParentFile ();
if ( ! parent . exists ()) parent . mkdirs ();
try ( FileWriter writer = new FileWriter ( file );
BufferedWriter bw = new BufferedWriter ( writer );){
for ( Student stu : students ){
bw . write ( stu . toString ());
bw . newLine ();
}
bw . flush ();
} catch ( IOException e ) {
e . printStackTrace ();
}
}
}

Java SE文章参考:Java SE入门及基础知识合集-CSDN博客

相关推荐
煸橙干儿~~8 分钟前
分析JS Crash(进程崩溃)
java·前端·javascript
2401_854391089 分钟前
Spring Boot大学生就业招聘系统的开发与部署
java·spring boot·后端
Amor风信子10 分钟前
华为OD机试真题---跳房子II
java·数据结构·算法
我是陈泽13 分钟前
一行 Python 代码能实现什么丧心病狂的功能?圣诞树源代码
开发语言·python·程序员·编程·python教程·python学习·python教学
优雅的小武先生23 分钟前
QT中的按钮控件和comboBox控件和spinBox控件无法点击的bug
开发语言·qt·bug
虽千万人 吾往矣29 分钟前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
创作小达人32 分钟前
家政服务|基于springBoot的家政服务平台设计与实现(附项目源码+论文+数据库)
开发语言·python
郭二哈35 分钟前
C++——list
开发语言·c++·list
杨荧36 分钟前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源
ZPC821042 分钟前
Python使用matplotlib绘制图形大全(曲线图、条形图、饼图等)
开发语言·python·matplotlib