刷算法题必备:Java常用工具类详解

后端 潘老师 1个月前 (03-24) 38 ℃ (0) 扫码查看

在算法题的“战场”上,Java的各类工具类堪称解题的得力“武器”。很多刷题平台缺少智能补全和提示功能,记住这些工具类及其用法就显得尤为重要。下面就来详细介绍在刷算法题时常用的Java工具类。

一、队列(Queue)相关工具类

(一)普通队列(Queue)

Queue是Java中很常用的接口,ArrayDeque是实现Deque接口的一个类,它既可以当作普通队列(遵循先进先出,即FIFO原则)使用,也能当成双端队列(既可以在队首操作,也能在队尾操作)。

// 创建一个队列,泛型指定为Integer类型
Queue<Integer> queue = new ArrayDeque<>();
// 常用方法如下:
// 1. 元素入队
// add方法用于添加元素到队列尾部,如果队列已满,会抛出`IllegalStateException`异常
queue.add(10); 
// offer方法同样是添加元素到队列尾部,不过队列已满时,它不会抛出异常,而是返回`false`
queue.offer(20); 

// 2. 元素出队
// remove方法移除并返回队列头部的元素,如果队列为空,会抛出`NoSuchElementException`异常
int firstElement = queue.remove(); 
// poll方法也是移除并返回队列头部的元素,但队列为空时,它返回null
Integer firstElementOrNull = queue.poll(); 

// 3. 查看队头元素
// element方法返回队列头部的元素,但不会移除它,如果队列为空,会抛出`NoSuchElementException`异常
int headElement = queue.element(); 
// peek方法返回队列头部的元素,队列为空时返回null
Integer headElementOrNull = queue.peek(); 

// 4. 其他常用方法
// size方法返回队列中的元素数量
int size = queue.size(); 
// isEmpty方法用于检查队列是否为空
boolean isEmpty = queue.isEmpty(); 
// clear方法用于清空队列
queue.clear(); 

// 5. 双端队列操作
// 虽然`ArrayDeque`可以当作普通队列,但它还支持双端队列的操作
// addFirst方法将元素添加到队列头部
queue.addFirst(5); 
// addLast方法将元素添加到队列尾部
queue.addLast(15); 
// removeFirst方法移除并返回队列头部的元素
int first = queue.removeFirst(); 
// removeLast方法移除并返回队列尾部的元素
int last = queue.removeLast(); 
// getFirst方法返回队列头部的元素
int head = queue.getFirst(); 
// getLast方法返回队列尾部的元素
int tail = queue.getLast(); 

(二)优先队列(PriorityQueue)

PriorityQueue是基于优先级堆实现的队列,元素按照优先级顺序出队,默认是最小堆,即最小的元素优先出队。下面是它的使用示例:

// 匿名实现比较器,用于指定元素的排序规则
public static Comparator<Customer> idComparator = new Comparator<Customer>() {
    @Override
    public int compare(Customer c1, Customer c2) {
        // 这里按ID升序排列
        return c1.getId() - c2.getId(); 
    }
};

// 创建优先队列,指定初始容量为7,并使用上面定义的比较器
Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator);

/*
更简洁的写法: 使用Lambda表达式实现比较器
Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, (c1, c2) -> c1.getId() - c2.getId());
*/

// 添加元素到优先队列
customerPriorityQueue.add(new Customer(5));
customerPriorityQueue.add(new Customer(1));
customerPriorityQueue.add(new Customer(3));

需要注意的是,PriorityQueue不是线程安全的。如果在多线程环境中使用,建议使用java.util.concurrent.PriorityBlockingQueue

二、栈(Stack)相关工具类

在Java中,实现栈功能的类有多种,常用的有以下3种:

// 方式一:使用ArrayDeque实现栈
Deque<Integer> stack1 = new ArrayDeque<>();

// 方式二:使用LinkedList实现栈
Deque<Integer> stack2 = new LinkedList<>(); 

// 方式三:使用Stack类实现栈(不过这个类设计较老,不太推荐使用)
Stack<Integer> stack3 = new Stack<>();

这3种实现方式都有一些常用方法:

  • void push(E e):把元素压入栈顶。
  • E pop():移除并返回栈顶元素。
  • E peek():返回栈顶元素,但不移除。
  • boolean isEmpty():检查栈是否为空。
  • int size():返回栈中元素的数量。
  • void clear():清空栈。

