如何对二维ArrayList进行排序

时间:2012-04-05 20:22:31

标签: java sorting multidimensional-array arraylist

我有一个包含双值的二维ArrayList:

ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 

与经典数组类似,我想对此矩阵的“cols”进行排序:我想在子ArrayLists中获取具有相同索引的项目,然后对它们进行排序。就像为每列调用Collections.sort()一样...... 按行我的意思是外层和内层是列。

这样做的正确方法是什么? 我想迭代矩阵来反转它然后用Collections.sort()排序每一行?但也许它不是最好的解决方案,因为矩阵大约是400 * 7000。

我不能使用经典数组,因为矩阵的大小是未知的。

感谢您的帮助。

7 个答案:

答案 0 :(得分:3)

做这样的事情:

    final int COLUMN = 5;
    Comparator<ArrayList<Double>> myComparator = new Comparator<ArrayList<Double>>() {
        @Override
        public int compare(ArrayList<Double> o1, ArrayList<Double> o2) {
            return o1.get(COLUMN).compareTo(o2.get(COLUMN));
        }
    };
    Collections.sort(list, myComparator);

将COLUMN设置为您要排序的任何列。

更新

是的,这根本不起作用。

我喜欢ahanin的第二个建议,即制作你自己的List,它包装你原来的List。您还必须包装get()返回的对象,以便变量wrappedList包含列值,wrappedList.get(0)也返回一列值。然后排序可以工作。我想知道你必须实现Collections.sort()在List上工作的最小方法。

最简单的方法就是拿别人的快速排序,让它与你的名单一起使用。

以下是一项实施:http://www.vogella.de/articles/JavaAlgorithmsQuicksort/article.html

答案 1 :(得分:3)

所以这里有一个类似于反转想法的选项,但不是反转整个事情,而是一次构建一个列,对其进行排序,然后丢弃它。

ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 

for(int c=0; c<data.get(0).size(); c++) {
    List<Double> col = new ArrayList<Double>();
    for( int r=0; r<data.size(); r++ )
        col.add( data.get(r).get(c) );

    Collections.sort(col);

    for( int r=0; r<col.size(); r++ )
        data.get(r).set( c, col.get(r) );
}

我怀疑你能否获得更高效的东西,除了可能选择创建你自己的类,它提供表格列的视图作为列表。

答案 2 :(得分:2)

我有两个疯狂的想法:要么实现自己的排序算法,要知道你的倒置矩阵结构,要么写一个Collection的实现,它将包装你的结构并表示列,以后可以用作参数到Collections.sort()。使用ArrayList,这应该相当快。

答案 3 :(得分:2)

这是将数据转换为对象数组的这种情况的方法。将列更改为您喜欢的任何内容。

final int column = 3;
ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 

// Convert data into an object array
Object [] temp = data.toArray();

Arrays.sort(temp, new Comparator<Object>() {
    @Override
    public int compare(Object o1, Object o2) {
        // Get inner arrays to be compared by type-casting
        ArrayList<Double> temp1 = (ArrayList<Double>) o1;
        ArrayList<Double> temp2 = (ArrayList<Double>) o2;

        // Then compare those inner arrays' indexes
        return temp1.get(column).compareTo(temp2.get(column));
    }
});

// Clear the old one and add the ordered list into
data.clear();

for(Object o: temp)
{
    data.add((ArrayList<Double>) o);
}

答案 4 :(得分:0)

我想如果存储不是问题,你可以在ArrayList中使用SortedMap。这样您就不必担心对元素进行排序。

ArrayList<SortedMap<Double,byte>> data;

答案 5 :(得分:0)

不确定我是否正确理解了您的Q,但这会对所有“列”进行排序(假设外层是行,内层是列):

    final ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 
    //...

    final Integer[] rows = new Integer[data.size()];
    for(int i=0;i<rows.length;i++)
        rows[i]=i;

    int cols = data.get(0).size();
    for(int c=0;c<cols;c++)
    {
        final int colidx = c;
        Arrays.sort(rows,new Comparator<Integer>(){
            @Override
            public int compare(Integer arg0,
                    Integer arg1) {
                return data.get(arg0).get(colidx).compareTo(data.get(arg1).get(colidx));        
            }});    

        for(int i=0;i<rows.length;i++)
            data.get(i).add(colidx+1,data.get(rows[i]).get(colidx));
        for(int i=0;i<rows.length;i++)
            data.get(i).remove(colidx);
    }

答案 6 :(得分:0)

您必须访问所有元素才能在任何情况下对它们进行排序。所以你能做的就是这个。

int temp[] = new temp[col.length];
int x = 0;
while(x < row.length)
{
    for(int i = 0; i<col.length; i++)
    {
        temp[i] = mat[x][i];
    }
    sort(temp);
    for(int i = 0; i<col.length; i++)
    {
        mat[x][i] = temp[i];
    }
x++;
}

此处的运行时间为O(n^2logn),但由于您只需要400次双打,不会花费太多时间。因为您必须至少访问矩阵中的每个元素一次,所以不能低于O(n^2)