开发者

cant sort the following tree map

for (a = 0; a < filename; a++) {
  Map<Double,String> m = new HashMap<Double,String>();

  String pre = "abc";
  String post = ".txt";
  for (int ii = 0; ii < 11; ii++) {
    m.put(similarityScore[a],pre + a + post + '\n');
  }
  SortedSet<Double> set = new TreeSet<Double>(m.keySet());
  for (Double d : set) {
    System.out.println(d + " " + m.get(d));
  }
}

Output :

0.5773502691896258 abc0.txt
0.5773502691896258 abc1.txt
0.5773502691896258 abc2.txt
NaN abc3.txt
0.5773502691896258 abc4.txt
NaN abc5.txt
NaN abc6.txt
NaN abc7.txt
NaN abc8.txt
0.5773502691896258 abc9.txt
NaN abc10.txt

This code should be able to sort the double values. But it displays the output on top开发者_运维问答. What happen ?


The problem is almost certainly NaN.

This is, as the name suggests, not a realy number, and behaves very strangely in terms of comparisons. Is NaN greater than, equal to, or less than 0.5773502691896258? It could be any of those results, and isn't even required to be consistent within a single execution of the program. NaN is not even equal to itself, which says something about how preconceptions of the laws of equality, and strong ordering, go out of the window when NaN is involved.

So the fix is not to use a non-numeric and expect Double.compareTo() to do what you want with it. Depending on what NaN means when returned from similarityScore(), there are several approaches you could take. If it means that it's not a match at all, you could have that method return a Double (rather than a double), return null in these cases, and then only add non-null results to the map. If these results should be displayed anyway, then perhaps you could use a result of 0.0 or -1.0, assuming that's less than any "real" similarity score. If you want something more finessed, then returning something as pure and straightforward as a primitive double is likely going to be the problem, and you may need to return your own (simple) domain class instead.


As an aside - why on earth do you create and populate a HashMap, then use a TreeSet to get the iteration order over the keys? If you simply create m as a TreeMap<Double, String> you get exactly the iteration order you want, so can just iterate overm.entrySet()`. It's clearer, more idiomatic (thus more understandable), and more efficient, so there's no reason not to do this.


for (int ii = 0; ii < 11; ii++) {
    m.put(similarityScore[a],pre + a + post + '\n');
}

This puts the same value into the map 11 times - you're not referencing ii inside the loop.

for (Double d : set) {
    System.out.println(d + " " + m.get(d));
}

This prints the single entry in the map.

You do the above for values 0..filename - Adding a value to the map several times, then printing it and restarting with a new map.

Map<Double,String> m = new HashMap<Double,String>();
for (a = 0; a < filename; a++) {
  String pre = "abc";
  String post = ".txt";
  m.put(similarityScore[a],pre + a + post + '\n');
}
SortedSet<Double> set = new TreeSet<Double>(m.keySet());
for (Double d : set) {
  System.out.println(d + " " + m.get(d));
}

This creates a map, populates it with values for 0..filename, then prints it sorted. You'll still have issues with NaN which isn't really sortable.

Map<Double,String> m = new TreeMap<Double,String>();
for (a = 0; a < filename; a++) {
  String pre = "abc";
  String post = ".txt";
  m.put(similarityScore[a],pre + a + post + '\n');
}
for (Double d : m.keySet()) {
  System.out.println(d + " " + m.get(d));
}

And this uses a TreeMap - No need for the intermediate Set


For any Collection to sort, the type of the value on which you are sorting should be same. And should implement comparable interface.

In your case you have NaN and Double values to sort.


Your loop means you're sorting for each filename separately. You'll need to pull the sorting out of the loop to get those values sorted. (Ooops, @Eric beat me to it.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