优先队列
队列符合先进先出原则,当你入队的时候如何让优先级高的VIP客户先进入队头呢?此时就需要了优先队列
优先队列定义:Queue <T> priorityqueue = new PriorityQueue<T>()
注意放入PriorityQueue中的元素必须实现Comparable
接口,PriorityQueue会根据元素的排序顺序决定出队的优先级
public class Main{
public static void main(String[] args){
Queue<String> priorityqueue=new PriorityQueue<String>();
//添加三个元素到队列
priorityqueue.offer("apple");
priorityqueue.offer("pear");
priorityqueue.offer("banana");
System.out.println(priorityqueue.pool());//apple
System.out.println(priorityqueue.pool());//banana
System.out.println(priorityqueue.pool());//pear
System.out.println(priorityqueue.pool());//null 因为队列为空
}
}
String类是默认实现Comparable接口的,如apple>banana
若放入的元素没有实现Comparable接口怎么办?PriorityQueue允许我们提供一个Comparator对象来判断两个元素的顺序
Class UserComparator implements Comparaot<User>{
public int compara(User u1,User u2){
if(u1.number,charAt(0)==u2.number.charAt(0)){
return u1.number.compareTo9u2.numebr);
}
if(u1.number.charAt(0)=='V'{
return -1;//u1的号码是V开头,优先级高)}
else{
return 1;//Comapator是判断是小于
}
class User {
public final String name;
public final String number;
public User(String name, String number) {
this.name = name;
this.number = number;
}
public String toString() {
return name + "/" + number;
}
public class Main {
public static void main(String[] args) {
Queue<User> q = new PriorityQueue<>(new UserComparator());
// 添加3个元素到队列:
q.offer(new User("Bob", "A1"));
q.offer(new User("Alice", "A2"));
q.offer(new User("Boss", "V1"));
System.out.println(q.poll()); // Boss/V1
System.out.println(q.poll()); // Bob/A1
System.out.println(q.poll()); // Alice/A2
System.out.println(q.poll()); // null,因为队列为空
}
}
上面的UserComparator的比较逻辑其实还是有问题的,它会把A10排在A2的前面,请尝试修复该错误。
拒绝修复,太懒惰了。
number是String类,我们只需将其转换为Integer类即可
int newnumber=Integer.paraseInt(number);
借此实现大顶堆
/*
最大堆问题
将所有的石头的重量放入最大堆中,每次依次从队列中去除最终的两块石头a和b,必有a>=b.
如果a>b,则将新石头a-b放回到最大堆中;若a=b,两块石头完全被粉碎,不会产生新的石头
重复上述操作,知道剩下的石头少于2块。
最终可能剩下一块石头,该石头的重量即为最大堆中剩下的元素,返回该元素;也可能没有石头剩下,此时最大堆为空,返回0
*/
public class Solution {
public int lastStoneWeight(int[] stones){
PriorityQueue<Integer> pq=new PriorityQueue<Integer>((a,b)->b-a);//使用的是匿名类
for (int stone:stones){
pq.offer(stone);
}//由此实现最大堆
while(pq.size()>1){
int a=pq.poll();
int b=pq.poll();
if (a>b){
pq.offer(a-b);
}
}
return pq.isEmpty()?0:pq.poll();
}
}
函数式编程
函数式编程(Functional Programming时把函数作为基本运算单元,函数可以作为变量,也可以接受函数。历史上研究函数式编程的卢纶时Lambda盐酸,所以我们经常把支持函数式编程的编码风格称为Lambda表达式)
Lambda表达式
在Java程序中,我们常遇到一大堆单方法接口,即一个接口只定义了一个方法:
- Comaparator
- Runnable
- Callable
以Comparator
为例,我们想要调用Arrays.sort()
时,可以传入一个Comaparator
实例,以匿名类方式编写如下:
String[] array=...
Arrays.sort(array,new Comaparator<String>(){
public int compare(String s1,String s2){
return s1.comparaeTo(s2);}
);
上述写法十分繁琐,从Java 8 开始,我们可以用Lambbda表达式替换单方法接口,改写上述代码如下:
public class Main {
public static void main(String[] args) {
String[] array = new String[] { "Apple", "Orange", "Banana", "Lemon" };
Arrays.sort(array, (s1, s2) -> {
return s1.compareTo(s2);
});
System.out.println(String.join(", ", array));
}
}
其中,参数是(s1, s2),参数类型可以省略,因为编译器可以自动推断出String类型。-> { … }表示方法体,所有代码写在内部即可。Lambda表达式没有class定义,因此写法非常简洁。
如果只有一行return xxx的代码,完全可以用更简单的写法:
Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));
FunctionalInterface
我们把只定义了单方法的接口称之为FunctionalInterface,用注解@FunctionalInterface标记。例如,Callable接口:
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
default Comparator<T> thenComparing(Comparator<? super T> other) {
...
}
...
}
虽然Comparator接口有很多方法,但只有一个抽象方法int compare(T o1, T o2),其他的方法都是default方法或static方法。另外注意到boolean equals(Object obj)是Object定义的方法,不算在接口方法内。因此,Comparator也是一个FunctionalInterface。
default方法的目的是,当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。
接口内部的方法全部是public abstract
Maven
windos下必须要配置Maven环境变量,才能使用mvn clean package命令
要安装Maven,可以从Maven官网下载最新的Maven 3.6.x,然后在本地解压,设置几个环境变量:
M2_HOME=/path/to/maven-3.6.x
PATH=$PATH:$M2_HOME/bin
win+R打开cmd 使用mvn -- version
查看mvn版本