在Java中对列表进行排序的最快方法

时间:2012-03-12 16:48:09

标签: java list sorting

我在Java中有以下代码:

   public  class ServerInfo {
    int serverId;
    int serverDataRate;
    public ServerInfo(int serverId, int serverDataRate) {
        this.serverId = serverId;
        this.serverDataRate = serverDataRate;
    }
    public int getServerId() {
        return serverId;
    }
    public double getServerDataRate() {
        return serverDataRate;
    }
       public String toString(){
            return serverId + ":" + serverDataRate;
        }
    }    

    public class ServerInfoComparator implements Comparator<ServerInfo> {

    @Override
    public int compare(ServerInfo o1, ServerInfo o2) {
          double datarate1=o1.getServerDataRate();
          double datarate2=o2.getServerDataRate();

          if(datarate1>datarate2)
              return -1;
          else if(datarate1<datarate2)
              return +1;
          else
              return 0;
    }           
}

   public class Sample {
    List<ServerInfo> listOfServers= new ArrayList<ServerInfo>();

    public void insertIntoList(){

        listOfServers.add( new ServerInfo(0,256));
        listOfServers.add( new ServerInfo(1,270));
        listOfServers.add( new ServerInfo(2,256));
        listOfServers.add( new ServerInfo(3,290));
        listOfServers.add( new ServerInfo(4,300));
        listOfServers.add( new ServerInfo(5,300));
        listOfServers.add( new ServerInfo(6,256));
        listOfServers.add( new ServerInfo(7,265));
        listOfServers.add( new ServerInfo(8,289));
        listOfServers.add( new ServerInfo(9,310));  
    }

    public static void main( String[] args){
        Sample s = new Sample();
        s.insertIntoList();
        ServerInfoComparator com  = new ServerInfoComparator();
        Collections.sort(s.listOfServers,com);

        for( ServerInfo server: s.listOfServers){
            System.out.println(server);
        }           
    }
}

我使用上面的代码根据serverDataRate按降序对元素进行排序。假设我在列表中有100个元素的更大样本集,并且代码必须每5-10秒执行一次,那么样本集非常小。这是对列表进行排序的最快方法,还是有一种我不知道的更快的方法?

7 个答案:

答案 0 :(得分:12)

我改变了你的考试

private final List<ServerInfo> listOfServers = new ArrayList<ServerInfo>();

public void insertIntoList() {
    for (int i = 0; i < 1000000; i++)
        listOfServers.add(new ServerInfo(i, (int) (200 + Math.random() * 200)));
}

public static void main(String[] args) {
    MyApp s = new MyApp();
    s.insertIntoList();
    ServerInfoComparator com = new ServerInfoComparator();
    long start = System.nanoTime();
    Collections.sort(s.listOfServers, com);
    long time = System.nanoTime() - start;
    System.out.printf("Sorting %,d took %.3f seconds%n", s.listOfServers.size(), time/1e9);

    for (ServerInfo server : s.listOfServers) {
//    System.out.println(server);
    }
}

并打印

Sorting 1,000,000 took 0.438 seconds

那要快一点;)

顺便说一句:我将double字段更改为int

答案 1 :(得分:3)

除非您的比较步骤非常重(看起来不像),否则100个元素不是很大的集合。在任何稍微现代化的机器中,100个元素将快速排序

话虽如此,我认为你的方法非常接近标准,我不会担心尝试优化它,除非你真的最终需要它。

早期优化是许多搞砸的父亲(假设是母亲)。

答案 2 :(得分:2)

您不需要在类中使用方法调用,即使该字段是私有的并不总是已知的 - private限制对类的访问,而不是对象的访问。

由于您的方法只返回属性,因此您可以直接使用该属性:

@Override
public int compare(ServerInfo o1, ServerInfo o2) {
/*
      double datarate1=o1.getServerDataRate ();
      double datarate2=o2.getServerDataRate ();
*/
      double datarate1=o1.serverDataRate;
      double datarate2=o2.serverDataRate;

      if (datarate1 > datarate2)
          return -1;
      else if ( datarate1 < datarate2)
          return +1;
      else
          return 0;
}           

但是JVM可能会优化函数调用,并且在100个元素的范围内,它几乎不可测量。

你的方法返回一个双 - 你可以解释为什么?

使用整数,您可以这样做:

@Override
public int compare (ServerInfo o1, ServerInfo o2) {
      return o2.serverDataRate - o1.serverDataRate;
}           

但是考虑int over-overrun和underrun问题的最极端值。

答案 3 :(得分:1)

这不正常。检查你的计时方式。

long start = System.nanoTime();

// Sort here

long time = System.nanoTime() - start;
System.out.println(time / 1000000L + " Milliseconds");

答案 4 :(得分:1)

鉴于您没有经常排序,速度不应成为问题。即使有数千个项目,Collections.sort也非常快。

您是否尝试过应用程序以查看速度是否存在问题?过早优化不是一个好主意:))

警惕您的代码有一点:除非您确保所有服务器的dataRates在排序过程中不会发生变化,否则您可能会得到不一致的结果!您应该同步方法,以便在整个列表排序之前datarates不会更改。

答案 5 :(得分:0)

您可以使用数据结构以更快的方式完成排序。

BST(二进制搜索树)或TRIE将帮助您以更快的方式对大量数据进行排序。

它们需要一些冗长的代码,但如果数据集很大,它将帮助你在日志中运行。

答案 6 :(得分:0)

首先,您的serverDataRate变量类型是int。但是getter方法返回类型是double。当比较器工作时,所有getServerDataRate方法都将字段转换为更高的数据格式。如果getter方法的返回类型与字段类型相同,那么比较时间将更短。 第二,如果您的任务是简单的操作,则无需使用if(),在比较方法中。只需使用减法。像这样:


the getter:
    public int getServerDataRate() {
        return serverDataRate;
    }

in comparator:
return o1.getServerDataRate()-o2.getServerDataRate(); // from smallest to largest value
or
return o2.getServerDataRate()-o1.getServerDataRate(); // from largest to smallest value