它们之间也存在一些区别,具体如下:

特性 ArrayDeque Stack LinkedList
底层数据结构 动态循环数组 动态数组(继承自Vector 双向链表
线程安全 不安全 安全(通过同步机制实现) 不安全
性能 高效(大部分操作时间复杂度为O(1)) 较低(存在同步开销) 高效(大部分操作时间复杂度为O(1))
推荐使用场景 栈或双端队列 不推荐使用(设计较老) 栈或双端队列
随机访问 不支持 支持 不支持
额外功能 支持双端队列操作 search()方法 支持双端队列操作

三、数组(Arrays)工具类

Arrays类提供了很多方便操作数组的方法,例如:

// 整数数组求和
int total = Arrays.stream(nums).sum();
// 整数数组获取最小值
int min = Arrays.stream(nums).min().getAsInt();

// 对数组进行排序
Arrays.sort(nums);

// 比较两个数组是否相等
Arrays.equals(nums1, nums2);

四、字符(Character)相关工具类

在处理字符时,Character类提供了一些实用的方法:

// 判断字符是否是字母或数字
Character.isLetterOrDigit(ch1);
// 将字符转为小写(对字母而言,如果字符已经是小写或不是字母,则返回原字符)
Character.toLowerCase(ch1); 

五、字符串相关工具类

(一)字符串数组拼接

// 使用指定的分隔符,将字符串数组拼接成一个字符串
String.join(" ", strs);

(二)字符串构建

// 创建一个StringBuffer对象,用于构建字符串
StringBuffer cur = new StringBuffer();
// 向StringBuffer中追加字符串
cur.append(str);
// 删除指定区间的字符,这里删除从start开始到字符串末尾的字符
cur.delete(start, cur.length());

(三)字符串转字符数组

// 将字符串转换为字符数组
char[] sc = str.toCharArray();

六、随机数生成相关工具类

在Java中,生成随机数有两种常见方式:

(一)使用Random类

// 创建Random对象
Random random = new Random();
// 生成一个0到9之间的随机整数
int a = random.nextInt(10);
// 生成一个0到9之间的随机long整数
long b = random.nextLong(10);
// 生成一个0到10(不包含)之间的随机浮点数
double c = random.nextDouble(10);

(二)使用Math.random()方法

// `Math.random()`是`Math`类的静态方法,返回一个`[0.0, 1.0)`范围内的伪随机`double`值。
// 通过乘以一个范围值并强制转换为`int`,可以生成一个随机整数
int num = (int) (Math.random() * 10); // 生成一个0到9的随机整数

这两种方法的区别如下:

特性 Random.nextInt(int bound) Math.random() + 强制转换
Random Math
方法 nextInt(int bound) Math.random()
返回值 [0, bound)范围内的int [0.0, 1.0)范围内的double
随机性 伪随机数,基于种子 伪随机数,基于系统时间
性能 较高 较低(涉及浮点数运算和转换)
线程安全 不安全 安全(静态方法)
适用场景 需要生成多个随机数时 生成单个随机数或简单场景

七、集合相关工具类

(一)元素排序

在集合中对元素进行排序,可以使用Collections.sort()方法,示例如下:

// 使用匿名内部类实现比较器,按值降序排列
Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
    @Override
    public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
        // 这里实现降序排列
        return o2.getValue().compareTo(o1.getValue()); 
    }
});

// 使用Lambda表达式简化代码
Collections.sort(list, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));

// 对于简单的比较规则,可以使用`Comparator.comparing`方法。例如:Comparator.comparingInt(Customer::getId)
Collections.sort(list, Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()));

(二)元素删除

在集合中删除元素时,需要注意不同集合的删除方法:

// list集合的remove()方法,参数传的是索引,这里删除list中最后一个元素
list.remove(list.size() - 1);
// hashMap集合的remove()方法,参数传的是key,删除指定key对应的元素
hashMap.remove(val);

(三)元素交换

// 交换集合中指定位置的两个元素
Collections.swap(curList, i, first);

八、基本类型转换相关工具类

在处理数据类型转换时,经常会用到一些方法,例如将字符串转换为整型:

// 将字符串转换为整型
Integer a = Integer.parseInt(s);

本文详细介绍了刷算法题时常用的Java工具类,内容后续还会持续更新和完善。希望这些知识能帮助大家在算法题的学习和练习中理解得更透彻。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/16195.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】