表、栈、队列与迭代器

344 阅读1分钟

与栈、队列不同,表支持直接访问任何位置的元素。

/**
 * 表的简单实现
 */
public class List<T> {
    private T[] arr = (T[]) new Object[10]; // 用于存储元素。由于不支持泛型数组,需要显式将Object[]转换为T[]类型。
    private int numOfElement = 0; // 用于记录已经存储的元素个数


    /**
     * 添加一个元素到表尾
     */
    public void add(T element) {
        add(numOfElement, element);
    }

    /**
     * 插入元素到指定位置
     */
    public void add(int index, T element) {
        if (numOfElement == arr.length) {
            resize(arr.length / 2);
        }
        for (int i = arr.length - 1; i >= index; i--) {
            arr[i] = arr[i - 1];
        }
        arr[index] = element;
        numOfElement++;
    }

    /**
     * 移除并返回指定位置的元素
     */
    public T remove(int index) {
        T element = arr[index];
        arr[index] = null;
        for (int i = index + 1; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        numOfElement--;
        if (numOfElement < arr.length / 4) {
            resize(arr.length / 2);
        }
        return element;
    }

    /**
     * 调整用于存储的数组的大小,避免浪费空间
     */
    private void resize(int newSize) {
        T[] newArr = (T[]) new Object[newSize];
        for (int i = 0; i < numOfElement; i++) {
            newArr[i] = arr[i];
        }
        arr = newArr;
    }
}

队列

队列是基于先进先出(FIFO)的数据结构,类似于现实生活中的排队,常用于计算机任务处理。队列应该只提供出队和入队操作,而不是对任意元素的操作。

import java.util.ArrayList;

/**
 * 队列的简单实现
 */
public class MyQueue<T> {
    private int numOfElements = 0;
    private T[] arr = (T[]) new Object[10];

    /**
     * 将元素加入到队尾
     */
    public void push(T newElement) {
        if (arr.length == numOfElements) {
            resize(arr.length * 2);
        }
        arr[numOfElements++] = newElement;
    }

    /**
     * 队首元素出列
     */
    public T pop() {
        T oldElement = arr[0];
        for (int i = 0; i < numOfElements; i++) {
            arr[i] = arr[i + 1];
        }
        arr[--numOfElements] = null;
        if (numOfElements < arr.length / 4) {
            resize(arr.length / 2);
        }
        return oldElement;
    }

    /**
     * 调整数组大小
     */
    private void resize(int newSize) {
        T[] newArr = (T[]) new Object[newSize];
        for (int i = 0; i < numOfElements; i++) {
            newArr[i] = arr[i];
        }
        arr = newArr;
    }
}
/**
 * 队列的链表实现
 */
public class MyLinkedQueue<T> {
    private Node first = null;
    private int numOfNodes = 0;

    private class Node {
        T element = null;
        Node next = null;
    }

    /**
     * 添加元素到表尾
     */
    public void push(T newElement) {
        Node newNode = new Node();
        newNode.element = newElement;

        if (numOfNodes == 0) {
            first = newNode;
        } else {
            Node currentNode = first;
            while (currentNode.next != null) {
                currentNode = currentNode.next;
            }
            currentNode.next = newNode;
        }

        numOfNodes++;
    }

    /**
     * 表首元素出列
     */
    public T pop() {
        T oldElement = first.element;
        first = first.next;
        numOfNodes--;
        return oldElement;
    }
}

栈与队列的实现方式类似,区别在于元素的出栈和入栈都在栈顶进行。

迭代器

实现了Iterable接口的数据结构可以使用forEach来迭代:

public static void main(String[] args) {
    ArrayList<Integer> arrayList = new ArrayList<>();
    arrayList.add(123);
    arrayList.add(456);

    arrayList.forEach(System.out::println); // 使用forEach方法
    
    for (Integer integer : arrayList) { // 使用forEach循环
        System.out.println(integer);
    }
}

实现了Iterable接口的类必须在类声明后添加implements Iterable<T>,并实现iterator方法,返回一个对应的迭代器。

@Override
public Iterator<T> iterator() {
    return new Iterator<T>() {
        int currentIndex = 0;

        @Override
        public boolean hasNext() {
            return currentIndex != numOfElements;
        }

        @Override
        public T next() {
            return arr[currentIndex++];
        }
    };
}

迭代器的hasNext()方法用于判断是否还可以调用next()方法。next()方法用于获取下一个值。