20200204のJavaに関する記事は9件です。

Javaの名前を変更するExcelシートとセットTabの色

この記事では、Spire.XLS for javaを使用して、ワークシートの名前を変更し、Javaアプリケーションのシートのタブカラーを設定する方法を紹介します。
使用ツール:Free Spire.XLS for Java (無料版)
Jarファイルの取得と導入:

Method 1:ホームページを通じてjarファイルのカバンをダウンロードします。ダウンロード後、ファイルを解凍して、libフォルダの下のSpire.xls.jarファイルをJavaプログラムに導入します。

Method 2:maven倉庫設置による導入。

import com.spire.xls.*;
import java.awt.*;

public class RenameSheetandSetTabColor {
    public static void main(String[] args) {

        // Excelドキュメントを読み込む
        Workbook workbook = new Workbook();
        workbook.loadFromFile("Sample.xlsx");

        //最初のワークシートの新しいワークシート名とタブの色を設定する
        Worksheet worksheet = workbook.getWorksheets().get(0);
        worksheet.setName("Rename1");
        worksheet.setTabColor(Color.red);

        //番目のシートの名前とタブの色を設定する
        worksheet = workbook.getWorksheets().get(1);
        worksheet.setName("Rename2");
        worksheet.setTabColor(Color.green);

        //サードシートの名前とタブの色を設定する
        worksheet = workbook.getWorksheets().get(2);
        worksheet.setName("Rename3");
        worksheet.setTabColor(Color.blue);

        // ドキュメントをファイルに保存する
        workbook.saveToFile("output/Result.xlsx", ExcelVersion.Version2010);
    }
}

効果図:
Rename the worksheet and set tab color.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaからGoogleスプレッドシートを操作する

新しいシートの追加

final String spreadsheetId = "my spreadsheetId";

List<Request> requests = new ArrayList<>();
SheetProperties sheetProperties = new SheetProperties().setTitle("New Sheet");
requests.add(new Request().setAddSheet(new AddSheetRequest().setProperties(sheetProperties)));

BatchUpdateSpreadsheetRequest requestBody = new BatchUpdateSpreadsheetRequest();
requestBody.setRequests(requests);

Sheets.Spreadsheets.BatchUpdate request = service.spreadsheets().batchUpdate(spreadsheetId, requestBody);

BatchUpdateSpreadsheetResponse response = request.execute();
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swing】JFrameクラスについて

(JFrameのクラス階層)

java.lang.Object
→java.awt.Component
→→java.awt.Container
→→→java.awt.Window
→→→→java.awt.Frame
→→→→→javax.swing.JFrame

(JFrameクラスのコンストラクタ)

JFrame()
//初期状態が不可視な新しいフレームを構築する
JFrame(GraphicsConfiguration gc)
//画面デバイスで指定されたGraphicsConfigurationと空のタイトルでFrameを作成
JFrame(String title)
//指定されたタイトルを使用して、初期状態で不可視な新しいFrameを作成
JFrame(String title, GraphicsConfiguration gc)
//指定されたタイトルと画面デバイスの指定されたGraphicsConfigurationで、JFrameを作成します。

→主に使うのは一番目と三番目のコンストラクタ
→使用例

import javax.swing.JFrame;

class Sample{
  public static void main(String args[]){
    JFrame frame = new JFrame("MyTitle");
  }
}

(メソッド)

public void setVisible(boolean b)
//引数がtrueならフレームを表示
public void setTitle(String title)
//引数にタイトルをセット
public void setSize(int width, int height)
//引数でフレームの広さ、高さを定義
public void setLocation(int x, int y)
//引数でフレームの位置を定義
public void setLocationRelativeTo(null);
//引数nullでフレームの位置が中央
public void setBounds(int x, int y, int width, int height)
//引数でフレームの位置と広さ高さを定義
public void setDefaultCloseOperation(int operation)
//引数にJFrame.EXIT_ON_CLOSEで×ボタンでフレームを終了

(JFrameクラスを継承したサブクラス)

→フレームに対して独自のメソッドなどを追加したい場合はJFrameクラスを継承したサブクラスを定義する
→フレームのサイズや位置などの初期化処理はサブクラスのコンストラクタ内で行う

import javax.swing.JFrame;

