java里的Collections类中的静态方法sort()是怎么用比较器比较两个对象?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java里的Collections类中的静态方法sort()是怎么用比较器比较两个对象?相关的知识,希望对你有一定的参考价值。

我写了个类:
class Light
String name;
float price;
Date date;

public Light(String name,float price,Date date)
this.name=name;
this.price=price;
this.date=date;


public String toString()
return "name:"+this.name+" price:"+this.price;


public void setDate(Date date)
this.date=date;


public Date getDate()
return this.date;


现在比较两个Light对象怎么比较,我知道要实现Comparator接口,但具体就不知道了。

1、定义一个实现Comparator接口的类如:LightComparator,然后实现public int compare(Object o1,Object o2)方法。这个方法的实现将决定你是以何种方式排序。例如:你根据价格排序,那么这个方法实现为:

public int compare(Object o1,Object o2)
Light l1 = (Light)o1;
Light l2 = (Light)o2;

return (int)(l1.getPrice()-l2.getPrice());
//假定你这个类里有get set方法。

2、运用Collections排序,提供一个List(保存的是Light对象)设为list:
Collections.sort(list,new LightComparator());
参考技术A sort
public static <T> void sort(List<T> list,
Comparator<? super T> c)根据指定比较器产生的顺序对指定列表进行排序。此列表内的所有元素都必须可使用指定比较器相互比较(也就是说,对于列表中的任意 e1 和 e2 元素,c.compare(e1, e2) 不得抛出 ClassCastException)。
此排序被保证是稳定的:不会因调用 sort 而对相等的元素进行重新排序。

排序算法是一个经过修改的合并排序算法(其中,如果低子列表中的最高元素小于高子列表中的最低元素,则忽略合并)。此算法提供可保证的 n log(n) 性能。 指定列表必须是可修改的,但不必是可大小调整的。此实现将指定列表转储到一个数组中,并对数组进行排序,在重置数组中相应位置每个元素的列表上进行迭代。这避免了由于试图原地对链接列表进行排序而产生的 n2 log(n) 性能。

参数:
list - 要排序的列表。
c - 确定列表顺序的比较器。null 值指示应该使用元素的自然顺序。

Java多线程3:Thread中的静态方法

Thread类中的静态方法

Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程"。为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程进行操作。下面来看一下Thread类中的静态方法:

1、currentThread()

currentThread()方法返回的是对当前正在执行线程对象的引用。看一个重要的例子,然后得出结论:

复制代码
public class MyThread04 extends Thread
{
    static
    {
        System.out.println("静态块的打印:" + 
                Thread.currentThread().getName());    
    }
    
    public MyThread04()
    {
        System.out.println("构造方法的打印:" + 
                Thread.currentThread().getName());    
    }
    
    public void run()
    {
        System.out.println("run()方法的打印:" + 
                Thread.currentThread().getName());
    }
}
复制代码
public static void main(String[] args)
{
    MyThread04 mt = new MyThread04();
    mt.start();
}

看一下运行结果:

静态块的打印:main
构造方法的打印:main
run()方法的打印:Thread-0

这个例子说明了,线程类的构造方法、静态块是被main线程调用的,而线程类的run()方法才是应用线程自己调用的。在这个例子的基础上,再深入:

复制代码
public class MyThread05 extends Thread
{
    public MyThread05()
    {
        System.out.println("MyThread5----->Begin");
        System.out.println("Thread.currentThread().getName()----->" + 
                Thread.currentThread().getName());
        System.out.println("this.getName()----->" + this.getName());
        System.out.println("MyThread5----->end");
    }
    
    public void run()
    {
        System.out.println("run----->Begin");
        System.out.println("Thread.currentThread().getName()----->" + 
                Thread.currentThread().getName());
        System.out.println("this.getName()----->" + this.getName());
        System.out.println("run----->end");
    }
}
复制代码
public static void main(String[] args)
{
    MyThread05 mt5 = new MyThread05();
    mt5.start();
}

看一下运行结果:

