【问题标题】:Java Collections.sort() not sortingJava Collections.sort() 不排序
【发布时间】:2018-10-11 19:46:24
【问题描述】:

我在使用 Java 的内置 Collections.sort() 方法时遇到问题。我正在尝试对名为 TreeNode 的自定义对象类型的 ArrayList 进行排序。我过去曾成功地使用过这种方法,并且想从外面看看我是否遗漏了任何明显的东西。

我想对这些 TreeNode 对象进行排序的方式是通过一个整数字段,它们都称为 myWeight,一个整数表示特定字符​​在文本文件中出现的次数。在我的项目中,我使用了一个名为 TreeNode 的自定义类以及该类的两个子类,名为 InternalNode 和 LeafNode。这些节点用于构建用于编码文本文件的 Huffman 树。我已经确保所有这些都实现了 Comparable 并且我尝试了只有具有 compareTo() 方法的父 TreeNode 类的变体,让它们都具有相同的 compareTo() 方法,我已经放弃了 compareTo()实现改为在其中使用 Integer.compare() 方法,但没有骰子。

我也尝试过使用比较器并将其作为 Collections.sort() 方法的参数传递,但也没有任何改变。

这是我试图调用排序并显示结果的地方:

        private void generateHuffmanTreeTest(final HashMap<Character, Integer> theMap) {
            ArrayList<TreeNode> sortedList = new ArrayList<TreeNode>();
            System.out.println("Generating the Huffman Tree with new logic...");

            for (Map.Entry<Character, Integer> entry : theMap.entrySet()) {
                sortedList.add(new LeafNode(entry.getKey(), entry.getValue()));
            }

            Collections.sort(sortedList);
            for (int i = 0; i < sortedList.size(); i++) {
        LeafNode n = (LeafNode) sortedList.get(i);
        System.out.println(n.myData + " " + n.myWeight);
    }

以下是我尝试比较的对象类。

    public class TreeNode implements Comparable<TreeNode> {

    /** Left child of this node. */
    public TreeNode myLeft;

    /** Right child of this node. */
    public TreeNode myRight;

    /** 
     * Weight of all nodes branching from this one, or the weight
     * of just this node if this node is a leaf.
     */
    public int myWeight;

    /**
     * Default constructor. Should not be used to create pure 
     * TreeNode objects.
     * No TreeNodes should be constructed, only InternalNodes
     * and LeafNodes should comprise the tree.
     */
    public TreeNode() {

    }



    /**
     * Sets the left child of this node.
     * 
     * @param theNode The node to become the left child.
     */
    public void setLeft(final TreeNode theNode) {
        myLeft = theNode;
    }

    /**
     * Sets the right child of this node.
     * 
     * @param theNode The node to become the right child.
     */
    public void setRight(final TreeNode theNode) {
        myRight = theNode;
    }

    /**
     * Compares two TreeNodes based on their myWeight field.
     */
    @Override
    public int compareTo(TreeNode theOther) {
        int result = 0;

        if (myWeight < theOther.myWeight) result = -1;
        if (myWeight > theOther.myWeight) result = 1;

        return result;
    }

}

    public class InternalNode extends TreeNode implements Comparable<TreeNode> {

    /**
     * Creates a new InternalNode.
     */
    public InternalNode() {
        super();

    }

    /**
     * Calculates the weight of both children from this Node.
     */
    public void calcWeight() {
        int result = 0;

        if (myLeft != null) result = result + myLeft.myWeight;
        if (myRight != null) result = result + myRight.myWeight;

        myWeight = result;
    }

    /**
     * Sets the left child of this node.
     * 
     * @param theNode The child to be set.
     */
    public void setLeft(final TreeNode theNode) {
        myLeft = theNode;

    }

    /**
     * Sets the right child of this node.
     * 
     * @param theNode The child to be set.
     */
    public void setRight(final TreeNode theNode) {
        myRight = theNode;

    }

    /**
     * Compares two TreeNodes based on their myWeight field.
     */
    @Override
    public int compareTo(TreeNode theOther) {
        int result = 0;

        if (myWeight < theOther.myWeight) result = -1;
        if (myWeight > theOther.myWeight) result = 1;

        return result;
    }
}

    public class LeafNode extends TreeNode implements Comparable<TreeNode> {

    /** Char value for this node to hold. */
    public char myData;

    /** Weight value of the char this node holds. */
    public int myWeight;

    /**
     * Creates a new LeafNode that contains a char value for it to 
     * hold as well as a weight value that is equal to the number
     * of times that character appears in the target String.
     * 
     * @param theData The char value for this node to hold.
     * @param theWeight The frequency of the char value in the text.
     */
    public LeafNode(final char theData, final int theWeight) {
        super();
        myData = theData;
        myWeight = theWeight;

    }

    /**
     * Compares two TreeNodes based on their myWeight field.
     */
    @Override
    public int compareTo(TreeNode theOther) {
        int result = 0;

        if (myWeight < theOther.myWeight) result = -1;
        if (myWeight > theOther.myWeight) result = 1;

        return result;
    }
}

编辑*** 是的,如果我也发布这个东西的输出可能会有所帮助。 这是我从阅读的文本文件中运行此代码时得到的结果:

 65007
  514908
! 3923
" 17970
# 1
$ 2
% 1
' 7529
( 670
) 670
* 300
, 39891
- 6308
. 30806
/ 29
0 179
1 392
2 147
3 61
4 23
5 55
6 57
7 40
8 193
9 35
: 1014
; 1145
= 2
? 3137
@ 2
A 6574
B 3606
C 2105
D 2017
E 2259
F 1946
G 1303
H 4378
I 7931
J 308
K 1201
L 713
M 3251
N 3614
O 1635
P 6519
Q 35
R 3057
S 2986
T 6817
U 254
V 1116
W 2888
X 673
Y 1265
Z 108
[ 1
] 1
à 4
a 199232
b 31052
c 59518
d 116273
ä 1
e 312974
f 52950
g 50023
h 163026
i 166350
é 1
j 2266
ê 11
k 19230
l 95814
m 58395
n 180559
o 191244
p 39014
q 2295
r 145371
s 159905
t 219589
u 65180
v 25970
w 56319
x 3711
y 45000
z 2280
 1

【问题讨论】:

  • 输出在哪里?它只是您问题中的最后一行 1 吗?此外,您的比较 impl 可以只是 return this.myWeight - theOther.myWeight;
  • 嗨@SomeDude 我忘了在我的原始帖子中包含输出。它现在应该在那里。正如你所看到的,它只是以某种默认顺序打印列表的内容,我假设它是 ASCII 顺序或类似的效果。

标签: java list sorting


【解决方案1】:

您遇到的问题是您在TreeNodeLeafNode 中都定义了myWeight。因此,compareTo 方法使用的myWeight 变量可能与LeafNode 构造函数写入的变量和打印LeafNode.myWeight 时写出的变量不同。

您可能只想从LeafNode 中删除myWeight 的重复定义。

请参阅此处的变量隐藏部分:https://dzone.com/articles/variable-shadowing-and-hiding-in-java

【讨论】:

  • 这是我的问题。错误地在 LeafNode 及其父 TreeNode 中声明了该变量,因此当我在列表中调用 Collections.sort() 时,它在所有这些节点上看到的 myWeight 值为 0,将它们全部保留。
【解决方案2】:

您可以使用Comparator&lt;TreeNode&gt;。这样,如果您向TreeNode 类添加了一个字段,您只需实现一个不同的比较器并将其传递给Collections.sort() 方法。但是,默认情况下,如果您仍希望它们为 Comparable,则可以使用默认的 compareTo() 方法:

输出:

[1, 5, 6, 0, 1, 0, 8, 3, 7, 4]
[0, 0, 1, 1, 3, 4, 5, 6, 7, 8]

树节点:

public static class TreeNode implements Comparable<TreeNode> {

  public TreeNode(int weight) {
    this.myWeight = weight;
  }

  public int myWeight;

  public String toString() {

  return "" + myWeight;
}

@Override
public int compareTo(TreeNode o) {

  int val = 0;

    if (myWeight > o.myWeight) {
      val = 1;

    } else if (myWeight < o.myWeight){

      val = -1;
    }


    return val;
  }
}

比较器,用于排序:

public static class TreeNodeComparator implements Comparator<TreeNode> {

  // Sorts by default `compareTo()`, You can always change this
  // If you want to sort by another property
  @Override
  public int compare(TreeNode o1, TreeNode o2) {

    return o1.compareTo(o2);
  }
}

主要:

public static void main(String[] args) throws Exception {


  java.util.ArrayList<TreeNode> nodes = new java.util.ArrayList<>();

  for (int i = 10; i > 0; i--) {

    int val = ThreadLocalRandom.current().nextInt(0, 10);

    TreeNode node = new TreeNode(val);

    nodes.add(node);

  }

  System.out.println(nodes);

  Collections.sort(nodes, new TreeNodeComparator());


  System.out.println(nodes);
}

【讨论】:

    【解决方案3】:

    您可以创建一个实现Comparator 接口的单独类,并像这样覆盖compare 方法:

    public class SortByWeight implements Comparator<TreeNode> {
    
    
    @Override
    public int compare(TreeNode o1, TreeNode o2) {
    return o1.myWeight - o2.myWeight;
    }
    }
    

    然后在方法中进行比较时,创建一个新的比较器实例。

     ArrayList<TreeNode> sortedList = new ArrayList<TreeNode>();
        System.out.println("Generating the Huffman Tree with new logic...");
    
        TreeNode t = new TreeNode();
        t.myWeight = 2;
    
        TreeNode r = new TreeNode();
        r.myWeight = 5;
    
        TreeNode q = new TreeNode();
        q.myWeight = 1;
    
        sortedList.add(t);
        sortedList.add(r);
        sortedList.add(q);
    
         //new comparator here
        Collections.sort(sortedList, new SortByWeight());
    
        for (int i = 0; i < sortedList.size(); i++) {
            System.out.println(sortedList.get(i).myWeight);
        }
    

    这个的输出是

    1
    2
    5
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2019-03-06
      • 2012-07-15
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      相关资源
      最近更新 更多