算法题的“战场”上,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():清空栈。

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

特性ArrayDequeStackLinkedList
底层数据结构动态循环数组动态数组(继承自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() + 强制转换
RandomMath
方法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工具类,内容后续还会持续更新和完善。希望这些知识能帮助大家在算法题的学习和练习中理解得更透彻。