//JFrameを継承
class JSample5_1 extends JFrame{
  public static void main(String args[]){
    JSample5_1 frame = new JSample5_1("MyTitle");
    frame.setVisible(true);
  }

//コンストラクタ
  JSample5_1(String title){
    setTitle(title);
    setBounds(100, 100, 600, 400);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}

(ペインの取得とコンポーネント)

→コンポーネントを追加するには
→フレームからペイン(pane)を取得しペインにコンポーネントを追加する
→ペイン(pane)とはそれぞれ異なる目的のためにフレームに定義されているもの

(ContentPane)

→ContentPaneを取得するためにはJFrameクラスのgetContentPaneメソッドを使う

import javax.swing.JFrame;
import java.awt.Container;

class Sample extends JFrame{
  public static void main(String args[]){
  }

  Sample(String title){
    Container contentPane = getContentPane();//ContentPaneの取得
  }
}

→ContentPaneに対してのコンポーネントの追加
→Containerクラスで定義されているaddメソッドを使う

public void add(Component comp, Object constraints)
//一番目の引数はコンポーネントのオブジェクト
//二番目の引数は追加する位置

→レイアウトマネージャー:コンポーネントをどうするか
→レイアウトマネージャーは複数種類ある

//東西南北中の位置を指定するレイアウトマネージャー
BorderLayout.NORTH
BorderLayout.SOUTH
BorderLayout.EAST
BorderLayout.WEST
BorderLayout.CENTER

(ボタン追加)

import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Container;
import java.awt.BorderLayout;

class Sample extends JFrame{
    public static void main(String[] args){
    JFrame frame = new JFrame();
        JButton btn = new JButton("aaaa");

    Container contentPane = frame.getContentPane();
    contentPane.add(btn, BorderLayout.NORTH);

    frame.setBounds(100, 100, 600, 400);
    frame.setTitle("MyTitle");
        frame.setVisible(true);
    }

}

(出力結果)
image.png

(ContentPaneの取得の省略)

→新しい環境なら自動でContentPaneを取得してくれるため省略可能

import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Container;
import java.awt.BorderLayout;

class Sample extends JFrame{
    public static void main(String[] args){
    JFrame frame = new JFrame();
        JButton btn = new JButton("aaaa");

    frame.add(btn, BorderLayout.NORTH);

    frame.setBounds(100, 100, 600, 400);
    frame.setTitle("MyTitle");
        frame.setVisible(true);
    }

}

(出力結果)
image.png

(レイアウトマネージャーの設定)

→フレームでレイアウトマネージャーを設定するにはContentPaneを取得しペインに対して設定する

public void setLayout(LayoutManager mgr)
//レイアウトマネージャーを設定する
//使用例
import javax.swing.JFrame;
import java.awt.FlowLayout;

class Sample extends JFrame{
  public static void main(String args[]){
  }

  Sample(String title){
    Container contentPane = getContentPane();
    contentPane.setLayout(new FlowLayout());
  }
}

※現在はContentPaneを取得しなくてもJFrameクラスのsetLayoutメソッドで自動的にContentPaneに設定される

public void setLayout(LayoutManager manager)
//レイアウトマネージャーを設定する
//使用例
import javax.swing.JFrame;
import java.awt.FlowLayout;

class Sample extends JFrame{
  public static void main(String args[]){
  }

  Sample(String title){
    setLayout(new FlowLayout());
  }
}
(背景色)
public void setBackground(Color bg)
//引数はColorクラスのものを使う
//例:「Color.GREEN」
(アイコン画像)
public void setIconImage(Image image)
//Imaginationクラスをインスタンス化し、画像のパスを引数に渡す
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】正規表現でズンドコキヨシ

流行ったよね、ズンドコ

完全に時期を逃しているのですが、流行ったときに書いて放置してたソースが出てきたので、投稿します。
Javaでは余りこのパターンは見かけなかった感ある。

元ネタはこれ。


ソース

ZunDokoKiyoshi.java
import java.util.Random;

public class ZunDokoKiyoshi {
    public static void main (String args[]) {
        Random random = new Random(0);
        StringBuilder sb = new StringBuilder("");
        while (!sb.toString().matches("^.*(ズン){4}ドコ$")) {
            String current = new String[]{"ズン", "ドコ"}[random.nextInt(2)];
            System.out.println(current);
            sb.append(current);
        }
        System.out.println("キ・ヨ・シ!");
    }
}

解説

