【问题标题】:How do I sort an ArrayList<String> that contains integers?如何对包含整数的 ArrayList<String> 进行排序?
【发布时间】:2019-09-18 12:06:42
【问题描述】:

我创建了一个单词计数器二叉搜索树,当一个单词被多次输入时,它会增加一个单词的计数。单词和单词计数都保存在树中。我正在尝试首先打印最高计数的单词,然后按降序排列。

为了做到这一点,我将 BST 转换为 ArrayList,但现在我似乎无法弄清楚如何通过递减计数顺序对列表进行排序。这是我目前所拥有的:

public ArrayList<String> toArray() {
  ArrayList<String> result = new ArrayList<String>();
  toArrayHelp(root, result);
  Collections.sort(result);
  return result;
}

private void toArrayHelp(Node<String, Integer> node, ArrayList<String> result) {
  if (node == null) {
      return;
  }
  toArrayHelp(node.left, result); 
  result.add("count: " + String.valueOf(node.count) + "/t word: " + node.data); 
  toArrayHelp(node.right, result); 
}

我尝试过 Collections.sort() 但这不是按字符串排序,而是按单词排序。

【问题讨论】:

  • 你可以实现自己的比较器来比较count的值
  • 这篇文章应该对dzone.com/articles/sorting-java-arraylist有帮助
  • 当您将可处理的数据转换为字符串然后尝试对结果进行排序时,您并没有帮自己一个忙,这需要解析字符串。收集到Nodes 的数组,按计数对其进行排序,然后将排序后的列表转换为Strings 的列表。

标签: java arrays sorting arraylist comparator


【解决方案1】:
  • 遍历树,从所有元素生成List&lt;Node&lt;String, Integer&gt;&gt;
  • List进行排序,按节点的int部分排序
  • 以相同的顺序创建一个仅保留字符串的列表

