首页 > 编程语言 >Java算法 数据结构 栈 队列 优先队列 比较器

Java算法 数据结构 栈 队列 优先队列 比较器

时间:2025-01-13 19:30:41浏览次数:3  
标签:排序 Java Comparator 队列 System println 数据结构 out

目录

栈 Stack

性质

构造

方法

代码示例

队列 Queue

性质

构造

方法

代码示例

优先队列 PriorityQueue

性质

构造

方法

代码示例

比较器

1. Comparator 接口的方法

2. 常见的内置比较器

1. 自然排序比较器(naturalOrder())

2. 逆序排序比较器(reverseOrder())

3. nullsFirst() 和 nullsLast()

3. 示例:常用的比较器

自定义类使用 Comparator 排序

输出:

4. 多重排序

5. 使用 Comparator 的常见场景

1. PriorityQueue

2. Collections.sort()

3. Arrays.sort()

6. 自定义比较器的实现方式

1. 使用匿名类实现 Comparator:

2. 使用 Lambda 表达式实现 Comparator(推荐):

3. 使用方法引用实现 Comparator:

7. 总结


栈 Stack

性质

后进先出

可以弹出栈顶元素 或者返回栈顶元素(不删除)

后压入栈的元素先出来

构造

  • 创建栈对象

Stack<Integer> stack = new Stack<>(); 创建了一个类型为 Integer 的栈。

方法

  • push():将元素压入栈中。
  • peek():查看栈顶元素,但不移除它。
  • pop():移除并返回栈顶元素。
  • size():获取栈中元素的数量。
  • isEmpty():判断栈是否为空。

代码示例

import java.util.Stack;

public class StackExample {
    public static void main(String[] args) {
        // 创建一个栈对象
        Stack<Integer> stack = new Stack<>();

        // 入栈
        stack.push(10);
        stack.push(20);
        stack.push(30);

        // 查看栈顶元素
        System.out.println("栈顶元素: " + stack.peek());

        // 出栈
        System.out.println("出栈元素: " + stack.pop());
        System.out.println("栈顶元素: " + stack.peek());

        // 查看栈的大小
        System.out.println("栈的大小: " + stack.size());

        // 判断栈是否为空
        if (stack.isEmpty()) {
            System.out.println("栈为空");
        } else {
            System.out.println("栈不为空");
        }
    }
}

队列 Queue

先进先出

可以移除队列头部元素 并且获取这个元素

也可以获取队列头部元素(不删除)

先进入队列的元素先出来

性质

构造

Queue<Integer> queue = newLinkedList<>();

创建了一个类型为 Integer 的队列。

方法

  • offer(E e):将元素 e 加入队列,若队列没有满(在 LinkedList 实现中,offer() 通常会成功)。
  • peek():返回队列头部元素,但不删除它。若队列为空,返回 null
  • poll():移除并返回队列头部的元素。如果队列为空,返回 null
  • size():获取队列中的元素个数。
  • isEmpty():判断队列是否为空。

代码示例

import java.util.Queue;
import java.util.LinkedList;

public class QueueExample {
    public static void main(String[] args) {
        // 创建一个队列对象
        Queue<Integer> queue = new LinkedList<>();

        // 入队
        queue.offer(10);
        queue.offer(20);
        queue.offer(30);

        // 查看队列头部元素
        System.out.println("队列头部元素: " + queue.peek());

        // 出队
        System.out.println("出队元素: " + queue.poll());
        System.out.println("队列头部元素: " + queue.peek());

        // 查看队列的大小
        System.out.println("队列的大小: " + queue.size());

        // 判断队列是否为空
        if (queue.isEmpty()) {
            System.out.println("队列为空");
        } else {
            System.out.println("队列不为空");
        }
    }
}

优先队列 PriorityQueue

性质

PriorityQueue 是一个优先级队列,它会按照元素的自然顺序或指定的比较器排序。在 PriorityQueue 中,出队的顺序是根据元素的优先级(大小或比较器的排序规则)来决定的。

构造

PriorityQueue<Integer> priorityQueue = newPriorityQueue<>();

方法

  • add(E e):将元素 e 插入到队列中。如果队列已满(取决于实现的容量限制),则抛出异常。
  • offer(E e):将元素 e 插入队列。如果队列容量已满,则返回 false,不会抛出异常。这个方法通常更安全,推荐使用。
  • poll():移除并返回队列头部的元素(优先级最高的元素)。如果队列为空,返回 null
  • peek():返回队列头部的元素(优先级最高的元素),但不移除它。如果队列为空,返回 null
  • remove():移除队列中的一个元素。通常情况下,poll() 是更常用的出队操作。
  • size():返回队列中元素的个数。
  • isEmpty():检查队列是否为空。
  • clear():清空队列中的所有元素。

代码示例

