LinkedList 的常用方法及与Stack和Queen的关联 -- 《JAVA编程思想》34

本文详细介绍了LinkedList在实现栈、队列和优先级队列中的应用,包括getFirst()、removeFirst()等方法的演示,以及自定义Stack和使用Java内置工具类的对比。通过实例展示了如何利用LinkedList进行数据结构操作。

LinkedList 和 ArrayList 一样包含了 List 的基本接口(关于 List 接口的基本方法介绍,可以参考:List 集合中的常用API ),还添加了可以使其用做栈、队列、双端队列的方法。

我们先来看看 LinkedList 中的常见方法(Fruits.arrayList() 是自己编写的一个用于生成指定长度不同类型 Fruit 集合的方法):

1.获取第一个元素

getFirst()、element()、peek() 都可以获取容器中第一个元素。当 List 为空时,getFirst()、element() 会抛出 NoSuchElementException,而 peek() 则会抛出 null。

2.移除第一个元素

removeFirst() 、remove()、poll() 都可以移除第一个元素并返回。当 List 为空时,removeFirst()、remove() 会抛出 NoSuchElementException,而 poll() 则会抛出 null。

3.移除最后一个元素

removeLast() 可以移除最后一个元素并返回。

4.添加元素至头部

addFirst()可以将元素添加至容器头部。

5.添加元素至尾部

add()、addLast() 可以元素添加至容器尾部。

public class LinkedListFeatures {

    public static void main(String[] args) {
        LinkedList<Fruits.Fruit> fruitList = new LinkedList<>(Fruits.arrayList(8));
        System.out.println(fruitList);
        System.out.println("getFirst()==" + fruitList.getFirst());
        System.out.println("element()==" + fruitList.element());
        System.out.println("peek()==" + fruitList.peek());
        System.out.println("remove()==" + fruitList.remove());
        System.out.println("removeFirst()==" + fruitList.removeFirst());
        System.out.println("poll()==" + fruitList.poll());
        System.out.println("removeFirst()==" + fruitList.removeFirst());
        System.out.println("removeLast()==" + fruitList.removeLast());
        System.out.println(fruitList);
        fruitList.addFirst(fruitList.get(1));
        System.out.println("addFirst()==" + fruitList);
        fruitList.offer(fruitList.get(1));
        System.out.println("offer()==" + fruitList);
        fruitList.add(fruitList.get(1));
        System.out.println("add()==" + fruitList);

    }

}
[Fruit{id=1, name='apple'}, Fruit{id=2, name='orange'}, Fruit{id=3, name='banana'}, Fruit{id=4, name='lemon'}, Fruit{id=5, name='watermelon'}, Fruit{id=6, name='cheery'}, Fruit{id=7, name='pear'}, Fruit{id=8, name='peach'}]
getFirst()==Fruit{id=1, name='apple'}
element()==Fruit{id=1, name='apple'}
peek()==Fruit{id=1, name='apple'}
remove()==Fruit{id=1, name='apple'}
removeFirst()==Fruit{id=2, name='orange'}
poll()==Fruit{id=3, name='banana'}
removeFirst()==Fruit{id=4, name='lemon'}
removeLast()==Fruit{id=8, name='peach'}
[Fruit{id=5, name='watermelon'}, Fruit{id=6, name='cheery'}, Fruit{id=7, name='pear'}]
addFirst()==[Fruit{id=6, name='cheery'}, Fruit{id=5, name='watermelon'}, Fruit{id=6, name='cheery'}, Fruit{id=7, name='pear'}]
offer()==[Fruit{id=6, name='cheery'}, Fruit{id=5, name='watermelon'}, Fruit{id=6, name='cheery'}, Fruit{id=7, name='pear'}, Fruit{id=5, name='watermelon'}]
add()==[Fruit{id=6, name='cheery'}, Fruit{id=5, name='watermelon'}, Fruit{id=6, name='cheery'}, Fruit{id=7, name='pear'}, Fruit{id=5, name='watermelon'}, Fruit{id=5, name='watermelon'}]

下面我们来看看 – Stack ,栈通常指“后进先出”的容器,也被成为“叠加栈”,最后压入栈的元素总是第一个弹出栈。可以把栈想象成自助餐的托盘,最后放上去的食物总是要最先拿出来食用。

LinkedList 包含 Stack 的所有方法,我们可以尝试自己实现一个简单的 Stack 类。

经测试自己实现的 SimpleStack 类 和 java.util.Stack (jdk自带的工具类)可以使一些基本操作达到相同的效果。

push() 往头部添加元素,peek() 获取头部元素,pop() 将头部元素移除,empty() 判断容器是否为空。

public class SimpleStack<T> {
    private LinkedList<T> storage = new LinkedList<>();

    public void push(T v) {
        storage.addFirst(v);
    }