【讨论】:

    【解决方案2】:

    您构建输出字符串的速度太快了:您需要先使用计数作为键对列表进行排序,然后再打印结果。您可以制作一个包含结果的简单包装器:

    public class WordCount implements Comparable<WordCount>{
       private String word;
       private Integer count;
    
       //constructors, getters, setters etc..
    
       @Override
       public int compareTo(WordCount other) {
           return Integer.compare(this.count, other.count);
       }
    
    }
    

    并在遍历树时构造一个List&lt;WordCount&gt; list。完成后,您只需按Collections.sort(list) 对列表进行排序并打印结果。

    【讨论】:

      【解决方案3】:

      1.对于 DESC 顺序,请使用 Collections.sort(result, Collections.reverseOrder());,因为默认排序顺序是 ASC。

      2.确保 count 的字符串表示具有相同的长度。否则,字典顺序假定为 11

      List<String> list = Arrays.asList("11", "1", "2");
      Collections.sort(list, Collections.reverseOrder());
      System.out.println(list); // output: [2, 11, 1]
      

      但如果数字的长度相同,则可以正常工作:

      List<String> list = Arrays.asList("11", "01", "02");
      Collections.sort(list, Collections.reverseOrder());
      System.out.println(list); // output: [11, 02, 01]
      

      如何添加前导零,您可以在此处找到 https://stackoverflow.com/a/275715/4671833。 应该是这样的result.add("count: " + String.format("%02d", String.valueOf(node.count)) + "/t word: " + node.data);

      【讨论】:

        【解决方案4】:

        两个要点:让名称选择和格式成为您的朋友!您需要养成选择简单且富有表现力的变量名称以及保持代码格式整齐的习惯。

        让我们从明确的步骤开始:

        (1) 有一个词数据源,表示为一棵节点树。避免过多的细节,让我们设置节点类型的重要细节,并使用 getter 使节点树可用。

        要提到的一个重要细节是,节点旨在保存在具有不同键值的排序二叉树中,并且任何左节点的值都严格小于该节点的值,并且值任何右节点的值都严格大于该节点的值。这有一个重要的后果,即一个节点的左子树的值都严格小于该节点的值,而右子树的值同样都严格大于该节点的值.

        public class Node<K, V> {
          public K key;
          public V value;
        
          public Node<K, V> left;
          public Node<K, V> right;
        
          public Node(K key, V value) {
            this.key = key;
            this.value = value;
          }
        }
        
        public Node<String, Integer> getRootNode() {
            // Undetailed ...
        }
        

        (2) 需要三个主要操作:将树的节点收集到列表中的操作,对列表进行排序的操作,以及显示排序列表的操作:

        public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
            // Undetailed ...
        }
        
        public void sort(List<Node<String, Integer>> nodes) {
            // Undetailed ...
        }
        
        public void print(List<Node<String, Integer>> nodes) {
            // Undetailed ...
        }
        

        (3) 这适合在一起,例如,如下:

        public void tester() {
          Node<String, Integer> rootNode = getRootNode();
          List<Node<String, Integer>> flatNodes = flatten(rootNode);
          sort(flatNodes);
          print(flatNodes)l
        }
        

        (4)剩下的就是详细介绍几种方法。我们从“扁平化”开始。这将作为递归操作来实现。而且,由于为平面列表传递存储更简单,因此该方法将分为两部分,一部分分配存储,另一部分进行递归处理。这种传递存储集合的技术是此类处理的典型。

        'flatten' 利用节点的排序属性相对于节点的左节点和节点的右节点:'flatten' 将左子树的所有值添加到平面节点列表中,然后是节点, 后跟右子树的所有值。

        public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
            List<Node<String, Integer>> flatNodes = new ArrayList<Node<String, Integer>>();
            flatten(rootNode, flatNodes);
            return flatNodes;
        }
        
        public void flatten(Node<String, Integer> node, List<Node<String, Integer>> flatNodes) {
           if ( node == null ) {
               return;
           }
           flatten(node.left, flatNodes);
           flatNodes.add(node);
           flatten(node.right, flatNodes);
        }
        

        (5) 以清晰为代价,可以通过移动空检查来提高效率。对于完全平衡的树,这将避免大约 2/3 的递归调用,这是相当不错的减少。这仅在节点数量很高的情况下才重要。无论如何,一个好的编译器很可能会以这种方式转换代码。

        public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
            List<Node<String, Integer>> flatNodes = new ArrayList<Node<String, Integer>>();
            if ( rootNode != null ) {
                flatten(rootNode, flatNodes);
            }
            return flatNodes;
        }
        
        public void flatten(Node<String, Integer> node, List<Node<String, Integer>> flatNodes) {
            Node<String, Integer> leftNode = node.left;
            if ( leftNode != null ) {
                flatten(leftNode, flatNodes);
            }
        
            flatNodes.add(node);
        
            Node<String, Integer> rightNode = node.right;
            if ( rightNode != null ) {
                flatten(rightNode, flatNodes);
            }
        }
        

        (6) 下一位是对平面节点列表进行排序。提出了两种实现,一种使用 lambdas 的更现代的实现,另一种使用显式比较器的旧式实现。编写比较以生成从最小到最大排序的列表。要反转排序顺序,请交换比较顺序。

        public void sort(List<Node<String, Integer>> nodes) {
            Collections.sort(
                nodes,
                ((Node<String, Integer> n1, Node<String, Integer> n2) -> Integer.compare(n1.value, n2.value)) );
        }
        
        public static final Comparator<Node<String, Integer>> NODE_COMPARATOR = 
            new Comparator<Node<String, Integer>>() {
                public int compare(Node<String, Integer> n1, Node<String, Integer> n2) {
                    return Integer.compare(n1.value, n2.value);
                }
            };
        
        public void sort(List<Node<String, Integer>> nodes) {
            Collections.sort(nodes, NODE_COMPARATOR);
        }
        

        (7) 打印生成的排序列表留作练习。

        【讨论】:

          猜你喜欢
          • 2014-03-01
          • 2017-02-24
          • 2016-08-28
          • 2012-03-24
          • 2020-12-12
          • 2017-03-08
          • 1970-01-01
          • 2011-03-11
          • 2013-09-09
          相关资源
          最近更新 更多