Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用分数表对java列表进行排序_Java_Sorting - Fatal编程技术网

使用分数表对java列表进行排序

使用分数表对java列表进行排序,java,sorting,Java,Sorting,我有一个N个字符串的列表,和一个N个分数的并行列表。我需要使用表中的分数对字符串进行排序。我该怎么做 我目前的解决方案是使用索引的辅助列表,如下所示: public static List<String> sortByScores(List<String> strings, final List<Float> scores) { List<Integer> indices = new ArrayList<Integer>(str

我有一个N个字符串的列表,和一个N个分数的并行列表。我需要使用表中的分数对字符串进行排序。我该怎么做

我目前的解决方案是使用索引的辅助列表,如下所示:

public static List<String> sortByScores(List<String> strings, final List<Float> scores) {
    List<Integer> indices = new ArrayList<Integer>(strings.size());
    for (int i=0; i<strings.size(); i++) 
        indices.add(i);
    Collections.sort(indices, new Comparator<Integer>() {
        @Override public int compare(Integer arg0, Integer arg1) {  // sort in descending order
            return -scores.get(arg0).compareTo(scores.get(arg1));
        }
    });
    List<String> sortedStrings = new ArrayList<String>(strings.size());
    for (int i=0; i<indices.size(); ++i)
        sortedStrings.add(strings.get(indices.get(i)));
    return sortedStrings;
}
public static List<String> sortByScoresUsingClass(List<String> strings, final List<Float> scores) {
    List<ScoreClass> list = new ArrayList<ScoreClass>(strings.size());
    for (int i=0; i<strings.size(); i++) {
        ScoreClass sc = new ScoreClass(strings.get(i),scores.get(i));
        list.add(sc);
    }
    Collections.sort(list);
    List<String> sortedStrings = new ArrayList<String>(strings.size());
    for (ScoreClass item: list)
        sortedStrings.add(item.myString);
    return sortedStrings;
}


sorting 10000 took 60 ms.
sorting 30000 took 121 ms.
sorting 100000 took 40 ms.
sorting 300000 took 280 ms.
sorting 1000000 took 648 ms.
sorting 3000000 took 3254 ms.
它可以工作,但似乎效率低下


有更好的解决方案吗?

将字符串和分数放在一个类中,并以这种方式实现可比较的接口。您可以对分数进行排序,但排序后您可以访问字符串,这对我来说似乎是最有效的

例如:

public class ScoreClass implements Comparable<ScoreClass>
{
    String myString;
    float score;

    public int compareTo(ScoreClass c)
    {
        return Float.compare(this.score, c.score);
    }
}

这是大脑编译的代码,所以如果有什么问题,请告诉我。

将字符串和分数放在一个类中,并实现可比较的接口,您可以按分数排序,但排序后您可以访问字符串,这对我来说似乎是最有效的

例如:

public class ScoreClass implements Comparable<ScoreClass>
{
    String myString;
    float score;

    public int compareTo(ScoreClass c)
    {
        return Float.compare(this.score, c.score);
    }
}

这是大脑编译的代码,所以如果有问题请告诉我。

我会创建一个包含字符串及其分数的新POJO,并让它实现可比较的

我会创建一个包含字符串及其分数的新POJO,并让它实现可比较的

伪代码

// Precondition: length of each list is the same, call it N
let m = new TreeMap<Integer, List<String>>()
for i in 0 .. N-1
    if m.containsKey(scores[i])
        m.get(scores[i]).append(strings[i])
    else
        m.put(scores[i], a new list containing the sole element strings[i])
    end if
end if

for each entry (k, v) in m
    output all the strings in v
end
不需要排序或定义可比数据或任何东西,因为树形图已经根据分数排序了

伪码

// Precondition: length of each list is the same, call it N
let m = new TreeMap<Integer, List<String>>()
for i in 0 .. N-1
    if m.containsKey(scores[i])
        m.get(scores[i]).append(strings[i])
    else
        m.put(scores[i], a new list containing the sole element strings[i])
    end if
end if

for each entry (k, v) in m
    output all the strings in v
end

不需要排序或定义可比数据或任何东西,因为树形图已经根据分数排序了

好的,我使用随机字符串集合测试了您建议的所有方法:

public static void testSortByScores(int count) {
    int length = 4;
    // Create a random array and random scores:
    List<String> strings = new ArrayList<String>(count);
    List<Float> scores = new ArrayList<Float>(count);
    RandomString randomString = new RandomString(length);
    String letters = "abcdefghijklmnopqrstuvwxyz";
    for (int iString=0; iString<count; ++iString) {
        StringBuffer randomStringBuffer = new StringBuffer(length);
        int score = 0;
        for (int iChar=0; iChar<length; ++iChar) {
            int index = (int)(Math.random()*letters.length());
            char c = letters.charAt(index);
            randomStringBuffer.append(c);
            score += index;
        }
        strings.add(randomStringBuffer.toString());
        scores.add((float)score);
    }


    long start = System.currentTimeMillis();
    strings = sortByScoresUsingIndices(strings,scores);
    //strings = sortByScoresUsingClass(strings,scores);
    //strings = sortByScoresUsingTree(strings,scores);
    System.out.println("sorting "+count+" took "+(System.currentTimeMillis()-start)+" ms.");
}
然后是使用ScoreClass的方法,我是这样实现的:

public static List<String> sortByScores(List<String> strings, final List<Float> scores) {
    List<Integer> indices = new ArrayList<Integer>(strings.size());
    for (int i=0; i<strings.size(); i++) 
        indices.add(i);
    Collections.sort(indices, new Comparator<Integer>() {
        @Override public int compare(Integer arg0, Integer arg1) {  // sort in descending order
            return -scores.get(arg0).compareTo(scores.get(arg1));
        }
    });
    List<String> sortedStrings = new ArrayList<String>(strings.size());
    for (int i=0; i<indices.size(); ++i)
        sortedStrings.add(strings.get(indices.get(i)));
    return sortedStrings;
}
public static List<String> sortByScoresUsingClass(List<String> strings, final List<Float> scores) {
    List<ScoreClass> list = new ArrayList<ScoreClass>(strings.size());
    for (int i=0; i<strings.size(); i++) {
        ScoreClass sc = new ScoreClass(strings.get(i),scores.get(i));
        list.add(sc);
    }
    Collections.sort(list);
    List<String> sortedStrings = new ArrayList<String>(strings.size());
    for (ScoreClass item: list)
        sortedStrings.add(item.myString);
    return sortedStrings;
}


sorting 10000 took 60 ms.
sorting 30000 took 121 ms.
sorting 100000 took 40 ms.
sorting 300000 took 280 ms.
sorting 1000000 took 648 ms.
sorting 3000000 took 3254 ms.

好的,我使用随机字符串集合测试了您建议的所有方法:

public static void testSortByScores(int count) {
    int length = 4;
    // Create a random array and random scores:
    List<String> strings = new ArrayList<String>(count);
    List<Float> scores = new ArrayList<Float>(count);
    RandomString randomString = new RandomString(length);
    String letters = "abcdefghijklmnopqrstuvwxyz";
    for (int iString=0; iString<count; ++iString) {
        StringBuffer randomStringBuffer = new StringBuffer(length);
        int score = 0;
        for (int iChar=0; iChar<length; ++iChar) {
            int index = (int)(Math.random()*letters.length());
            char c = letters.charAt(index);
            randomStringBuffer.append(c);
            score += index;
        }
        strings.add(randomStringBuffer.toString());
        scores.add((float)score);
    }


    long start = System.currentTimeMillis();
    strings = sortByScoresUsingIndices(strings,scores);
    //strings = sortByScoresUsingClass(strings,scores);
    //strings = sortByScoresUsingTree(strings,scores);
    System.out.println("sorting "+count+" took "+(System.currentTimeMillis()-start)+" ms.");
}
然后是使用ScoreClass的方法,我是这样实现的:

public static List<String> sortByScores(List<String> strings, final List<Float> scores) {
    List<Integer> indices = new ArrayList<Integer>(strings.size());
    for (int i=0; i<strings.size(); i++) 
        indices.add(i);
    Collections.sort(indices, new Comparator<Integer>() {
        @Override public int compare(Integer arg0, Integer arg1) {  // sort in descending order
            return -scores.get(arg0).compareTo(scores.get(arg1));
        }
    });
    List<String> sortedStrings = new ArrayList<String>(strings.size());
    for (int i=0; i<indices.size(); ++i)
        sortedStrings.add(strings.get(indices.get(i)));
    return sortedStrings;
}
public static List<String> sortByScoresUsingClass(List<String> strings, final List<Float> scores) {
    List<ScoreClass> list = new ArrayList<ScoreClass>(strings.size());
    for (int i=0; i<strings.size(); i++) {
        ScoreClass sc = new ScoreClass(strings.get(i),scores.get(i));
        list.add(sc);
    }
    Collections.sort(list);
    List<String> sortedStrings = new ArrayList<String>(strings.size());
    for (ScoreClass item: list)
        sortedStrings.add(item.myString);
    return sortedStrings;
}


sorting 10000 took 60 ms.
sorting 30000 took 121 ms.
sorting 100000 took 40 ms.
sorting 300000 took 280 ms.
sorting 1000000 took 648 ms.
sorting 3000000 took 3254 ms.

如果有两个具有相同分数的字符串,这将不起作用,因为树映射只能为每个键保存一个项目!你说得对,埃雷,我完全错过了。我将编辑答案。如果有两个分数相同的字符串,这将不起作用,因为树形图只能为每个键保存一个项目!你说得对,埃雷,我完全错过了。我将编辑答案。