JavaSE学习笔记-chapter07-集合

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


  1. 默认初始化容量**(0)**

  2. 第一次调用add()方法,底层扩容为长度为10的数组

  3. 扩容策略

    扩容之后的容量是原来容量的1.5倍

10. Vector

  1. 调用无参构造器,Vector默认初始化长度为10

  2. 扩容策略,扩大为原来的2倍

11. 链表存储结构

12. LinkedList

  1. 调用无参构造器,初始化长度为0

  2. 调用add(“Zeus”)方法默认插入到链表的尾部

  3. 调用add()方法插入到指定位置

  4. 修改元素

    检查下标是否越界—>找到待修改的结点—>修改—>返回修改前的结点数据

  5. 删除元素

    上述代码中如果删除的是头结点直接first = next;,不需要将next.prev置空吗?

    对于头节点的删除操作,确实没有单独的步骤去将新头节点的prev置为null,因为链表的结构维护逻辑已经隐含地处理了这种情况,确保了链接的正确性。

  6. 获取元素

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));
        }
    }
}
  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象编程是一种编程范式,它将程序的构建和设计思路以面向对象的方式进行组织和实现。在Java中,面向对象编程是基于Java SE(Standard Edition)的一种编程方式。第07讲主要介绍了面向对象编程中的一些基本概念和关键术语。 在面向对象编程中,我们将程序中的数据和对数据的操作(方法)封装在一起,形成一个对象。对象由两部分构成:属性和方法。属性是用来描述对象的特征,而方法则是对象可以执行的操作。对象之间通过消息(方法调用)进行通信和交互。面向对象的核心思想是通过封装、继承和多态实现程序的复用和扩展。 封装是面向对象编程中的一个重要概念,它指的是将类的属性和方法进行封装,使得外部无法直接访问和修改对象的内部状态,只能通过公共的方法来操作属性和执行方法。封装提供了一种将数据和行为组合在一起的方式,可以保护数据的完整性和安全性。 继承是面向对象编程中的另一个重要概念,它指的是通过定义一个新的类来继承现有类的属性和方法。通过继承,子类可以继承父类的属性和方法,并可以在此基础上进行扩展和修改。继承提供了一种代码复用的机制,可以减少重复编码的工作量。 多态是面向对象编程的又一个重要概念,它指的是同一类型的对象在不同的情况下可以有不同的表现形式。多态通过方法的重写和方法的重载实现。方法的重写指的是在子类中重新定义和实现父类的方法,方法的重载指的是在同一个类中可以定义多个同名但参数列表不同的方法。 总结来说,面向对象编程是一种将程序组织和设计思路以对象为中心的编程方式。在JavaSE中,我们可以通过封装、继承和多态来实现面向对象编程的目标。封装可以提高程序的可维护性和可复用性,继承可以减少重复编码的工作量,多态可以灵活地操作对象。掌握这些基本概念和关键术语,可以帮助我们更好地理解和应用面向对象编程的思想。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值