Comparator接口、Lambda表达式和PriorityQueue优先队列

Comparator接口

  1. 接口重写方法

Comaparator接口用于实现排序,通常作为排序的参数输入,如Collections.sort(array,Comparator),接口中包含compare(Object obj1,Object obj2)和equals(Object obj)方法,compare方法用于比较obj1和obj2,obj1>obj2,return 大于0的数,相等return0,小于则return小于零的数

  1. 接口的实现方法

接口实现方法:类实现(重写compare方法,equals方法Object类中实现,因此不需要重写)、lambda表达式

  1. 匿名对象代码实例
public void test5() {
     
        //TreeMap的定制排序
        Comparator com = new Comparator() {
     
            @Override
            public int compare(Object o1, Object o2) {
     
                if (o1 instanceof Person1 && o2 instanceof Person1) {
     
                    Person1 p1 = (Person1) o1;
                    Person1 p2 = (Person1) o2;
                    int i = p1.getSex().compareTo(p2.getSex());
                    if (i == 0) {
     
                        return p1.getAge().compareTo(p2.getAge());
                    }
                    return i;
                }
                return 0;
            }
        };


        Map map = new TreeMap(com);
        map.put(new Person1("AA", 23), 55);
        map.put(new Person1("CC", 44), 55);
        map.put(new Person1("ZZ", 255), 55);
        map.put(new Person1("DD", 32), 55);
        map.put(new Person1("GG", 11), 55);
        map.put(new Person1("MM", 15), 55);
        map.put(new Person1("CC", 33), 55);
        for (Object a : map.keySet()) {
     
            System.out.println(a + "=" + map.get(a));
        }

    }

Lambda表达式

Lambda表达式允许通过表达式来代替功能接口功能(注意表达式中参数以及参数方法的一致性,使用中尽量添加泛型约束)
通过另一篇博客进行学习,本文中进行了一些转载和自己的相关测试:Lambda表达式的使用

  1. Lambda表达式的基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s) 
  1. for循环和Lambda表达式的循环
String[] arr=new String[]{
     "sdf","dsf","34"};
        List<String> list= Arrays.asList(arr);
        //1、以往for循环
        for(String a:list){
     
            System.out.print(a+" ");
        }
        System.out.println();
        //2、forEach和Lambda
        //forEach()即增强for循环方法,测试发现引用数据类型Integer和String等没有这个方法
        list.forEach((a)-> System.out.print(a+" "));

在这里插入图片描述

  1. 匿名内部类和Lambda
    注意:Lambda用于实现匿名内部类方法时,内部类继承的接口应只有一个抽象方法,否则虚拟机不能判断调用哪个方法,报错
//1、匿名内部类
        Person p1=new Person(){
     
            @Override
            public void run() {
     
                System.out.println("hello");
            }
        };
        //2、Lambda
        Person p2=()-> System.out.println("hello");

        p1.run();
        p2.run();

在这里插入图片描述

  1. Lambda作为功能接口实现排序
    Lambda作为排序参口传递进方法中,也就是说Lambda可以替代Comparator接口作为排序参数
    三种排序接口的实现方式(使用TreeMap作为参考):
    (1)匿名类对象实现Comparator接口
 Comparator com = new Comparator() {
     
            @Override
            public int compare(Object o1, Object o2) {
     
                if (o1 instanceof Person1 && o2 instanceof Person1) {
     
                    Person1 p1 = (Person1) o1;
                    Person1 p2 = (Person1) o2;
                    int i = p1.getSex().compareTo(p2.getSex());
                    if (i == 0) {
     
                        return p1.getAge().compareTo(p2.getAge());
                    }
                    return i;
                }
                return 0;
            }
        };
        Map map = new TreeMap(com);

(2)Lambda表达式实现Comparator接口

Comparator<Person1> com1=(p1,p2)->p1.getAge().compareTo(p2.getAge());
Map map=new TreeMap(com1);

**注意:**在网上找了一些学习资料后,自己测试过程中遇到了Comparator com1=(p1,p2)->p1.getAge().compareTo(p2.getAge());这行代码报错的问题,刚开始以为是Person1类中我没有实现compareTo方法,但是修改后还是不对,多次测试后发现,Comparator中,T默认为Object类,因此只要输入参数p1和p2不是此类就会报错,而且Lambda表达式中会自动识别输入参数类,不需要用类来修饰。
(3)匿名Lambda表达式
TreeMap构造器中传入匿名Lambda表达式时需要加泛型,在使用匿名Lambda方法时需要注意

 Map map=new TreeMap<>((Person1 p1,Person1 p2)->p1.getAge().compareTo(p2.getAge()));

PriorityQueue优先队列

  1. PeiorityQueue之前没有总结过,这里做个总结,底层使用小顶堆二叉树实现,因此能够实现由小到大的排序,底层数组的第0个索引元素为最小值
  2. 小顶堆的排序方法可以通过传入排序接口对象实现,这里采用匿名Lambda方法
  3. 实例化方法
//源码:
public PriorityQueue(Comparator<? super E> comparator) {
     
        this(DEFAULT_INITIAL_CAPACITY, comparator);
    }
//测试:
 PriorityQueue heap=new PriorityQueue<Integer>((n1,n2)->n1-n2);
  1. add()、offer()方法
//add()、offer():向优先队列中添加元素,插入失败add()抛出异常,offer()返回false
heap.offer(20);
heap.offer(1);
heap.offer(58);
System.out.println(heap);

在这里插入图片描述
可以看到,每添加一个元素,优先队列就按照排序方法排序为小顶堆

  1. element()、peek()
//element()、peek():都是获取但不删除队首元素,方法失败时前者抛出异常,后者返回null
        System.out.println(heap.peek());

在这里插入图片描述

  1. remove()、poll()
 PriorityQueue heap=new PriorityQueue<Integer>((n1,n2)->n1-n2);
        heap.offer(20);
        heap.offer(15);
        heap.offer(58);
        heap.offer(17);
        System.out.println(heap);
        //remove()、poll():获取并删除队首元素,当方法失败时前者抛出异常,后者返回null
        //按照小顶堆二叉树原理,将根节点元素和最后一个叶节点元素调换,并删去此叶节点,之后对二叉树重新小顶堆
        heap.poll();
        System.out.println(heap);

在这里插入图片描述
Comparator接口、Lambda表达式和PriorityQueue优先队列_第1张图片

你可能感兴趣的:(java,lambda,queue,接口)