  1. while文内で「ズン」か「ドコ」をランダムに出力
  2. while文内で出力した文字をStringBuilderで溜め込む
  3. while文の終了条件は「末尾が「ズン」連続4回の直後に「ドコ」」である(正規表現でチェック)
  4. while文抜けてから「キ・ヨ・シ!」を出力して〆

真っ先に思い付いたのがコレ、だった記憶。
ビット演算とかstreamとか難しいことはわがんねから、素直に自分の得意なのでやった。
StringBuilder使うなら逐次System.out.printlnしなくてもいい気はする。
でもそうするとあとから改行入れるの面倒になるから逐次にした。
改行入れなくていいんならStringBuilderに全文溜め込むほうがきれいかもだ。

追記

別に溜め込む方式も面倒くさくなかったわ。
改行をStringBuilderに溜め込むときに追加するパターンの場合、改行を含む正規表現になっちゃう。
その場合は、while文の終了判定時にsb.toString().replaceAll("\n", "")にするほうがいいと思う。

public static void main (String args[]) {
    Random random = new Random(0);
    StringBuilder sb = new StringBuilder("");
    while (!sb.toString().matches("^.*(ズン){4}ドコ$")) {
        sb.append(new String[]{"ズン", "ドコ"}[random.nextInt(2)]);
    }
    System.out.println(sb.toString().replaceAll("(.{2})", "$1\n") + "キ・ヨ・シ!");
}

今更気付いたんだけど、「ズン」「ドコ」5つの組み合わせの配列単位で出力すべきだった…?
まあそれにしても出力方法の違いなのでロジックの根本は変わらんけど。
2重ループにしてwhileの内側に5回配列作る分のループ突っ込んで、while文の終了判定がその配列をStringUtilsだったかArrayUtilsのjoinでつなげて正規表現で…って感じになるかな。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

オブジェクト指向を「英文」とみなそうとするともやもやが残る理由

0. 結論

他動詞と自動詞を区別しよう。ただそれだけ。

1. 導入

 オブジェクト指向による適度に可読化されたコードが、英文とみなせるということを聞いたことのある方は多いだろう。具体的にコードを英文として読むためには、次のように読む。

oop↔eng
主語.述語();//第1文型
主語.述語(補語);//第2文型
主語.述語(目的語);//第3文型
主語.述語(目的語, 目的語);//第4文型
主語.述語(目的語, 補語);//第5文型

2. 問題

2-1. 分かりやすい問題

 しかし、述語(動詞)の種類によっては、「主語」が本当に「主語」なのか疑わしくなってしまう時がある。
例えば、javaのList(知らない方向けに説明すると、配列のようなもの)では
list.add(obj);
のような書き方ができる。
このコードではListのインスタンスlistobjを追加するということである。
決してlist「が」(どこかへ)objを追加するわけではないのだ。
そのため英文では「JVM adds list obj.」となってしまい、listは主語でなくなってしまう。
英文的な正しさを追求するなら「JVM adds list obj.」も誤り。addは第4文型をとらないので、素直に「JVM adds obj to list.」と、修飾語付きの第3文型で書くべきである。但し、これは自然言語的な問題であり、人工言語への統一的な変換規則を考える上では相応しくない。そのため今後もすべての他動詞において、第4文型や第5文型に対応するものとみなす。

2-2. 実際上の大問題

 2-1節の問題をなあなあにすると、アクセッサが180度入れ替わってしまう大問題に発展する。すなわちgetterはsetterに、setterはgetterになってしまう。
例えば
フィールドram
およびそのアクセッサ
getRam(int address),
setRam(int address, byte value)
を持つクラス
OS
を用意し、そのインスタンス
computer
を作ったとしよう。

OSクラスとcomputerインスタンス
public class OS
{
    private byte[] ram;
    public byte getRam(int address){return this.ram[address];}
    public void setRam(int address, byte value){this.ram[address]=value;}
    public OS(int ram_size){this.ram = new byte[ram_size];}
}

class Main{ public static void main(String...args)
{
    OS computer = new OS(64);//64byteのRAMを持つコンピュータの作成
    int i=0;
    for(char each_char : "hello world".toCharArray())
        computer.setRam(i++, (byte)each_char);
        //0~10番地に「hello world」を書き込む