import java.util.PriorityQueue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        // 创建一个优先级队列对象
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();

        // 入队
        priorityQueue.offer(30);
        priorityQueue.offer(10);
        priorityQueue.offer(20);

        // 查看队列头部元素
        System.out.println("队列头部元素: " + priorityQueue.peek());

        // 出队
        System.out.println("出队元素: " + priorityQueue.poll());
        System.out.println("队列头部元素: " + priorityQueue.peek());

        // 查看队列的大小
        System.out.println("队列的大小: " + priorityQueue.size());
    }
}

比较器

1. Comparator 接口的方法

Comparator 接口包含以下几个方法:

  • compare(T o1, T o2):比较 o1o2,如果返回值为负数,则 o1 排在 o2 之前;如果返回值为零,则 o1o2 相等;如果返回值为正数,则 o1 排在 o2 之后。
  • reversed():返回一个与当前比较器顺序相反的比较器。
  • thenComparing(Comparator<? super T> other):如果 compare() 方法返回 0,则继续使用另一个比较器 other 进行比较。
  • naturalOrder():返回一个自然排序的比较器(升序)。
  • reverseOrder():返回一个逆序排序的比较器(降序)。
  • nullsFirst() / nullsLast():处理 null 值的排序,nullsFirst() 会将 null 值排在前面,nullsLast() 会将 null 值排在后面。

2. 常见的内置比较器

1. 自然排序比较器(naturalOrder()

Comparator.naturalOrder() 返回一个自然排序的比较器,通常是升序排序。适用于实现了 Comparable 接口的对象。

java


复制代码
Comparator<Integer> naturalOrder = Comparator.naturalOrder();
2. 逆序排序比较器(reverseOrder()

Comparator.reverseOrder() 返回一个降序排序的比较器。

java


复制代码
Comparator<Integer> reverseOrder = Comparator.reverseOrder();
3. nullsFirst()nullsLast()

这两个方法用来处理 null 值的排序:

  • nullsFirst():将 null 值排在前面。
  • nullsLast():将 null 值排在后面。
java


复制代码
Comparator<String> nullsFirst = Comparator.nullsFirst(Comparator.naturalOrder());
Comparator<String> nullsLast = Comparator.nullsLast(Comparator.naturalOrder());

3. 示例:常用的比较器

自定义类使用 Comparator 排序

假设我们有一个 Person 类,包含 nameage 字段,我们可以根据不同的字段排序。

java


复制代码
import java.util.*;

class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + ": " + age;
    }
}

public class ComparatorExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        );

        // 按年龄升序排序
        Comparator<Person> byAge = Comparator.comparingInt(p -> p.age);
        Collections.sort(people, byAge);
        System.out.println("按年龄升序排序:" + people);

        // 按名字升序排序
        Comparator<Person> byName = Comparator.comparing(p -> p.name);
        Collections.sort(people, byName);
        System.out.println("按名字升序排序:" + people);

        // 按年龄降序排序
        Comparator<Person> byAgeDesc = Comparator.comparingInt(Person::getAge).reversed();
        Collections.sort(people, byAgeDesc);
        System.out.println("按年龄降序排序:" + people);
    }
}
输出:
yaml


复制代码
按年龄升序排序:[Bob: 25, Alice: 30, Charlie: 35]
按名字升序排序:[Alice: 30, Bob: 25, Charlie: 35]
按年龄降序排序:[Charlie: 35, Alice: 30, Bob: 25]

4. 多重排序

如果我们希望对多个属性进行排序,可以使用 thenComparing() 方法。例如,按 age 排序,如果年龄相同,则按 name 排序:

java


复制代码
Comparator<Person> byAgeThenName = Comparator.comparingInt(Person::getAge)
                                               .thenComparing(Person::getName);

Collections.sort(people, byAgeThenName);

5. 使用 Comparator 的常见场景

1. PriorityQueue

在使用 PriorityQueue 时,你可以通过传递自定义的 Comparator 来指定队列中的优先级顺序。例如,按降序排列整数:

java


复制代码
PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
pq.offer(10);
pq.offer(20);
pq.offer(30);

while (!pq.isEmpty()) {
    System.out.println(pq.poll());  // 输出:30, 20, 10
}
2. Collections.sort()

你可以在排序时传递自定义的比较器。例如,按字符串的长度排序:

java


复制代码
List<String> strings = Arrays.asList("apple", "banana", "pear", "grape");

Collections.sort(strings, Comparator.comparingInt(String::length));

System.out.println(strings);  // 输出:[pear, apple, grape, banana]
3. Arrays.sort()

Arrays.sort() 也可以接受一个比较器。例如,按数字的降序排列:

java


复制代码
Integer[] numbers = {3, 1, 4, 1, 5, 9};
Arrays.sort(numbers, Comparator.reverseOrder());
System.out.println(Arrays.toString(numbers));  // 输出:[9, 5, 4, 3, 1, 1]

