我在这个论坛和其他论坛上读了很多关于这个问题的文章,但我仍然无法得到具体的答案。无论如何,我决定这样做:
下面是一个保存字符串和整数的类:
public class Tuple{
private String token;
private int docID;
public Tuple(String token, int docID) {
this.token = token;
this.docID = docID;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getDocID() {
return docID;
}
public void setDocID(int docID) {
this.docID = docID;
}
}
然后,我创建一个数组列表来将这些元组放在private ArrayList<Tuple> temps = new ArrayList<>();
然后我像这样填充数组列表:
for ( int i = 0; i < numberOfDocs; i++ )
{
Tuple cat = new Tuple(Double.toString(vect[i]),i);
temps.add(cat);
}
最终,我将像这样对数组进行排序:
public void sortTmp()
{
Collections.sort(temps, new Comparator<Tuple>()
{
@Override
public int compare(Tuple tr2, Tuple tr1)
{
return tr2.getToken().compareTo(tr1.getToken());
}
});
}
java 和双精度存在一些问题,我不能直接使用我的双矩阵,所以我必须做Double.toString()
.结果已排序,但不完全正确,因为从双精度数排序计算的字符串不是很准确。
有什么想法吗?
如果你通过String
表示来比较double
的字典顺序,你确实可能会发现一些意想不到的结果。
您可以:
- 重构
Tuple
,以便token
是double
(如果要在实例上调用compareTo
,则Double
包装器( - 否则,在
Comparator
中,您可以在String
上调用Double.parseDouble
(这应该是相对安全的,因为String
首先来自double
s(,并在返回的Double
包装器上调用compareTo
。
最后一个选项听起来很丑陋,因为您在Double
和String
之间有一堆看似不必要的来回转换,反之亦然。
这也意味着性能下降,因为在对集合进行排序时,compareTo
将被多次调用。
您可以在Tuple
中将令牌存储为双精度,并实现Comparable
接口。 在getToken
中,您可以返回实际需要的双精度形式的字符串表示。
public class Tuple implements Comparable<Tuple>{
private double token;
private int docID;
public Tuple(double token, int docID) {
this.token = token;
this.docID = docID;
}
public String getToken() {
return String.valueOf(token);
}
public void setToken(double token) {
this.token = token;
}
public int getDocID() {
return docID;
}
public void setDocID(int docID) {
this.docID = docID;
}
@Override
public int compareTo(Tuple o) {
return Double.compare(this.token, o.token);
}
}
如果真的需要将双精度转换为字符串,使用起来更安全
BigDecimal.valueOf(vect[i])).toString();
因为它处理双重不可预测性。
我和弗拉德·博切宁有同样的想法:
您只需实现Comparable
并覆盖compareTo
:
public class Tuple implements Comparable<Tuple> {
public Double token;
public int docID;
public Tuple(final double token, final int docID) {
this.token = token;
this.docID = docID;
}
@Override
public int compareTo(final Tuple o) {
return this.token.compareTo(o.token);
}
}
还有一个单元测试:
public class TestTuple {
@Test
public void testSort() {
final Random r = new Random(System.currentTimeMillis());
final int numberOfDocs = 100;
final ArrayList<Tuple> temp = new ArrayList<Tuple>();
for (int i = 0; i < numberOfDocs; i++) {
temp.add(new Tuple(r.nextDouble(), i));
}
Collections.sort(temp);
Tuple old = temp.get(0);
// test if sorted
for (final Tuple next : temp) {
Assert.assertTrue(next.token >= old.token);
old = next;
}
}
}
您可以将令牌存储为元组中的双精度,并实现可比较接口。 在getToken中,您可以以实际需要的形式返回双精度的字符串表示。
private double token;
private int docID;
public Tuple(double token, int docID) {
this.token = token;
this.docID = docID;
}
public String getToken() {
return String.valueOf(token);
}
public void setToken(double token) {
this.token = token;
}
public int getDocID() {
return docID;
}
public void setDocID(int docID) {
this.docID = docID;
}
@Override
public int compareTo(Tuple o) {
return Double.compare(this.token, o.token);
}
}
查看有关比较的更多信息