0

重複の可能性:
特殊文字列の配列リストを日付でソート

ファイルから読み込む文字列の ArrayList があり、各文字列の最初の部分は日付 ex: 12/01/2012 です。Collections.sort(); を使用する場合 年内は古いものから新しいものへと適切に並べ替えられますが、2013 年 1 月 1 日になると、古いものから順にリストの一番上に表示されます。ソートの一部として年を使用するにはどうすればよいですか? Date を使用してみましたが、同じでした。各文字列には、保持したい多くの情報があり、最初から並べ替えます。コードは機能しているため、コードを投稿する必要はありません。問題があるのは並べ替えだけです。ここでしばらく検索しましたが、いくつかの異なる並べ替えオプションを試してみましたが、役に立ちませんでした。だから私は混乱しているか、何かを忘れているに違いありません。最初に日付を含む文字列をソートする方法を誰かが知っている場合は、助けてください! ありがとう!

文字列の例: "12/01/2012 34023843 アイテム番号"

4

4 に答える 4

1

カスタムコンパレータが必要です。文字列を自然な順序で比較すると (つまり、 がString実装されているという事実を使用してComparable<String>)、表示される結果が得られます。01

これはあなたが望むことを行うことができるクラスの例ですが、すべての日付が正しくフォーマットされていると仮定していることに注意してください(日付が正しくない場合、 のparse()メソッドはDateFormat未チェックをスローしIllegalArgumentExceptionます):

public final class MyComparator
    implements Comparator<String>
{
    // Date parsing
    // Note: SimpleDateFormat is not thread-safe, if possible use Joda Time instead
    private static final DateFormat fmt = new SimpleDateFormat("dd/MM/YYYY");

    private static final Comparator<String> INSTANCE = new MyComparator();

    private MyComparator()
    {
    }

    public static Comparator<String> getInstance()
    {
        return INSTANCE;
    }

    @Override
    public int compare(String o1, String o2)
    {
        // Grab dates
        String s1 = o1.subString(0, 10);
        Date d1 = fmt.parse(s1);
        String s2 = o2.subString(0, 10);
        Date d2 = fmt.parse(s2);

        // Date implements Comparable<Date>, so we can use that...
        int ret = d1.compareTo(d2);

        // If dates are equal, compare the rest of the strings instead.
        return ret != 0 ? ret : o1.subString(10).compareTo(o2.subString(10));
    }
}

その後、使用できますCollections.sort(theArray, MyComparator.getInstance());

于 2013-01-01T23:41:45.633 に答える
1

文字列が常に同じ形式である場合は、カスタムコンパレータを実装して Collections.sort(list, comparison) を使用できます。このコンパレータは、最初に年、次に月、日をチェックします。

または、(最善の解決策です)、複数のフィールド(および日付)を持つオブジェクトのリストを持つように再設計し、日付を使用してコンパレータを実装できます。文字列を直接操作することは決して保存されません (たとえば、ここで文字列のコンパレータを使用すると、他の日付形式を操作できなくなります)

于 2013-01-01T23:36:55.607 に答える
1

現在、文字列順序を使用して並べ替えています。つまり、「0」は「1」より小さいため、「01/01/2013」は「12/31/2012」の前にソートされます。

カスタム コンパレータを使用して、さまざまなロジックを使用できます。コンパレータ内では、次のことを行います。

  1. 文字列を分割して日付を取得するだけです
  2. SimpleDateFormat を使用してフィールド 0 を日付に変換する
  3. 次に、2 つの日付で比較を呼び出します
于 2013-01-01T23:37:46.537 に答える
0

@fgeの答えは機能しますが、コンパレーターは文字列を複数回分割して変換する必要があります。実際、典型的なソート アルゴリズムの場合、これは、リストの長さであるO(NlogN)回数実行する必要があります。N大きなリストの場合、このlogN用語は重要になります。

私の提案はLine、ファイルの行を表すカスタム クラスを作成することです。コンストラクターに行を表す文字列をコンポーネントに解析させ、日付コンポーネントを解析して、関連するすべてのコンポーネントをプライベート フィールドに保持します。カスタム クラスに を実装させ、日付で線を比較するメソッドをComparable<Line>実装します。compareTo(Line)

次に、ファイルの内容をArrayList<Line>ではなくとして表しますArrayList<String>

(とにかく、行を解析する必要がある可能性があります...並べ替えられた後。したがって、このアプローチは、並べ替えの前に解析を行うだけで、一度だけ実行します。FWIW、「複製」の質問カバーへの回答これも:特別な文字列の配列リストを日付で並べ替えます)

于 2013-01-02T00:06:06.687 に答える