1

Swing を使用するアプリケーションに取り組んでいます。JTabbedPane があり、各タブは「ページ」と見なされます。各ページには、2x2 GridLayout に従って配置された 4 つの通常のパネル (「ビュー」と呼びます) が含まれています。

ページの量を最小限に抑えたいので、ビューが削除されるたびに、すべてのページのすべてのビューを再ソートして (より理にかなっている場合は 2 次元配列を考えてください)、ビューが最後のページに表示され、そこから削除され、先頭に近いページに追加されます。

次の例を検討してください。

Object[][] array = new Object [][] {

    { new Object(), null, new Object(), new Object() },
    { null, null, new Object(), new Object() },
    { new Object(), new Object(), new Object(), new Object() }

};

その配列を次のように並べ替えるにはどうすればよいですか。

Object[][] array = new Object[][] {

    { new Object(), new Object(), new Object(), new Object() },
    { new Object(), new Object(), new Object(), new Object() },
    { new Object(), null, null, null },

};

array.length最初は、0 から へのループとから 0 へのループの 2 つのループを使用することをarray.length考えました。長さから 0 へのループが 0 に近づくと、配列のインデックスが0からlength までは空です。その場合、null 以外の要素を を含むインデックスに配置しますnull

このアプローチは、すべてのループのために頭が痛くなったので、親しい友人に提案を求めました。彼はもっと洗練された解決策を提案しました: Arrays.sort(Object[][], Comparator).

このコードは結果でした:

    Object[][] array = new Object[][] { { new Object(), null, new Object(), new Object() }, { null, null, new Object(), new Object() }, { new Object(), new Object(), new Object(), new Object() } };

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            System.out.println("Before sorting: (i = " + i + " j = " + j + " null = " + (array[i][j] == null) + ")");
        }
    }

    Arrays.sort(array, new Comparator<Object>()
    {

        public int compare(Object a, Object b)
        {
            return a == null ? (b == null ? 0 : -1) : (b == null ? 1 : 0);
        }

    });

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            System.out.println("After sorting: (i = " + i + " j = " + j + " null = " + (array[i][j] == null) + ")");
        }
    }

出力は次のとおりです。

ソート前: (i = 0 j = 0 null = false)
ソート前: (i = 0 j = 1 null = true)
ソート前: (i = 0 j = 2 null = false)
ソート前: (i = 0 j = 3 null = false)
ソート前: (i = 1 j = 0 null = true)
ソート前: (i = 1 j = 1 null = true)
ソート前: (i = 1 j = 2 null = false)
ソート前: (i = 1 j = 3 null = false)
ソート前: (i = 2 j = 0 null = false)
ソート前: (i = 2 j = 1 null = false)
ソート前: (i = 2 j = 2 null = false)
ソート前: (i = 2 j = 3 null = false)
ソート後: (i = 0 j = 0 null = false)
ソート後: (i = 0 j = 1 null = true)
ソート後: (i = 0 j = 2 null = false)
ソート後: (i = 0 j = 3 null = false)
ソート後: (i = 1 j = 0 null = true)
ソート後: (i = 1 j = 1 null = true)
ソート後: (i = 1 j = 2 null = false)
ソート後: (i = 1 j = 3 null = false)
ソート後: (i = 2 j = 0 null = false)
ソート後: (i = 2 j = 1 null = false)
ソート後: (i = 2 j = 2 null = false)
ソート後: (i = 2 j = 3 null = false)

まったく同じ。compare(Object, Object)また、実装を次のものに置き換えてみました。

        public int compare(Object a, Object b)
        {
            if (a == null && b != null)
            {
                return -1;
            }
            if (b == null && a != null)
            {
                return 1;
            }
            return 0;
        }

...そして同じ結果を達成しました。私はちょっと途方に暮れています。これは私が知識を持っていないということではありません。このような問題の解決策を実際に作成する方法について頭を悩ませることはできません。

助けていただければ幸いです。ループ方式とコンパレータ方式のどちらのアプローチを好む場合でも、ぜひご覧ください。

ありがとう!

4

5 に答える 5

2

もしかして

Object[][] array = new Object [][] { .. };

あなたの場合、2次元配列を配列(1次元配列)に変換する必要があります。新しい配列を並べ替えた後、並べ替えられた配列で 2 次元配列を埋めます。

// convert to 1-D array
Object[] all = new Object[12];
int k = 0;
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 4; j++) {
        all[k++] = array[i][j];
    }
}

// then sort the new array
Arrays.sort(all, yourComparator);

// then fill the 2-D array with the sorted array
k = 0;
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 4; j++) {
        array[i][j] = all[k++];
    }
}
于 2012-05-17T02:41:43.590 に答える
1

あなたの例は不明確であり、実際のアプリケーション要件と明らかに一致しません。Object(未分化のインスタンスの束をソートしても意味がありません!)