    for(int j=0; j<11; j++)
        System.out.print((char)computer.getRam(j));
        //0~10番地を(charとして)表示
        //→コンソールに「hello world」と表示される。
}}

このようにして、(何の役にも立たない)自作OSを定義し、そのOSの入った(何の役にも立たたない)仮想computerを作り、hello worldと表示させることに成功する。

ここで、

oop
    int i=0;
    for(char each_char : "hello world".toCharArray())
        computer.setRam(i++, (byte)each_char);

により、RAMに"hello world"を書き込んでいる。
setRamの主語は誰だろう。
つまり誰がRAMを書き込んで(setして)いるのだろうか。
ここでコードは大ウソをついている
コードはこの疑問に、あろうことかcomputerと答えている。
computerは書き込まれる目的語じゃんか。。。

setRamの主語を本当にcomputerであるとするなら、
computerがRAMを外の世界に書き込んで(setして)いることになってしまう。
そしてそれは、getRamの機能「RAMの内容を呼び出し元に返却する」に他ならないではないか。

つまりコードを素直に解釈すると、setterはgetterになってしまうのだ。
この主張を理解できない上級者の方は、初心に返って考えてほしい。
「『computer』が『ram』を(『呼び出し元』に)『書き込みset』する」といったとき、
ramはcomputerに書き込まれるの?それとも「呼び出し元」に書き込まれるの?と考えてみよう。
そこで気がついてほしい。自分は今までとんでもない世界に慣れてしまい、感覚がマヒしていたのだと。

同様に、getterもsetterになってしまう
computer.getRAM(~);を素直に解釈すると、
「『computer』が『ram』を『取得get』する」のだからこれはsetterの定義に他ならない。

3. 問題の発生要因

 この問題が生まれたのは、他動詞と自動詞の区別ができる(重んじる)技術者があまりにも少ないためである。
少なくともOracleは他動詞と自動詞を混同させてオブジェクト指向を説明してしまっている。もはやオブジェクト指向を理解できない方が正しいと言わざるを得ない段階まで悲惨だ。
以下、https://docs.oracle.com/javase/tutorial/java/concepts/object.html から引用および和訳する。

(引用)

Real-world objects share two characteristics: They all have state and behavior. Dogs have state (name, color, breed, hungry) and behavior (barking, fetching, wagging tail). Bicycles also have state (current gear, current pedal cadence, current speed) and behavior (changing gear, changing pedal cadence, applying brakes).

(和訳)

実世界のオブジェクトには2つの特性がある。「状態」と「行動」だ。
犬は状態として「名前」、「色」、「犬種」、「空腹さ」を持ち、
行動として「吠える」、「くわえる」、「尻尾を振る」を持つ。
自転車であれば状態として「現在のギア」、「現在のペダルを漕ぐ速さ」、「現在の速さ」を持ち、
行動として「ギアチェンジ」、「ペダルの漕ぐ速さの変更」、「ブレーキ作動」などがある。

この文章の中で、犬の行動と自転車の行動で決定的(いや、致命的)な違いがある。
犬の行動は犬が「自分でとる行動」であるのに対し、自転車の行動は人という「自分以外のものが取る行動」だ。
犬の行動「吠える」、「くわえる」、「尻尾を振る」はいずれも犬が主語となる自動詞であるが、
自転車の行動「ギアチェンジ」も「ペダルを漕ぐ速さを変える」のも「ブレーキを作動させる」のも、自転車が主語にならない他動詞である。

自転車の行動としてあげられている例は、本当は「自転車に対して適用可能な操作」である。

犬の「行動」と自転車の「操作」を混同して、「これがオブジェクト指向の例だよ」といわれても、初学者の素直な感覚では理解不能であろう。
「行動」と「操作」の違いを頑張って忘れ、getとsetの方向を間違えるようになって、初めてオブジェクト指向は理解できる のが現状だ。
これでは「理解していない方が正しい」といわざるを得ないし、
(主語.述語(目的語)が嘘と分からないままで)オブジェクト指向を理解することは、一種の洗脳にかかることとすら言えるであろう。

4.解決

4-1. 理論

 他動詞メソッドを受動態に変えるか、インスタンスを第1引数に移動することで、オブジェクト指向のコードは正しく英文として読めるようになる。4章ではこのことを解説していく。