复制代码
MyThread5----->Begin
Thread.currentThread().getName()----->main
this.getName()----->Thread-0
MyThread5----->end
run----->Begin
Thread.currentThread().getName()----->Thread-0
this.getName()----->Thread-0
run----->end
复制代码

上篇文章的开头就说过,要理解一个重要的概念,就是"this.XXX()"和"Thread.currentThread().XXX()"的区别,这个就是最好的例子。必须要清楚的一点就是:当前执行的Thread未必就是Thread本身。从这个例子就能看出来:

(1)执行MyThread05构造方法是main,当前线程却是Thread-0

(2)执行run()方法的Thread-0,当前线程也是Thread-0,说明run()方法就是被线程实例去执行的

所以,再强调一下,未必在MyThread05里调用Thread.currentThread()返回回来的线程对象的引用就是MyThread05

2、sleep(long millis)

sleep(long millis)方法的作用是在指定的毫秒内让当前"正在执行的线程"休眠(暂停执行)。这个"正在执行的线程"是关键,指的是Thread.currentThread()返回的线程。根据JDK API的说法,"该线程不丢失任何监视器的所属权",直白点讲,就是不让出CPU资源。CPU还在执行当前线程run()方法中的代码,无非执行的内容是"睡觉"而已。看一下例子:

复制代码
public class MyThread07 extends Thread
{
    public void run()
    {
        try
        {
            System.out.println("run threadName = " + 
                    this.getName() + " begin");
            Thread.sleep(2000);
            System.out.println("run threadName = " + 
                    this.getName() + " end");
        } 
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
复制代码
复制代码
public static void main(String[] args)
{
    MyThread07 mt = new MyThread07();
    System.out.println("begin = " + System.currentTimeMillis());
    mt.start();
    System.out.println("end = " + System.currentTimeMillis());
}
复制代码

看一下运行结果:

begin = 1443694780609
end = 1443694780609
run threadName = Thread-0 begin
run threadName = Thread-0 end

当然,因为打印结果是静态的,所以只能看出异步执行的效果,看不出sleep(long millis)方法执行的效果。实际上第3句打出2秒后打出第4句,这和run()方法里面的sleep(2000)是对应的

3、yield()

暂停当前执行的线程对象,并执行其他线程。这个暂停是会放弃CPU资源的,并且放弃CPU的时间不确定,有可能刚放弃,就获得CPU资源了,也有可能放弃好一会儿,才会被CPU执行。看一下例子:

复制代码
public class MyThread08 extends Thread
{
    public void run()
    {
        long beginTime = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 50000000; i++)
        {
            Thread.yield();
            count = count + i + 1;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("用时:" + (endTime - beginTime) + "毫秒!");
    }
}
复制代码
public static void main(String[] args)
{
    MyThread08 mt = new MyThread08();
    mt.start();
}

看一下运行结果:

复制代码
用时:3264毫秒!
用时:3299毫秒!
用时:3232毫秒!
用时:3256毫秒!
用时:3283毫秒!
用时:3504毫秒!
用时:3378毫秒!
复制代码

看到,每次执行的用时都不一样,证明了yield()方法放弃CPU的时间并不确定。

4、interrupted()

测试当前线程是否已经中断,执行后具有将状态标识清除为false的功能。换句话说,如果连续两次调用该方法,那么返回的必定是false:

复制代码
public static void main(String[] args)
{
    Thread.currentThread().interrupt();
    System.out.println("是否停止1?" + Thread.interrupted());
    System.out.println("是否停止2?" + Thread.interrupted());
    System.out.println("end!");
}
复制代码

当然,这也涉及Java的中断机制,留在后面的一篇文章专门讲解。

以上是关于java里的Collections类中的静态方法sort()是怎么用比较器比较两个对象?的主要内容,如果未能解决你的问题,请参考以下文章

Java-Collections 和 Arrays

C++ 静态方法(在不同的类中)(如 Java 的)

Java中自定义对象使用Collections工具类中的Sort方法

JAVA如何获取嵌套在静态LIST类中的静态LIST类

java里的静态成员变量是放在了堆内存还是栈

Java学习笔记静态导入