質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.40%

  • Java

    14788questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1786questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Javaでarraylistを使って任意順のソートをしたい

解決済

回答 5

投稿

  • 評価
  • クリップ 2
  • VIEW 2,751

Erebea

score 5

前提・実現したいこと

CSVを読んで中身を変換、ソートして標準出力をしたい。
CSVの中身は

1
A100,yyyyMMdd,名前
S234,yyyyMMdd,名前


となっていて、頭の数字が1なら降順、0なら昇順にする。
データ欠損、存在しない日、アンパサンドのデータなどのエラーは表示しない。

ソートはIDの1文字目でAEDGSRの順で並べたい。それ以外はエラーになる。

発生している問題・エラーメッセージ

任意順のソートができない

該当のソースコード

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import dateconversion.Mysort;

public class Reader {
public static void main(String args[]) {
// 1行を格納する箱作成
List<Mysort> tmpList = new ArrayList<Mysort>();
File file = new File(args[0]); // CSVデータファイル

if (file.isFile()) {
try (BufferedReader br = Files.newBufferedReader(Paths.get(args[0]), Charset.forName("MS932"))) {
// ファイルオープン
String line;
String retention = null;
int sub1;
String sub2 = null, sub3 = null, addsub = null;
while ((line = br.readLine()) != null) {
Mysort M = new Mysort();
if (line.length() == 1) {
//始めの1行用
retention = line;
} else {
try {
String[] cols = line.split(",");
if (cols.length == 3) {
M.setSub1(cols[0]);
M.setSub2(cols[1]);
M.setSub3(cols[2]);

sub1 = M.getChange1();
sub2 = M.getChange2();
sub3 = M.getChange3();

if (sub1 != 9 && sub2 != null && sub3 != null && cols[0].length() == 4) {
sub3 = cols[2];
//文字列結合
addsub = cols[0] + "," + sub2 + "," + sub3;
// 文字列を格納
//                                 M.add(sub1);

}
}
} catch (NumberFormatException e) {
}
}
}

if (retention.equals("1")) {
// 降順になる
} else if (retention.equals("0")) {
// 昇順になる
}
Collections.sort(tmpList, new Comparator<Mysort>()
public int compare(Mysort mysort1, Mysort mysort2) {
int temp = 0;
if (mysort1.getChange1() > mysort2.getChange1())
temp = -1;
if (mysort1.getChange1() < mysort2.getChange1())
temp = 1;
if (temp == 0) {
temp = mysort1.getChange2().compareTo(mysort2.getChange2());
return temp;
}

for (int i = 0; i < tmpList.size(); i++) {
System.out.println(tmpList.get(i));
}

} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("ファイル指定が間違っています");
System.exit(-1);

}

}
_________________________
package dateconversion;

public class Mysort {

private String sub1;
private String sub2;
private String sub3;

public String getSub1() {
return sub1;
}

public void setSub1(String sub1) {
this.sub1 = sub1;
}

public String getSub2() {
return sub2;
}

public void setSub2(String sub2) {
this.sub2 = sub2;
}

public String getSub3() {
return sub3;
}

public void setSub3(String sub3) {
this.sub3 = sub3;
}

@Override
public String toString() {
return  sub1 + ", " + sub2 + ", " + sub3;
}

public int getChange1() {
int change1;
switch (sub1.substring(0, 1)) {
case "A":
change1 = 1;
break;
case "E":
change1 = 2;
break;
case "D":
change1 = 3;
break;
case "G":
change1 = 4;
break;
case "S":
change1 = 5;
break;
case "R":
change1 = 6;
break;
default:
change1 = 9;
}
return change1;
}

public String getChange2() {
return Converter.conversion(sub2);
}

public String getChange3() {
return Nullchecker.nullchecker(sub3);
}
}
__________________________
package dateconversion;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Mfnumconverter {

public static String mfnumconvertion(String mfnum) {
String sub2 = null;

boolean bo = Nullchecker.isNotEmpty(mfnum);
if (bo == true) {
String num1 = mfnum.substring(0, 1);
String num2 = mfnum;
boolean num3 = Mfnumconverter.isNumberStr(mfnum.substring(1));
if (num1.equals("A") || num1.equals("E") || num1.equals("D") || num1.equals("G") || num1.equals("S")
|| num1.equals("R")) {

if (num2.length() == 4 && num3 == true) {
sub2 = num2;
}
}
return sub2;
}
return sub2;
}

public static boolean isNumberStr(String num3) {
Pattern p = Pattern.compile("^[0-9]+$");
Matcher m = p.matcher(num3);
return m.find();
}

}

試したこと

IDの1文字目を切り取って数字を割り振った

補足情報(言語/FW/ツール等のバージョンなど)

win10 64bit
Java 8
eclipse

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • swordone

    2016/11/11 11:38

    マークダウン記法を使ってください。

    キャンセル

  • swordone

    2016/11/11 11:54 編集

    当方のEclipseに入れてみましたが、コンパイルエラーが多すぎて読めたものじゃありません。最低限コンパイルが通る形にして下さい。あとConverterとかNullCheckerとか謎のクラスが登場していますが、これは何でしょう?

    キャンセル

  • Erebea

    2016/11/11 15:07

    要点を抑えていない質問、わけの分からない状態のプログラムから意図を汲み取って返信してくだりありがとうございます。一応他にもクラスが有り、ConverterはyyyyMMddをyyyyMMdd(E)に変換するクラス、NullChecerはCVSデータの欠損を阻止するためのクラスでした。IDの頭文字の英語を数字に変換し、その数字をデータの最初に来る0or1で昇順、降順の判断、をするというところが試行錯誤するうちにわからなくなってしまっていました。 これらを参考にもう一度作り直してみたいと思います。ありがとうございました。

    キャンセル

  • 退会済みユーザー

    2016/11/21 10:21

    こちらの質問が他のユーザから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 5

+1

ソートはよく使う操作なのでjava(に限らず大抵の言語で)標準ライブラリーに順序付きの列を表現するいくつかのデータ型(配列、List、Stream, ... etc.)に対してソートするメソッドが提供されています。

ソートするには任意の2つの要素の順序を決めることが必要です。アプリケーションによってどういう順序にしたいかは様々なので、ソートを行うライブラリーは「2つのデータの大小比較を行った結果を負、0、正のいずらかの整数で返すComparatorを指定させる」ことで任意の順番のソートを行えるように設計されています。つまり「ソートを実現する」ことは「Comparatorを定義する」問題に帰着します。本件についてちょっと工夫が必要なのは以下の点です。

AEDGSRの順番に並べる

このような「そのままでは大小比較が単純にできないもの」を大小比較するための基本的な考え方は、与えられた'A'なり'E'なりといったデータを、順番を表す数値0, 1, ...へ写像(変換)することです。ありえるデータの種類がごく少数ならswitch文で変換してもよいでしょうし、多いならHashMapなどを使って変換を高速化するなどの方式をとることもあるでしょう。また1文字の場合ならString#indexOfを使うという手もあります。いずれにせよあり得るデータの種類に対して(漏れなく)一意な数値に変換する方法が考えられればよいのです。

ちなみに昇順、降順は要するに順序が逆なだけですからどちらかを表すComparatorCを定義してやりさえすれば、それを用いて-Cを返すもう一つのComparatorを定義するだけで昇順、降順の両方のソートが可能です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/17 16:59

    ちなみにJava8では、昇順、降順いずれかのComparatorを作れば、そのComparatorに対してreversed()を呼び出すだけで逆順のComparatorを作ることが可能です。

    キャンセル

  • 2016/11/20 23:17

    そういえばみたことありましたw;使わないとすぐ忘れちゃいますね。

    キャンセル

checkベストアンサー

0

ややこしい仕様や設計はメイン処理に書かず、オブジェクトにまとめるようにします。
具体的には、データの妥当性の判定(データ欠落、日にち間違いなど)はコンストラクタで、
並び順はComparableを付けてcompateToで判定させます。
(以下コードは動作未検証)

Readerクラス

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Reader {

    public static void main(String args[]) {
        // 1行を格納する箱作成
        List<Mysort> tmpList = new ArrayList<Mysort>();
        File file = new File(args[0]); // CSVデータファイル

        if (!file.isFile()) {
            System.out.println("ファイル指定が間違っています");
            System.exit(-1);
        }
        try (BufferedReader br = Files.newBufferedReader(Paths.get(args[0]), Charset.forName("MS932"))) {
            // ファイルオープン
            String line;
            final boolean acsend = br.readLine().equals("0");
            while ((line = br.readLine()) != null) {
                try {
                    Mysort M = new Mysort(line);
                    tmpList.add(M);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }

            }

            if (acsend) {
                Collections.sort(tmpList);
            } else {
                Collections.sort(tmpList, Collections.reverseOrder());
            }

            for (int i = 0; i < tmpList.size(); i++) {
                System.out.println(tmpList.get(i));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Mysortクラス

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;

public class Mysort implements Comparable<Mysort> {
    private static final String INDEX = "AEDGSR";
    private String id;
    private LocalDate localDate;
    private String name;

    public Mysort(String line) throws IllegalArgumentException {
        String[] ids = line.split(",");
        if (ids.length != 3) {
            throw new IllegalArgumentException("Length of data is invalid: " + line);
        }
        if (Arrays.asList(ids).contains("")) {
            throw new IllegalArgumentException("It has blank data: " + line);
        }
        if (INDEX.indexOf(ids[0].charAt(0)) == -1) {
            throw new IllegalArgumentException("Invalid index: " + line);
        }
        try {
            id = ids[0];
            localDate = LocalDate.parse(ids[1], DateTimeFormatter.BASIC_ISO_DATE);
            name = ids[2];
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("Invalid date: " + line, e);
        }
    }
    // やたら長く書いていた文字と番号の対応は、String#indexOf(char)や配列を使うと楽
    public int getIndex() {
        return INDEX.indexOf(id.charAt(0));
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return name + ", " + localDate + ", " + name;
    }

    @Override
    public int compareTo(Mysort o) {
        int temp = this.getIndex() - o.getIndex();
        if (temp == 0) {
            temp = this.localDate.compareTo(o.localDate);
        }
        return temp;
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

質問者さんの目標が今ひとつ理解できないのですが、

文字列型のArrayListを6個作り、先頭の一文字を判定して、6個のうちどれかに1行の文字列を格納する
全データを処理したら、ファイルの先頭の1/0に従って、望む順に出力する

じゃ、ダメなのでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

以下のコードでできると思います

import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
 import java.util.regex.Matcher;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.ParseException;

class QL{


public static void main(String[] args){

try(BufferedReader br=new BufferedReader(new FileReader("C1.csv"))){
int count=0;
String data=null;
int flag=0;

ArrayList<Data> st=new ArrayList<>();

while((data=br.readLine())!=null){

Data d=new Data();
d.data=data;



if(count==0){

try{
int c=Integer.parseInt(data);

if(c==1)flag=1;
if(c==0)flag=0;
count++;
continue;
}catch(Exception o){}
}

String r[]=data.split(",");

if(r.length!=3){

count++;
continue;
}

DateFormat format=new SimpleDateFormat("yyyyMMdd"); 
format.setLenient(false);

try{
java.util.Date date = format.parse(r[1]); 

}catch(Exception m){
count++;
continue;
}




String regex = "[A|E|D|G|S|R][0-9]";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(data);
if (m.find() ) {

//System.out.println ( m.group().replaceAll("[0-9]","") + " ");
try{
char c=m.group().replaceAll("[0-9]","").charAt(0);

int c2=(int)c;

d.id=c2;
}catch(Exception p2){}

}else{
count++;
continue;
}

st.add(d);
count++;
}

//書き出し

if(flag==0){
Collections.sort(st,new Sorts());
}
if(flag==1){
Collections.sort(st,new Sorts2());
}

for(Data as:st){

System.out.println(as.data);
}

}catch(Exception r){}


}


}



class Data{

Integer id=0;

String data="";


}


class Sorts implements Comparator<Data>{

public int compare(Data d1,Data d2){

return d1.id.compareTo(d2.id);

}


}


class Sorts2 implements Comparator<Data>{

public int compare(Data d1,Data d2){

return d2.id.compareTo(d1.id);

}


}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

Comparatorの定義の問題なのですが、以下のようにすればよいと思います。
(アイデアを見やすくするため、質問者さんのソースとは違います。)

サンプル

package test54773;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Reader {

    public static void main(String args[]) {

        int num = 0; // 1なら降順、0なら昇順にする
        List<String> list = new ArrayList<>(); // CSVのデータ各行

        File file = new File("resource/test54773.txt");
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            // 1行目を読み取る。
            num = Integer.parseInt(br.readLine());
            // 2行目からはデータ
            String line = null;
            while ((line = br.readLine()) != null) {
                list.add(line);
            }
        } catch (FileNotFoundException e) {
            System.out.println("ファイルが存在しません。");
        } catch (IOException e) {
            System.out.println("エラーが発生しました。");
        }

        // 並び替え
        final int caseOfSort = num;
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                char c1 = s1.charAt(0);
                char c2 = s2.charAt(0);
                int value = value(c1) - value(c2);
                return value != 0 ? value : s1.compareTo(s2);
            }

            private int value(char c) {
                int value = 9;
                switch (c) {
                case 'A':
                    value = 1;
                    break;
                case 'E':
                    value = 2;
                    break;
                case 'D':
                    value = 3;
                    break;
                case 'G':
                    value = 4;
                    break;
                case 'S':
                    value = 5;
                    break;
                case 'R':
                    value = 6;
                    break;
                }
                return caseOfSort == 0 ? value : -value;
            }
        });

        // 出力
        for (String s : list) {
            System.out.println(s);
        }

    }
}

出力

S234,yyyyMMdd,名前
E101,yyyyMMdd,名前
A100,yyyyMMdd,名前
A102,yyyyMMdd,名前
A103,yyyyMMdd,名前

test54773.txtの内容

1
A100,yyyyMMdd,名前
S234,yyyyMMdd,名前
E101,yyyyMMdd,名前
A103,yyyyMMdd,名前
A102,yyyyMMdd,名前

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.40%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Java

    14788questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1786questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。