 3章に示した通り、他動詞と自動詞を区別しない文化が、主語と目的語を混同する現状を招いている。掘り下げていえば、オブジェクト指向では他動詞の目的語を主語とみなす文化がある。・・・①
本来、自動詞の主語は「能動的な行動者」(例:吠える犬)であり、
他動詞の主語は「操作者」(例:自転車のギアを変える人)であって、
他動詞の目的語が「受動的な行動者」(例:ギアを変えられる自転車)になる。・・・②
①②をまとめていうなら「オブジェクト指向では、他動詞が出てきたとき、受け身の名詞と主語の名詞を逆にしてしまう問題を抱えている」のである。

 逆に言えば、他動詞が出てきたとき、受動態に書き換えることで、もう一度主語と目的語を反転させることができるから、正しい英文が完成する。
例えば
bicycle.change_gear_to(5);

bicycle.is_changed_gear_to(5);
あるいは
bicycle.gear_is_changed_to(5);
とすれば、「自転車は、ギアを5に変更される」と和訳できるような英文として読めるため、意味の上でも正しくなる。・・・受動態法

 あるいはコード上でもインスタンスを引数の位置に持ってきてしまう。
change_gear(of bicycle,to 5);
これなら、主語(javaならJVM)の欠けた英文、すなわち命令文として正しく読むことができる。・・・目的語法

4-2. 受動態法の実践 

OSクラスとcomputerインスタンスの例では、次のようになる。

OSクラスとcomputerインスタンス
public class OS
{
    private byte[] ram;
    public byte is_got_ram(int address){return this.ram[address];}
    public void is_set_ram(int address, byte value){this.ram[address]=value;}

    public OS(int ram_size){this.ram = new byte[ram_size];}
}

class Main{ public static void main(String...args)
{
    OS computer = new OS(64);//64byteのRAMを持つコンピュータの作成
    int i=0;
    for(char each_char : "hello world".toCharArray())
        computer.is_set_ram(i++, (byte)each_char);//by jvm
        //0~10番地に「hello world」を書き込む

    for(int j=0; j<11; j++)
        System.out.print((char)computer.is_got_ram(j));//by jvm
        //0~10番地を(charとして)表示
        //→コンソールに「hello world」と表示される。
}}

確かに、英文として正しく読めるようにはなったものの
今度はメソッド名に_が多くなり、わかりにくくなってしまった。
(とくに、isから始まるメソッドはboolean型を返却するという掟と競合してしまうのは問題)

目的語法(4-3節)ではこの問題が発生しない。

4-3. 目的語法の実践 

OSクラスとcomputerインスタンスの例では、次のようになる。

String code = "

OSクラスとcomputerインスタンス
public class OS
{
    private byte[] ram;
    public byte getRam(int address){return this.ram[address];}
    public void setRam(int address, byte value){this.ram[address]=value;}

    public OS(int ram_size){this.ram = new byte[ram_size];}
}

class Main{ public static void main(String...args)
{
    OS computer = new OS(64);//64byteのRAMを持つコンピュータの作成
    int i=0;
    for(char each_char : "hello world".toCharArray())
        SetRam(of computer,i++, (byte)each_char);
        //0~10番地に「hello world」を書き込む

    for(int j=0; j<11; j++)
        System.out.print((char)GetRam(of computer,j));
        //0~10番地を(charとして)表示
        //→コンソールに「hello world」と表示される。
}}

"; code=new P().parse(code);

これなら読みやすいが、
例えば
SetRam(of computer, i++, (byte)each_char)

computer.setRam(i++, (byte)each_char)
に置き換えるようなパーサPを構築する必要がある。
(正規表現では、括弧言語を受理しないため、力不足)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Studyplusで時短管理学習してみました。

目的、背景

仕事や家庭などでなかなか学習できない、そのような人向けとして、このStudyplusを社会人こそ使うと便利だと気づきました。また、今年は応用情報などの資格を取りたいという人向けにも良いです。

実践

0.社会人カテゴリーがあるので社会人でも気軽に参加できる。

1.教材登録できます!

Screenshot_20200204_080843_jp.studyplus.android.app.jpg

2.学習成果をグラフで視覚化

Screenshot_20200204_080546_jp.studyplus.android.app.jpg

3. カレンダー管理で学習計画を立てられる

達成目標を設定でき、それに向けて学習できる。
Screenshot_20200204_080557_jp.studyplus.android.app.jpg

4. SNS、通知機能ついてる

5. メモ機能もついてる

Screenshot_20200204_082606_jp.studyplus.android.app.jpg

さいごに

以上のことから、studyplus+qiitaなどを使うとさらに便利にエンジニアライフを送れるのではないでしょうか?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaで同一階層のファイルをimportする

packageって考え方が必要らしい。

package = directory と思うと楽そうだ。

mainの .java ファイルをとあるフォルダに入れる。

image.png

main()がある Test1.java の先頭にこれを入れる

package test1;

そうすると、何もimportせずに同一階層の MyTest1Exception.java が読み込める。

