【问题标题】:Sorting List of lists/ Arraylists/ Hashmaps with multiple values in Java在Java中对具有多个值的列表/数组列表/哈希图进行排序
【发布时间】:2016-07-02 04:02:06
【问题描述】:

我想在 Java 中创建一个类似表的结构,如图所示

表结构 虽然我不是 Java 专家,但我尝试使用 Arraylist 结构来实现它,如下所示:

List<List<Double>> dataList = new ArrayList<List<Double>>();
for(int x = 0; x < n; x++){
    List<Double> tempList = new ArrayList<Double>();
    dataList.add(tempList);
}

for(int y = 0; y < n; y++){
    double execution = exectime[y];
    double cost= cost[y];
    dataList.get(y).add(execution);
    dataList.get(y).add(cost);
}

for (int z=0;z<dataList.size();z++) {
    Double v1=dataList.get(z).get(0);
    Double v2=dataList.get(z).get(1);

    System.out.println("ID"+z +" Execution time:" + v1 + "cost: " + v2);
}

“n”、“exectime[n]”和“cost[n]”的值将从文件中读取,“n”是需要创建的“id”总数。

创建表后,我想根据“执行时间”值和“成本”值对其进行排序,包括升序和降序。请在这方面帮助我。

【问题讨论】:

  • 请先查看 StackOverflow 用户所做的编辑。
  • 您是否尝试过使用Comparetor 类对自定义类进行排序?如果是这样,那么只有我会帮助你。 @Nilotpal
  • @VikrantKashyap 我用过一点。 Comparator.sort() 方法
  • 那里有什么困惑??它非常容易,您可以浏览 Internet 上的各种示例。谢谢

标签: java sorting arraylist hashmap


【解决方案1】:

@snovelli 关于使用类封装数据的回答是一个好点。

如果您使用的是 Java 8,则可以轻松创建和链接使用访问器的比较器。

为了对对象列表进行排序,它可能类似于:

List<ExecutionTimeData> dataList = new ArrayList<>();
dataList.sort(Comparator
    .comparing(ExecutionTimeData::getExecutionTime)
    .thenComparing(ExecutionTimeData::getCost));

按执行时间排序,后跟成本。

如果你真的想的话,你也可以使用它来对List&lt;List&lt;Double&gt;&gt; 进行排序。

List<List<Double>> doubleListList = new ArrayList<>();
doubleListList.sort(Comparator
    .comparing((List<Double> l) -> l.get(0))
    .thenComparing(l -> l.get(1)));

按列表的元素 0 排序,后跟元素 1。

或者逆序排序:

List<ExecutionTimeData> dataList = new ArrayList<>();
dataList.sort(Comparator
    .comparing(ExecutionTimeData::getExecutionTime).reversed()
    .thenComparing(ExecutionTimeData::getCost).reversed());