    public T peek() {
        return storage.getFirst();
    }

    public T pop() {
        return storage.removeFirst();
    }

    public boolean empty() {
        return storage.isEmpty();
    }

    public String toString() {
        return storage.toString();
    }
    
}

import java.util.Stack;
import mtn.baymax.simpleStack;

public class StackCollision {

    public static void main(String[] args) {

        SimpleStack<String> simpleStack = new SimpleStack<>();
        for (String s : "My dog has fleas".split(" ")) {
            simpleStack.push(s);
        }
        while (!simpleStack.empty()){
            System.out.print(simpleStack.pop()+" ");
        }
        System.out.println();

        Stack<String> stringStack = new Stack<>();
        for (String s : "My dog has fleas".split(" ")) {
            stringStack.push(s);
        }
        while (!stringStack.empty()){
            System.out.print(stringStack.pop()+" ");
        }
    }
    
}

fleas has dog My 
fleas has dog My 

然后我们再来看看队列 – Queen ,队列是一个先进先出的容器。即从容器的一端放入事物,从另一端取出,并且事物放入容器的顺序与取出的顺序相同。

队列常被当做一种将对象从程序的某个区域传输另一个区域的可靠途径,在并发编程中应用广泛。

LinkedList 提供了支持队列行为的方法,并且实现了 Queue 接口,因此 LinkedList 可以向上转型为 Queue (Queue 窄化了对 LinkedList 方法的访问权限,只有恰当的方法才能访问)。

offer() 添加元素至队列尾部;peek() 返回第一个元素,无则返回 null;remove() 移除并返回最后一个元素。

public class QueueDemo {


    public static void printQ(Queue queue) {
        while (queue.peek() != null) {
            System.out.print(queue.remove() + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<Integer>();
        Random random = new Random(47);
        for (int i = 0; i < 10; i++) {
            queue.offer(random.nextInt(i + 10));
        }
        printQ(queue);
        
        Queue<Character> qc = new LinkedList<>();
        for (char c : "Brontosaurus".toCharArray()) {
            qc.offer(c);
        }
        printQ(qc);
    }

}
0 3 5 4 5 11 8 2 4 14 
B r o n t o s a u r u s 

先进先出是最典型的队列规则,下一个元素总是等待时间最长的元素。

假设在机场,飞机临近起飞,这架航班的乘客需要优先登记,此时普通的队列就无法满足我们的需求了,有些消息必须优先得到处理,PriorityQueue 可以帮助解决这个问题。

在 PriorityQueue 调用 offer() 方法插入元素时,元素在队列中会根据自然顺序进行排序(下述例子中的字符 char 会自动转换成对应的 ASCII 码,空格字符会排在字母前面),但可以提供自己的 Comparator 改变排序规则。

public class PriorityQueueDemo {

    public static void main(String[] args) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
        Random random = new Random(47);
        for (int i = 0; i < 10; i++) {
            priorityQueue.offer(random.nextInt(i + 10));
        }
        QueueDemo.printQ(priorityQueue);

        List<Integer> integers = Arrays.asList(25, 22, 20, 18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25);
        priorityQueue = new PriorityQueue<>(integers);
        QueueDemo.printQ(priorityQueue);

        priorityQueue = new PriorityQueue<>(integers.size(), Collections.reverseOrder());
        priorityQueue.addAll(integers);
        QueueDemo.printQ(priorityQueue);

        String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION";
        List<String> strings = Arrays.asList(fact.split(""));
        PriorityQueue<String> stringPQ = new PriorityQueue<>(strings);
        QueueDemo.printQ(stringPQ);
        
        stringPQ = new PriorityQueue<>(strings.size(), Collections.reverseOrder());
        stringPQ.addAll(strings);
        QueueDemo.printQ(stringPQ);

        HashSet<Character> charSet = new HashSet<>();
        for (char c : fact.toCharArray()) {
            charSet.add(c);
        }
        PriorityQueue<Character> characterPQ = new PriorityQueue<Character>(charSet);
        QueueDemo.printQ(characterPQ);
        
        characterPQ=new PriorityQueue<>(charSet.size(),Collections.reverseOrder());
        characterPQ.addAll(charSet);
        QueueDemo.printQ(characterPQ);
    }

}

0 1 1 1 1 1 3 5 8 14 
1 1 2 3 3 9 9 14 14 18 18 20 21 22 23 25 25 
25 25 23 22 21 20 18 18 14 14 9 9 3 3 2 1 1 
      A A B C C C D D E E E F H H I I L N N O O O O S S S T T U U U W 
W U U U T T S S S O O O O N N L I I H H F E E E D D C C C B A A       
  A B C D E F H I L N O S T U W 
W U T S O N L I H F E D C B A 

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BaymaxCS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值