    void runSample() throws MyTest1Exception {
                    ...
            throw new MyTest1Exception("独自の例外です"); 

ふむ

reference
https://itsakura.com/java-dokuji-reigai

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java error handlingの基礎 - catch は一番手前でしか拾われないという話

エラーをどこで拾うかはほんとに迷う。

subroutineの中でうかつにtry-catchしてしまうと、拾いたいところまで届かなかったりする。

javaも同じだった

届かない例

同じExceptionを多段なsubroutineでかけると、内側のsubroutineでしか拾えない。

public class MyException {
    final private static int[] M = {1,2,3}; 
    public static void main(String[] args) {
        try {
            subroutine(M);
        }
        catch ( ArrayIndexOutOfBoundsException e ) {
           System.out.println("[SECOND] catch : " + e.getMessage());
        }
    }

    public static void subroutine(int[] M) throws ArrayIndexOutOfBoundsException {
        try {
            System.out.println(M[4]);
        }
        catch ( ArrayIndexOutOfBoundsException e ) {
           System.out.println("[FIRST] catch : " + e.getMessage());
        }
    }
}

result

[FIRST] catch : Index 4 out of bounds for length 3

届く例

内側のcatchの中で再度 throw させると、外側でも拾える。
throwするときは引数 e をいい感じにして渡す。eのままだとエラーになった。よくわかってない。

public class MyException {
    final private static int[] M = {1,2,3}; 
    public static void main(String[] args) {
        try {
            subroutine(M);
        }
        catch ( ArrayIndexOutOfBoundsException e ) {
           System.out.println("[SECOND] catch : " + e.getMessage());
        }
    }

    public static void subroutine(int[] M) throws ArrayIndexOutOfBoundsException {
        try {
            System.out.println(M[4]);
        }
        catch ( ArrayIndexOutOfBoundsException e ) {
           System.out.println("[FIRST] catch : " + e.getMessage());
           throw new ArrayIndexOutOfBoundsException(e.getMessage());
        <--- throwさせる
        }
    }
}

result

[FIRST] catch : Index 4 out of bounds for length 3
[SECOND] catch : Index 4 out of bounds for length 3

というわけで、何が言いたいかというと
- errorを拾うところはできるだけまとめたほうが見やすい
- けどそれぞれのmoduleの役割もあるので、責任範囲で区切るのも大事
- 区切るときに、安易に Exception/RUntimeException を拾っちゃうと外側まで届かない
- 内側ではできるだけ細かく、ちゃんとした xxException を拾ってかないといけない
- そのためには、何をしたら何のexceptionが出るのかしっかりわかってないといけない
- if & throw するのがベストなんだろう
- ( if == 0: throw new DivededByZeroException みたいな)

reference
http://math.hws.edu/javanotes/c8/s3.html

ここの最後のコードも、 if + throw で成り立ってる。そうしよう的なことを書いてる、と思うんだが、眠すぎてもう理解できないので寝る。

まあそんな感じのメモ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java 入れ子のBeanをaaa.bbb[0].cccの形式に変換する

はじめに

  • 入れ子のBeanをaaa.bbb[0].cccの形式に変換する必要があるためとりあえず試作したもののためバグがあるかもしれません
  • 想定している型は下記になります
    • 親Beanのメンバ変数にString or List or 子Bean or List<子Bean>
Bean0.java
@Data
public class Bean0 {
    private List<Bean1> listBean1;
}
Bean1.java
@Data
public class Bean1 {
    private String id;
    private String name;
    private List<String> list;
    private Bean2 bean2;
    private List<Bean2> listBean2;
}
Bean1.java
@Data
public class Bean2 {
    private String count;
    private List<String> hogeList;
}
Bean1Test.java
@SpringBootTest
public class Bean1Test {


    @Test
    public void hoge() throws IllegalArgumentException, IllegalAccessException {
        Bean0 b0 = new Bean0();
        List<Bean1> list = new ArrayList<Bean1>();
        for(int i = 0; i <= 2; i++) {
            Bean1 b1 = new Bean1();

            b1.setId("" + i);
            b1.setName("ほげ太郎" + i);
            b1.setList(new ArrayList<String>(Arrays.asList("aaa", "bbb", "ccc")));

            Bean2 b2 = new Bean2();
            b2.setCount("10" + i);
            b2.setHogeList(Arrays.asList("1" + i));

            b1.setBean2(b2);

            List<Bean2> listb2 = new ArrayList<Bean2>();
            Bean2 b21 = new Bean2();
            b21.setCount("101" + i);
            b21.setHogeList(Arrays.asList("11" + i, "12" + i));
            listb2.add(b21);

            Bean2 b22 = new Bean2();
            b22.setCount("102" + i);
            b22.setHogeList(Arrays.asList("101" + i, "1001" + i, "10001" + i));
            listb2.add(b22);

            b1.setListBean2(listb2);
            list.add(b1);
        }
        b0.setListBean1(list);

        try {
            List<String> ret = getFieldNameValue(b0);
            for(String str: ret) {
                System.out.println(str);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<String> getFieldNameValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
        List<String> list = new ArrayList<String>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for(Field f : fields) {
            f.setAccessible(true);
            Object val = f.get(obj);
            if(f.getType().equals(String.class)) {
                list.add(f.getName() + ":" + val);
            }
            else if(f.getType().equals(List.class)) {
                int i = 0;
                int j = 0;
                if(null == f.get(obj)) continue;
                for(Object obj2: (List<Object>)val) {
                    if(obj2.getClass().equals(String.class)) {
                        list.add(f.getName() + "[" + i++ + "]:" + obj2.toString());
                    }
                    else {
                        List<String> list2 = getFieldNameValue(obj2);
                        List<String> list3 = new ArrayList<String>();
                        for(String str2 : list2) {
                            list3.add(f.getName() + "[" + j + "]" + "." + str2);
                        }
                        list.addAll(list3);
                        j++;
                    }
                }
            } else {
                List<String> list2 = getFieldNameValue(val);
                List<String> list3 = new ArrayList<String>();
                for(String str2 : list2) {
                    list3.add(f.getName() + "." + str2);
                }
                list.addAll(list3);
            }
        }
        return list;
    }
}

- JUnitの実行結果

listBean1[0].id:0
listBean1[0].name:ほげ太郎0
listBean1[0].list[0]:aaa
listBean1[0].list[1]:bbb
listBean1[0].list[2]:ccc
listBean1[0].bean2.count:100
listBean1[0].bean2.hogeList[0]:10
listBean1[0].listBean2[0].count:1010
listBean1[0].listBean2[0].hogeList[0]:110
listBean1[0].listBean2[0].hogeList[1]:120
listBean1[0].listBean2[1].count:1020
listBean1[0].listBean2[1].hogeList[0]:1010
listBean1[0].listBean2[1].hogeList[1]:10010
listBean1[0].listBean2[1].hogeList[2]:100010
listBean1[1].id:1
listBean1[1].name:ほげ太郎1
listBean1[1].list[0]:aaa
listBean1[1].list[1]:bbb
listBean1[1].list[2]:ccc
listBean1[1].bean2.count:101
listBean1[1].bean2.hogeList[0]:11
listBean1[1].listBean2[0].count:1011
listBean1[1].listBean2[0].hogeList[0]:111
listBean1[1].listBean2[0].hogeList[1]:121
listBean1[1].listBean2[1].count:1021
listBean1[1].listBean2[1].hogeList[0]:1011
listBean1[1].listBean2[1].hogeList[1]:10011
listBean1[1].listBean2[1].hogeList[2]:100011
listBean1[2].id:2
listBean1[2].name:ほげ太郎2
listBean1[2].list[0]:aaa
listBean1[2].list[1]:bbb
listBean1[2].list[2]:ccc
listBean1[2].bean2.count:102
listBean1[2].bean2.hogeList[0]:12
listBean1[2].listBean2[0].count:1012
listBean1[2].listBean2[0].hogeList[0]:112
listBean1[2].listBean2[0].hogeList[1]:122
listBean1[2].listBean2[1].count:1022
listBean1[2].listBean2[1].hogeList[0]:1012
listBean1[2].listBean2[1].hogeList[1]:10012
listBean1[2].listBean2[1].hogeList[2]:100012
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む