6. 自定义比较器的实现方式

1. 使用匿名类实现 Comparator
java


复制代码
Comparator<Person> byName = new Comparator<Person>() {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.name.compareTo(p2.name);
    }
};
2. 使用 Lambda 表达式实现 Comparator(推荐):
java


复制代码
Comparator<Person> byName = (p1, p2) -> p1.name.compareTo(p2.name);
3. 使用方法引用实现 Comparator
java


复制代码
Comparator<Person> byName = Comparator.comparing(Person::getName);

7. 总结

Java 提供了多种方式来实现比较器 Comparator,你可以:

  • 使用内置的 Comparator 方法(如 naturalOrder()reverseOrder()nullsFirst() 等)。
  • 定制比较器,使用 Comparator.comparing()thenComparing() 等进行多重排序。
  • 使用自定义 Comparator 对象来排序集合,如 PriorityQueueCollections.sort()Arrays.sort() 等。

通过灵活地使用这些比较器,你可以对各种类型的对象进行多样化的排序。

4o

标签:排序,Java,Comparator,队列,System,println,数据结构,out
From: https://blog.csdn.net/qq_30500575/article/details/145121968

相关文章

  • java项目之教师工作量管理系统(ssm+mybatis+mysql)
    风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的码农一枚。今天要和大家聊的是一款基于ssm的教师工作量管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息。项目简介:教师工作量管理系统的主要使用者管理员可以管理教师,可以对教师信息修改删除以及查询操作;可以查......
  • 进程、线程,java如何实现多线程任务,Thread里面常用的方法
    1.线程和进程的概述1.1什么是进程正在执行的程序,称为进程。进程是系统分配资源的单元。1.2什么是线程线程又称轻量级的进程,是CPU调度的基本单位,一个进程由一个或多个线程组成进程与进程之间无法共享数据同一个进程的线程与线程之间可以共享数据2.并发与并行的概述并......
  • java企业人事档案管理系统论文+源码 2025毕设
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景在当今企业快速发展的环境下,企业规模不断扩大,员工数量日益增多,人事管理工作变得愈发复杂。传统的人事档案管理方式主要依赖手工操作和纸质档案,这......
  • java面试刷题系统设计论文+源码 2025毕设
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着就业市场竞争的日益激烈,面试在求职过程中的重要性愈发凸显。如今,计算机技术的广泛应用为面试准备提供了新的途径。在传统的面试准备过程中,求......
  • 方法引用与lambda底层原理&Java方法引用、lambda能被序列化么?
    0.引入最近笔者使用flink实现一些实时数据清洗(从kafka清洗数据写入到clickhouse)的功能,在编写flink作业后进行上传,发现运行的时候抛出:java.io.NotSerializableException,错误消息可能类似于“org.apache.flink.streaming.api.functions.MapFunctionimplementationisnotser......
  • 基于java的停车场车牌识别系统
    一、系统背景与意义随着城市化进程的加速,停车场管理面临着越来越大的挑战。传统的手工记录车牌号方式不仅费时费力,还容易出错。而基于Java的停车场车牌识别系统的出现,则有效地解决了这一问题。该系统能够自动识别进出停车场的车辆车牌号,实现快速、准确的车辆管理,提高了停车......
  • 基于Java的外卖骑手管理系统
    一、系统背景与意义随着外卖行业的蓬勃发展,外卖配送成为了一个关键环节。传统的骑手管理方式存在调度不合理、信息更新不及时等问题,影响了配送效率和用户满意度。因此,开发一个基于Java的外卖骑手管理系统具有重要意义,它可以实现骑手的自动化管理,优化配送流程,提高配送效率,同......
  • JavaScript与服务器端框架Flask
    JavaScript与服务器端框架Flask基本概念和作用说明示例一:设置基本的Flask环境示例二:使用JavaScript发起请求功能使用思路及代码示例示例三:处理POST请求示例四:表单验证与反馈开发经验分享在现代Web开发中,前端和后端的紧密结合对于创建高效、响应迅速的应用程序至关......
  • 【最新原创毕设】基于SSM的在线学习平台+09650(免费领源码)可做计算机毕业设计JAVA、PHP
    目 录摘要1绪论1.1选题背景及意义1.2国内外现状分析1.3论文结构与章节安排2 在线学习平台系统分析2.1可行性分析2.2系统业务流程分析2.3系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4系统用例分析2.5本章小结3在线学习平台总体设......
  • leetcode周赛432 T4(单调栈 + 单调队列)
    一道练习单调栈+单调队列的好题题目链接:problem对于求合法子数组数量的题目,可以先考虑传统的枚举右端点,二分左端点的套路。此题用这种方法恰好可行,因为对于一个序列,左端增加一个数不会让操作数更少。因此对于固定右端点,合法的左端点一定是一段区间。所以现在问题转化为:用双指......