【讨论】:

    【解决方案2】:

    使用Collections.sort() with Comparator

    但是,您将丢失您的ID 信息,因为它基于您的 ArrayList 索引。因此,如果您使用此方法并想保留您的 ID 信息,您需要将add() ID 加入到您的 ArrayList 中,就像 executioncost 一样。

    Comparator<List<Double>> ORDER = new Comparator<List<Double>>() {
        @Override
        public int compare(List<Double> lhs, List<Double> rhs) {
            if (lhs.get(1) < rhs.get(1)) return -1;
            if (lhs.get(1) == rhs.get(1)) return 0;
            return 1;
        }
    };
    
    Collections.sort(dataList, ORDER);
    

    在上面的代码中,您的 dataList 将使用 cost 排序,因为它位于 ArrayList 的索引 1 处。

    但是,更好的方法(在可读性方面)是将列放入一个类中,而不仅仅是一个 ArrayList。例如,您可以这样创建一个类:

    class Information {
        private int id;
        private double execution;
        private double cost;
    
        Information(int id, double execution, double cost) {
            this.id = id;
            this.execution = execution;
            this.cost = cost;
        }
    }
    

    并在该类中实现静态比较器。它将提高代码的可读性。

    【讨论】:

      【解决方案3】:

      我认为您应该使用链式Comparator 来使用多个属性来实现sorting。因为如果单独使用一个Comparator,它会按照自己的Compare()方法实现对数据进行排序。

      最好使用 Chained Comparator,它可以根据多个属性对您的数据进行排序...尝试以下链接 ==> Sorting a list by multiple attributes example

      【讨论】:

      • No appriciation.. 如果它帮助您接受这个作为答案或对此的任何赞成或反对票。谢谢@NilotpalChakraborty
      【解决方案4】:
      • 使用集合作为列表,RegisterType是根据表中存在的寄存器类型创建的(例如:具有3个双属性)
      • 实现 Comparator 接口 Comparator
      • 以您想要的方式覆盖 compare(RegisterType o1, RegisterType o2) 方法(定义如何对 RegisterType 类型的 2 个元素进行排序)
      • Inkove Collections.sort(List list, ComparatorClass)

      然后您的收藏列表将按照您想要的方式排序。

      【讨论】:

        【解决方案5】:

        表格是表示对象列表的一种方式,那为什么不使用对象列表呢?

        我认为您希望拥有一个可以定义为的类的 SortedSet

        public class ExecutionTimeData{
        
            private final long id;
            private final long executionTime;
            private final int cost;
        
            public ExecutionTimeData(long id, long executionTime, int cost){
                 this.id = id;
                 this.executionTime = executionTime;
                 this.cost = cost;
            }        
        
            /* Getters */      
           
        }
        

        然后你将简单地有一个未排序的列表,如

        List<ExecutionTimeData> unsortedList = new ArrayList<>();
        

        正如@VikrantKashyap 所指出的那样,要对具有价值和成本的列表进行排序,您必须实现Chained Comparator

        public class ExecutionTimeDataChainedComparator implements Comparator<ExecutionTimeData> {
         
            private List<Comparator<ExecutionTimeData>> listComparators;
         
            @SafeVarargs
            public ExecutionTimeDataChainedComparator (Comparator<ExecutionTimeData>... comparators) {
                this.listComparators = Arrays.asList(comparators);
            }
         
            @Override
            public int compare(ExecutionTimeData etd1, ExecutionTimeData etd2) {
                for (Comparator<ExecutionTimeData> comparator : listComparators) {
                    int result = comparator.compare(etd1, etd2);
                    if (result != 0) {
                        return result;
                    }
                }
                return 0;
            }
        }
        

        并像这样实现比较器

        public class ExecutionTimeDataCostComparator implements Comparator<ExecutionTimeData > {
         
            @Override
            public int compare(ExecutionTimeData a, ExecutionTimeData b) {
               return b.getCost() > a.getCost()?-1:1;
            }
        }
        
        public class ExecutionTimeDataExecutionComparator implements Comparator<ExecutionTimeData > {
         
            @Override
            public int compare(ExecutionTimeData a, ExecutionTimeData b) {
               return b.getExecutionTime() > a.getExecutionTime()?-1:1;
            }
        }
        

        当然,您可以通过实例化提供ASCENDINGDESCENDING 顺序的比较器找到一种简单的方法来反转顺序

        【讨论】:

        • 您提供的解决方案不适用于 Chained Comaparator 。它是个人Comparator 实现。所以它总是单独排序而不是链式。谢谢
        • 所以,请删除你的答案。如果他尝试这个解决方案,它真的很困扰所有者。请删除此。 @snovelli
        猜你喜欢
        • 1970-01-01
        • 2017-05-30
        • 2017-12-13
        • 2019-01-29
        • 2017-12-13
        • 1970-01-01
        • 1970-01-01
        • 2017-02-17
        • 1970-01-01
        相关资源
        最近更新 更多