JavaSE学习笔记-chapter07-集合
学习资源:动力节点java学习
更新日志
- 2024.6.6更新至13小节(手写单向链表)
文章目录
第七章 集合
1. 集合概述
2. 集合的继承结构(Java21)
3. Collection接口的通用方法
package addery.zeus.com.collectiontest;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Collection;
/**
* Collection接口的通用方法
*/
public class CollectionMethodTest {
// 向集合中添加元素 获取集合中元素个数
@Test
public void testAddAndSize() {
Collection c = new ArrayList();
c.add(10); // 自动装箱
c.add(3.14); // 自动装箱
c.add(false); // 自动装箱
c.add("Addery");
c.add(new Object());
System.out.println(c.size()); // 5
}
// 将参数集合中所有元素全部加入当前集合
@Test
public void testAddAll() {
Collection c1 = new ArrayList();
c1.add(10);
c1.add(3.14);
c1.add(false);
Collection c2 = new ArrayList();
c2.addAll(c1);
System.out.println(c2.size()); // 3
}
// 判断集合中是否包含对象o
@Test
public void testContains() {
Collection c1 = new ArrayList();
c1.add(10);
c1.add(3.14);
c1.add(false);
c1.add("addery");
System.out.println(c1.contains(10)); // true
System.out.println(c1.contains(100)); // false
String s = new String("addery");
// 重写了equals方法,比较时使用equals
System.out.println(c1.contains(s)); // true
}
// 从集合中删除对象o
@Test
public void testRemove() {
Collection c1 = new ArrayList();
c1.add(10);
c1.add(3.14);
c1.add(false);
c1.add("addery");
System.out.println(c1.size()); // 4
System.out.println(c1.remove(10)); // true
System.out.println(c1.size()); // 3
System.out.println(c1.remove(10)); // false
String s = new String("addery");
// 底层会调用equals方法来完成删除
System.out.println(c1.remove(s)); // true
System.out.println(c1.size()); // 2
}
// 清空集合 判断集合元素个数是否为空
@Test
public void testClear() {
Collection c1 = new ArrayList();
c1.add(10);
c1.add(3.14);
c1.add(false);
c1.add("addery");
System.out.println(c1.size()); // 4
System.out.println(c1.isEmpty()); // false
c1.clear();
System.out.println(c1.size()); // 0
System.out.println(c1.isEmpty()); // true
}
// 将集合转换成一维数组
@Test
public void testToArray() {
Collection c1 = new ArrayList();
c1.add(10);
c1.add(3.14);
c1.add(false);
c1.add(new Object());
Object[] array = c1.toArray();
for(Object obj : array) {
System.out.println(obj);
}
}
}
4. Collection的通用遍历方式
package addery.zeus.com.collectiontest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Collection接口通用迭代器
*/
public class CollectionTest01 {
public static void main(String[] args) {
// 创建集合对象
Collection c1 = new ArrayList();
// 向集合中添加元素
c1.add(10);
c1.add(3.14);
c1.add(true);
// 创建迭代器对象
Iterator iterator = c1.iterator();
System.out.println(iterator);
// 判断当前光标处是否有元素
while(iterator.hasNext()) {
// 返回当前元素,并将光标向后移动一格
Object next = iterator.next();
System.out.println(next);
}
}
}
5. SequencedCollection接口
package addery.zeus.com.sequncedcollectiontest;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.SequencedCollection;
/**
* SequencedCollection接口常用方法单元测试
* ArrayList LinkedList Vector LinkedHashSet TreeSet Stack都可以调用这个接口中的方法
*/
public class SequencedCollectionMethodTest {
/**
* 向头部添加元素 向末尾添加
*/
@Test
public void testAddFirstAndAddLast() {
SequencedCollection<String> sc = new ArrayList<>();
sc.add("zhangsan1");
sc.add("zhangsan2");
sc.add("zhangsan3");
sc.add("zhangsan4");
sc.add("zhangsan5");
sc.add("zhangsan6");
sc.addFirst("Zeus");
sc.addLast("Addery");
Iterator<String> iterator = sc.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
/**
* 删除头部 删除末尾
*/
@Test
public void testRemoveFirstAndRemoveLast() {
SequencedCollection<String> sc = new ArrayList<>();
sc.add("zhangsan1");
sc.add("zhangsan2");
sc.add("zhangsan3");
sc.add("zhangsan4");
sc.add("zhangsan5");
sc.add("zhangsan6");
sc.removeFirst();
sc.removeLast();
Iterator<String> it = sc.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
/**
* 获取头部节点 获取尾部节点
*/
@Test
public void testGetFirstAndGetLast() {
SequencedCollection<String> sc = new ArrayList<>();
sc.add("zhangsan1");
sc.add("zhangsan2");
sc.add("zhangsan3");
sc.add("zhangsan4");
sc.add("zhangsan5");
sc.add("zhangsan6");
System.out.println(sc.getFirst()); // zhangsan1
System.out.println(sc.getLast()); // zhangsan6
}
/**
* 翻转集合中的元素
*/
@Test
public void testReversed() {
SequencedCollection<String> sc = new ArrayList<>();
sc.add("zhangsan1");
sc.add("zhangsan2");
sc.add("zhangsan3");
sc.add("zhangsan4");
sc.add("zhangsan5");
sc.add("zhangsan6");
SequencedCollection<String> reversed = sc.reversed();
Iterator<String> iterator = reversed.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
6. 泛型(Java5)
6.1 初识泛型
package addery.zeus.com.genericitytest;
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void print() {
System.out.println(this.name + "正在打印");
}
}
package addery.zeus.com.genericitytest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class GenericityTest02 {
public static void main(String[] args) {
// 如果不使用泛型
//Collection collection = new ArrayList();
Collection<User> collection = new ArrayList<User>();
// 钻石表达式 省略后面泛型的类型
//Collection<User> collection = new ArrayList<>();
User user1 = new User("zhangsan");
User user2 = new User("wangwu");
collection.add(user1);
collection.add(user2);
//Iterator iterator = collection.iterator();
Iterator<User> iterator = collection.iterator();
while(iterator.hasNext()) {
// 不使用泛型 只能做向下转型
//Object next = iterator.next();
//User next1 = (User) next;
//next1.print();
User next = iterator.next();
next.print();
}
}
}
package addery.zeus.com.genericitytest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class GenericityTest01 {
public static void main(String[] args) {
// 指定了集合中存储元素的类型
Collection<String> collection = new ArrayList<String>();
// 向集合中添加元素
collection.add("addery");
collection.add("zeus");
// 编译器报错 只能向集合中添加String类型元素
//collection.add(10);
// 遍历集合
Iterator<String> iterator = collection.iterator();
while(iterator.hasNext()) {
String next = iterator.next();
// 使用String类型的方法
System.out.println(next.charAt(1));
}
}
}
6.2 泛型的擦除与补偿
6.3 泛型的定义
6.3.1 在类上定义泛型
package addery.zeus.com.genericitytest;
public class Student <S> {
private S name;
public S getName() {
return name;
}
public void setName(S name) {
this.name = name;
}
public Student() {
}
public Student(S name) {
this.name = name;
}
}
package addery.zeus.com.genericitytest;
public class GenericityTest03 {
public static void main(String[] args) {
Student<String> stringStudent = new Student<String>();
stringStudent.setName("zhangsan");
String name = stringStudent.getName();
// 编译器报错
//stringStudent.setName(10);
}
}
package addery.zeus.com.genericitytest;
public class Animals <N, A>{
private N name;
private A age;
public Animals() {
}
public Animals(N name, A age) {
this.name = name;
this.age = age;
}
public N getName() {
return name;
}
public void setName(N name) {
this.name = name;
}
public A getAge() {
return age;
}
public void setAge(A age) {
this.age = age;
}
}
package addery.zeus.com.genericitytest;
public class GenericityTest04 {
public static void main(String[] args) {
Animals<String, Integer> an = new Animals<>();
an.setAge(10);
Integer age = an.getAge();
an.setName("Zeus");
String name = an.getName();
}
}
6.3.2 在静态方法上定义泛型
在类名上的泛型都实在实例化对象时使用,或者说初始化的,但对于静态方法不涉及对象所以无法使用类名上的泛型
package addery.zeus.com.genericitytest;
public class GenericityTest05{
/*
如果在静态方法中使用泛型,则需要再方法返回值类型前面进行泛型的声明。
public static <E> void eatable(E e) {
}
*/
public static <E> void eatable(E[] es) {
for (E e : es) {
System.out.println(e);
}
}
public static void main(String[] args) {
String[] strs = {"zzy", "addery", "zeus"};
eatable(strs);
}
}
6.3.3 在接口上定义泛型
package addery.zeus.com.genericitytest;
public interface Flyable <T>{
void fly(T t);
}
package addery.zeus.com.genericitytest;
// 知道具体的类型
public class Bird implements Flyable<Bird>{
@Override
public void fly(Bird bird) {
}
}
package addery.zeus.com.genericitytest;
// 不知道具体的类型
public class Plane <A> implements Flyable<A>{
@Override
public void fly(A a) {
}
}
接口上使用泛型的区别
package addery.zeus.com.genericitytest;
public interface MyComparable<C> {
int compareTo(C c);
}
package addery.zeus.com.genericitytest;
/**
* 实现接口不使用泛型,方法里的参数列表类型默认为Object,进行比较的时候需要强制类型转化
*/
public class Goods implements MyComparable{
private int price;
public Goods() {
}
public Goods(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public int compareTo(Object o) {
Goods goo = (Goods) o;
return this.price - goo.price;
}
}
package addery.zeus.com.genericitytest;
/**
* 使用泛型不需要再手动进行强制类型转化
*/
public class Goods1 implements MyComparable<Goods1>{
private int price;
public Goods1() {
}
public Goods1(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public int compareTo(Goods1 goo) {
return this.price - goo.price;
}
}
6.4 泛型通配符
package addery.zeus.com.genericitytest;
import java.math.BigDecimal;
import java.util.ArrayList;
public class GenericityTest06 {
public static void print1(ArrayList<?> arrayList) {
// 任意引用类型
}
public static void print2(ArrayList<? extends Number> arrayList) {
// Number及Number的子类
}
public static void print3(ArrayList<? super B> arrayList) {
// B和B的父类
}
public static void main(String[] args) {
print1(new ArrayList<String>());
print1(new ArrayList<Integer>());
print1(new ArrayList<Object>());
print2(new ArrayList<Number>());
print2(new ArrayList<BigDecimal>());
print2(new ArrayList<Double>());
print2(new ArrayList<Integer>());
// 编译器报错
//print2(new ArrayList<Object>());
print3(new ArrayList<B>());
print3(new ArrayList<A>());
print3(new ArrayList<Object>());
// 编译器报错
//print3(new ArrayList<C>());
}
}
class A {
}
class B extends A {
}
class C extends B {
}
7. 迭代时删除元素
package addery.zeus.com.genericitytest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 迭代时删除元素
*/
public class GenericityTest07 {
public static void main(String[] args) {
// 创建集合对象
Collection<String> c = new ArrayList<>();
// 向集合中添加元素
c.add("zhangsan");
c.add("wangwu");
c.add("lisi");
c.add("wangmazi");
// 遍历集合
Iterator<String> it = c.iterator();
while (it.hasNext()) {
String name = it.next();
if ("lisi".equals(name)) {
// 使用Collection的remove()方法
// ConcurrentModificationException异常。
//c.remove(name);
// 使用迭代器的remove()方法
it.remove();
}
System.out.println(name);
}
}
}
8. List接口
8.1 常用方法
package addery.zeus.com.listtest;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* List接口常用方法单元测试
*
* void add(int index, E element) 在指定索引处插入元素
* E set(int index, E element); 修改索引处的元素
* E get(int index); 根据索引获取元素(通过这个方法List集合具有自己特殊的遍历方式:根据下标遍历)
* E remove(int index); 删除索引处的元素
* int indexOf(Object o); 获取对象o在当前集合中第一次出现时的索引。
* int lastIndexOf(Object o); 获取对象o在当前集合中最后一次出现时的索引。
* List<E> subList(int fromIndex, int toIndex); 截取子List集合生成一个新集合(对原集合无影响)。[fromIndex, toIndex)
*
* static List<E> of(E... elements); 静态方法,返回包含任意数量元素的不可修改列表。(获取的集合是只读的,不可修改的。)
*/
public class ListMethodTest {
// void add(int index, E element) 在指定索引处插入元素
@Test
public void testAdd() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
list.add(1, "李四");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println(list); // [zhangsan, 李四, lisi, wangwu, zhaoliu]
}
// E set(int index, E element); 修改索引处的元素
@Test
public void testSet() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
list.set(1, "李四");
System.out.println(list); // [zhangsan, 李四, wangwu, zhaoliu]
}
// E remove(int index); 删除索引处的元素
// E get(int index); 根据索引获取元素(通过这个方法List集合具有自己特殊的遍历方式:根据下标遍历)
@Test
public void testRemoveAndGet() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
for (int i = 0; i < list.size(); i++) {
if ("lisi".equals(list.get(i))) {
list.remove(i);
}
}
System.out.println(list);
}
// int indexOf(Object o); 获取对象o在当前集合中第一次出现时的索引。
// int lastIndexOf(Object o); 获取对象o在当前集合中最后一次出现时的索引。
@Test
public void testIndexOfAndLastIndexOf() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
list.add("zhangsan");
System.out.println(list.indexOf("zhangsan")); // 0
System.out.println(list.lastIndexOf("zhangsan")); // 4
}
// List<E> subList(int fromIndex, int toIndex); 截取子List集合生成一个新集合(对原集合无影响)。
// [fromIndex, toIndex)
@Test
public void testSubList() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
List<String> subList = list.subList(1, 3); // [1, 3)
System.out.println(subList); // [lisi, wangwu]
}
// static List<E> of(E... elements); 静态方法,返回包含任意数量元素的不可修改列表。(获取的集合是只读的,不可修改的。)
@Test
public void testOf() {
List<String> list = List.of("1", "2", "3", "Zues");
System.out.println(list);
// 只能读不能修改
//list.set(1, "Addery"); // UnsupportedOperationException
}
}
8.2 特有迭代器
package addery.zeus.com.listtest;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
// List接口特有迭代器
public class ListTest01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
// 获取List集合特有的迭代器
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("=========");
// 从列表中的指定位置开始,获取List集合特有的迭代器
ListIterator<String> it1 = list.listIterator(1);
while (it1.hasNext()) {
System.out.println(it1.next());
}
}
}
package addery.zeus.com.listtest;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/**
* ListIterator接口常用方法单元测试
*
* boolean hasNext(); 判断光标当前指向的位置是否存在元素。
* E next(); 将当前光标指向的元素返回,然后将光标向下移动一位。
* void remove(); 删除上一次next()方法返回的那个数据(删除的是集合中的)。remove()方法调用的前提是:你先调用next()方法。不然会报错。*
*
* void add(E e); 添加元素(将元素添加到光标指向的位置,然后光标向下移动一位。)
* boolean hasPrevious(); 判断当前光标指向位置的上一个位置是否存在元素。
* E previous(); 获取上一个元素(将光标向上移动一位,然后将光标指向的元素返回)
* int nextIndex(); 获取光标指向的那个位置的下标
* int previousIndex(); 获取光标指向的那个位置的上一个位置的下标
* void set(E e); 修改的是上一次next()方法返回的那个数据(修改的是集合中的)。set()方法调用的前提是:你先调用了next()方法。不然会报错。
*/
public class ListIteratorMethodTest {
// void add(E e); 添加元素(将元素添加到光标指向的位置,然后光标向下移动一位。)
@Test
public void testAdd() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
String next = it.next();
if ("lisi".equals(next)) {
it.add("李四"); // 添加后,光标向下移动一位,指向wangwu
}
System.out.println(next); // zhangsan, lisi, wangwu, zhaoliu 不会输出李四
}
System.out.println(list); // [zhangsan, lisi, 李四, wangwu, zhaoliu]
}
// boolean hasPrevious(); 判断当前光标指向位置的上一个位置是否存在元素。
// E previous(); 获取上一个元素(将光标向上移动一位,然后将光标指向的元素返回)
@Test
public void testHasPreviousAndPrevious() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
ListIterator<String> it = list.listIterator();
System.out.println(it.hasPrevious()); // false
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println(it.hasPrevious()); // true
System.out.println(it.previous()); // zhaoliu
}
// int nextIndex(); 获取光标指向的那个位置的下标
// int previousIndex(); 获取光标指向的那个位置的上一个位置的下标
@Test
public void testNextIndexAndPreviousIndex() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
String next = it.next();
if ("lisi".equals(next)) {
System.out.println(it.nextIndex()); // 2
System.out.println(it.previousIndex()); // 1
}
}
}
// void set(E e); 修改的是上一次next()方法返回的那个数据(修改的是集合中的)。
// set()方法调用的前提是:你先调用了next()方法。不然会报错。
@Test
public void testSet() {
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
ListIterator<String> it = list.listIterator();
//it.set("addery"); // IllegalStateException
while (it.hasNext()) {
String next = it.next();
if ("lisi".equals(next)) {
it.set("李四");
}
}
System.out.println(list); // [zhangsan, 李四, wangwu, zhaoliu]
}
}
8.3 使用Comparator排序
- 数组排序(要排序的类实现Comparable接口)
package addery.zeus.com.listtest.arraysort;
public class User implements Comparable<User>{
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(User o) {
return this.getAge() - o.getAge();
}
}
package addery.zeus.com.listtest.arraysort;
import java.util.Arrays;
public class UserSort {
public static void main(String[] args) {
User user1 = new User("abc", 10);
User user2 = new User("abb", 8);
User user3 = new User("bbc", 16);
User user4 = new User("bcc", 13);
User[] users = {user1, user2, user3, user4};
Arrays.sort(users);
System.out.println(Arrays.toString(users));
}
}
- List集合的排序:Comparator方式
package addery.zeus.com.listtest.listsort;
public class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package addery.zeus.com.listtest.listsort;
import java.util.Comparator;
public class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
package addery.zeus.com.listtest.listsort;
import java.util.ArrayList;
import java.util.List;
public class PersonSort {
public static void main(String[] args) {
Person p1 = new Person("abc", 10);
Person p2 = new Person("abb", 8);
Person p3 = new Person("bbc", 16);
Person p4 = new Person("bcc", 13);
List<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.sort(new PersonComparator());
System.out.println(list);
}
}
- List集合的排序:Comparator方式 + 匿名内部类
package addery.zeus.com.listtest.listsort;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class PersonSort1 {
public static void main(String[] args) {
Person p1 = new Person("abc", 10);
Person p2 = new Person("abb", 8);
Person p3 = new Person("bbc", 16);
Person p4 = new Person("bcc", 13);
List<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.sort(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getName().compareTo(o2.getName());
}
});
System.out.println(list);
}
}
9. ArrayList
-
默认初始化容量**(0)**
-
第一次调用add()方法,底层扩容为长度为10的数组
-
扩容策略
扩容之后的容量是原来容量的1.5倍
10. Vector
-
调用无参构造器,Vector默认初始化长度为10
-
扩容策略,扩大为原来的2倍
11. 链表存储结构
12. LinkedList
-
调用无参构造器,初始化长度为0
-
调用add(“Zeus”)方法默认插入到链表的尾部
-
调用add()方法插入到指定位置
-
修改元素
检查下标是否越界—>找到待修改的结点—>修改—>返回修改前的结点数据
-
删除元素
上述代码中如果删除的是头结点直接first = next;,不需要将next.prev置空吗?
对于头节点的删除操作,确实没有单独的步骤去将新头节点的
prev
置为null
,因为链表的结构维护逻辑已经隐含地处理了这种情况,确保了链接的正确性。 -
获取元素
13. 手写单向链表
13.1 单链表类
package addery.zeus.com.listtest;
/**
* 单向链表
*/
public class MyLinkedList<E> {
/**
* 链表中结点的个数
*/
private int size;
/**
* 链表的头结点
*/
private Node<E> first;
public MyLinkedList() {
}
/**
* 默认的添加方式
* @param data 待添加的数据
*/
public boolean add(E data) {
addLast(data);
return true;
}
/**
* 添加至指定位置
* @param index 待添加的位置
* @param data 待添加的数据
*/
public void add(int index, E data) {
checkPositionIndex(index);
if (index == size)
addLast(data);
else
addAppoint(data, node(index), index);
}
/**
* 删除指定索引处的结点,并返回原结点的数据
* @param index 待删除的索引
* @return 待删除索引的数据
*/
public E remove(int index) {
checkPositionIndex(index);
Node<E> oldNode = node(index);
E oldNodeData = oldNode.item;
if (index == 0) { // 如果删除的是头结点
first = oldNode.next;
}else { // 非头结点
Node<E> oldNodePrev = node(index - 1);
oldNodePrev.next = oldNode.next;
}
oldNode.next = null;
oldNode.item = null;
size--;
return oldNodeData;
}
/**
* 修改指定索引处结点的数据,并返回原始数据
* @param index 待修改的结点索引
* @param data 新的结点数据
* @return 待修改结点的原始数据
*/
public E set(int index, E data) {
checkPositionIndex(index);
Node<E> oldNode = node(index);
E oldData = oldNode.item;
oldNode.item = data;
return oldData;
}
/**
* 获取指定结点处的元素数据
* @param index 待查找的索引
* @return 待查找索引的数据
*/
public E get(int index) {
checkPositionIndex(index);
return node(index).item;
}
/**
* 默认添加至末尾
*/
public void addLast(E data) {
Node<E> newNode = new Node<>(data, null);
if (first == null)
first = newNode;
else
node(size - 1).next = newNode;
size++;
}
/**
* 添加结点至指定位置
* @param data 待添加的结点数据
* @param in 目标位置的结点对象
* @param index 目标位置索引
*/
void addAppoint(E data, Node<E> in, int index) {
Node<E> newNode = new Node<>(data, in);
if (index == 0) { // 如果在头结点处添加结点
first = newNode;
} else { // 非头结点处
Node<E> inPrevNode = node(index - 1);
inPrevNode.next = newNode;
}
size++;
}
/**
* 查找结点,返回结点对象
* @param index 待查找到结点索引
* @return 目标节点对象
*/
Node<E> node(int index) {
Node<E> x = first;
for(int i = 0; i < index; i++) {
x = x.next;
}
return x;
}
/**
* 检查下标
* @param index 下标
*/
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 下标是否在合理范围内
* @param index 下标
* @return 合理true,不合理false
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
/**
* 构造IndexOutOfBoundsException的提示信息
* @param index 下标
* @return 提示信息:String
*/
private String outOfBoundsMsg(int index) {
return "Index:" + index + ", Size:" + size;
}
/**
* 获取链表中结点的个数
* @return 结点个数
*/
public int getSize() {
return size;
}
/**
* 内部类:单链表的结点
*/
private static class Node<E> {
/**
* 结点数据
*/
E item;
/**
* 下一个结点
*/
Node<E> next;
Node(E item, Node<E> next) {
this.item = item;
this.next = next;
}
}
}
13.2 Junit单元测试
package addery.zeus.com.listtest;
import org.junit.jupiter.api.Test;
/**
* MyLinkedList自定义单链表方法单元测试
*/
public class MyLinkedListMethodTest {
// add()
@Test
public void testAdd() {
MyLinkedList<String> mll = new MyLinkedList<>();
mll.add("Zeus");
mll.add("Stone");
mll.add("Apple");
mll.add("pear");
mll.add("peach");
mll.add(2, "Addery");
//mll.add(10, "Addery"); // java.lang.IndexOutOfBoundsException: Index:10, Size:6
for (int i = 0; i < mll.getSize(); i++) {
System.out.println(mll.get(i));
}
}
// test()
@Test
public void testSet() {
MyLinkedList<String> mll = new MyLinkedList<>();
mll.add("Zeus");
mll.add("Stone");
mll.add("Apple");
mll.add("pear");
mll.add("peach");
String oldData = mll.set(2, "Addery");
System.out.println(oldData); // Apple
for (int i = 0; i < mll.getSize(); i++) {
System.out.println(mll.get(i));
}
}
// remove()
@Test
public void testRemove() {
MyLinkedList<String> mll = new MyLinkedList<>();
mll.add("Zeus");
mll.add("Stone");
mll.add("Apple");
mll.add("pear");
mll.add("peach");
String oldData = mll.remove(1);
System.out.println(oldData);
mll.remove(0);
mll.add("z");
for (int i = 0; i < mll.getSize(); i++) {
System.out.println(mll.get(i));
}
}
// get()
@Test
public void testGet() {
MyLinkedList<String> mll = new MyLinkedList<>();
mll.add("Zeus");
mll.add("Stone");
mll.add("Apple");
mll.add("pear");
mll.add("peach");
System.out.println(mll.get(2));
System.out.println("======");
for (int i = 0; i < mll.getSize(); i++) {
System.out.println(mll.get(i));
}
}
}