だから私は突き刺すつもりです...そしてあなたは本当にヌルを最後に動かそうとしているだけだと思います。(他の非 null 要素は既にソートされており、1 つまたはいくつかを削除してもそれは変更されません。または、ソートする必要がまったくないかもしれません ...)

その場合、簡単な方法は次のとおりです。

  • 適切なサイズの一時的な 1 次元配列を作成する
  • 要素を表示する順序 (列内の行など) で 2 次元配列を繰り返し、null 以外の要素を 1 次元配列にコピーします。
  • 1 次元配列からコピーして、2 次元配列を再度反復します。

または、null 以外の要素を並べ替える必要がある場合は、 を使用して 1 次元配列で並べ替えを行うことができますArrays.sort(Object[], int, int)。配列の末尾にある null を除外する境界を選択します。これにより、 を理解する「複雑な」コンパレーターを作成する必要がなくなりますnull


あなたの現在のアプローチは複雑すぎます...そして不必要に複雑なコードは悪い考えです。

また、他のオブジェクトの順序を維持しながらヌルを最後に移動するだけの場合sortは、コストがかかります。(メソッドは安定したソートを行うと文書化されているComparatorため、定義した で動作します。しかし、この場合、動作するのは残念sort(Object[] ...)だと言いたくなりました。)

于 2012-05-17T03:28:22.837 に答える
1

配列のタイプはObject[][]です。そうするときは、内に保持されているsort(array, theComparator)3 つのそれぞれを配置します。これら 3 つの配列のそれぞれの内容をソートしていません。Object[]array

また、 の 3 つのいずれもObject[]nullarrayではないため、コンパレーターは各比較でゼロを返し、それらObject[]は 内に留まりますarray

したがって、 の 1 次元配列に変換しObject、並べ替えてから、2 次元配列に分割する必要があります。

于 2012-05-17T02:39:40.983 に答える
0

コードに null を含めたくない、null をチェックしたくない、null に出くわしたくない、null にセマンティクスを持たせたくない。

したがって、配列は必要ありません。

さまざまなサイズのコレクションを使用する場合は、配列を使用しないでください。

たとえば、使いやすく、可変サイズで、null を使用する必要がない ArrayList を使用します。

ArrayList から要素 2 を削除すると、次のようになります。

   List <JPanel> al = new ArrayList <JPanel> ();
   al.add (new JPanel ());
   al.add (new JPanel ());
   al.add (new JPanel ());
   al.add (new JPanel ());

   al.remove (1); // 0-based numbering like in Arrays. 

これで、要素 2 と 3 が 1 つ前にずれます。あなたのアレイは今どのくらいですか?

   System.out.println (al.size ()); 

リストにnullがない、nullに対してテストする必要がない、反復?

   for (JPanel jp : al) 
        // do something to every jp.

コードで null を使用しないでください。ただし、禁止してください。

さまざまなサイズのコレクションに配列を使用しないでください。

于 2012-05-17T14:04:07.250 に答える
0

外側の配列がnullかどうかを確認しているだけなので、コードが失敗する理由は、外側の配列の内容も確認する必要があります。

このコードを参照してください:

import java.util.Arrays;
import java.util.Comparator;

public class Test2DArrayComparator {
    public static void main(String[] args) {
        Object[][] array = new Object[][]{
                {new Object(), null, new Object(), new Object()}, 
                {null, null, new Object(), new Object()},
                {new Object(), new Object(), new Object(), new Object()}
                };

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                System.out.println("Before sorting: (i = " + i + " j = " + j + " null = " + (array[i][j] == null) + ")");
            }
        }

        class ArrayComparator implements Comparator<Object>{

            @Override
            public int compare(Object a, Object b) {
                if(a == null && b == null){
                    return 0;
                } else if(a != null && b == null){
                    return 1;
                } else if(a == null && b != null){
                    return -1;
                } else {
                    return checkConents(((Object[])a), ((Object[])b));
                }
            }

        }
        Arrays.sort(array, new ArrayComparator());

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                System.out.println("After sorting: (i = " + i + " j = " + j + " null = " + (array[i][j] == null) + ")");
            }
        }

    }

    static int checkConents(Object[] first, Object[] second){
        for(int iDx = 0; iDx < first.length; iDx++){
            if(first[iDx] != null && second[iDx] == null){
                return -1;
            } else if(first[iDx] == null && second[iDx] == null){
                return 0;
            } else if(first[iDx] == null && second[iDx] != null){
                return 1;
            }
        }
        return -1;
    }
}

checkContent内容を比較するために外側の配列の有効性をチェックした後checkContent、両方の配列が同じサイズであると仮定することにも注意してください。

于 2012-05-17T02:50:56.890 に答える