JavaでEntityをMapに変換からの文字列連結、ソートは上手くいってないから使い物にならないけど。追記:ソートはできました

JavaでEntityのとあるフィールドだけ文字連結したいみたいなことあるあるだよね~。

え?無いですか?甘ったれてんじゃないわよ!

ということで、今回はJavaの話です。

結論から言うと未完です、面目ない。というわけで、お時間のある方のみご照覧ください。

 

Eclipseでプロジェクト作成

とりあえず、Eclipseにて、Gradleプロジェクトを作成します。(Javaプロジェクトでもまったく問題ないです。)

f:id:ts0818:20181118002417p:plain

「プロジェクト名」を適当に入力し、「次へ(N)>」。(キャプチャだと、「MapsTest」ってなってますが、自分は、「MapTest」という名前で作成してます。)

f:id:ts0818:20181118002607p:plain

「次へ(N)>」。

f:id:ts0818:20181118002716p:plain

「完了(F)」をクリック。

f:id:ts0818:20181118002826p:plain

クラスを用意。「entity」パッケージ、「controller」パッケージに1つずつクラスを作成。「controller」パッケージのクラスには、作成時に『public static void main(String[] args)』メソッドを追加しておきます。

f:id:ts0818:20181118002335p:plain

 

クラスの編集

というわけで、編集していきます。 

Entityのクラス。

package entity;

import java.util.Map;

public class Ippman {

	private String name;
	private String age;
	private String gender;
	private String from;
	private String hobby;
	private String message1;
	private String message2;
	private String message3;
	private String message4;
	private String message5;
	private String message6;
	private String message7;
	private String message8;
	private String message9;
	private String message10;
	private String message11;
	private String message12;
	private String message13;

	public Ippman() {

	}

	public Ippman(Map<String, Object> map) {
		super();
		this.name = (String) map.get("name");
		this.age = (String) map.get("age");
		this.gender = (String) map.get("gender");
		this.from = (String) map.get("from");
		this.hobby = (String) map.get("hobby");
		this.message1 = (String) map.get("message1");
		this.message2 = (String) map.get("message2");
		this.message3 = (String) map.get("message3");
		this.message4 = (String) map.get("message4");
		this.message5 = (String) map.get("message5");
		this.message6 = (String) map.get("message6");
		this.message7 = (String) map.get("message7");
		this.message8 = (String) map.get("message8");
		this.message9 = (String) map.get("message9");
		this.message10 = (String) map.get("message10");
		this.message11 = (String) map.get("message11");
		this.message12 = (String) map.get("message12");
		this.message13 = (String) map.get("message13");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String jender) {
		this.gender = jender;
	}

	public String getFrom() {
		return from;
	}

	public void setFrom(String from) {
		this.from = from;
	}

	public String getHobby() {
		return hobby;
	}

	public void setHobby(String hobby) {
		this.hobby = hobby;
	}

	public String getMessage1() {
		return message1;
	}

	public void setMessage1(String message1) {
		this.message1 = message1;
	}

	public String getMessage2() {
		return message2;
	}

	public void setMessage2(String message2) {
		this.message2 = message2;
	}

	public String getMessage3() {
		return message3;
	}

	public void setMessage3(String message3) {
		this.message3 = message3;
	}

	public String getMessage4() {
		return message4;
	}

	public void setMessage4(String message4) {
		this.message4 = message4;
	}

	public String getMessage5() {
		return message5;
	}

	public void setMessage5(String message5) {
		this.message5 = message5;
	}

	public String getMessage6() {
		return message6;
	}

	public void setMessage6(String message6) {
		this.message6 = message6;
	}

	public String getMessage7() {
		return message7;
	}

	public void setMessage7(String message7) {
		this.message7 = message7;
	}

	public String getMessage8() {
		return message8;
	}

	public void setMessage8(String message8) {
		this.message8 = message8;
	}

	public String getMessage9() {
		return message9;
	}

	public void setMessage9(String message9) {
		this.message9 = message9;
	}

	public String getMessage10() {
		return message10;
	}

	public void setMessage10(String message10) {
		this.message10 = message10;
	}

	public String getMessage11() {
		return message11;
	}

	public void setMessage11(String message11) {
		this.message11 = message11;
	}
	public String getMessage12() {
		return message12;
	}

	public void setMessage12(String message12) {
		this.message12 = message12;
	}

	public String getMessage13() {
		return message13;
	}

	public void setMessage13(String message13) {
		this.message13 = message13;
	}

}

controllerのクラス。

package controller;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

import entity.Ippman;

public class TestMap {

	public static void main(String[] args) {
		// 画面からデータが来たと想定し、Mapにセット
		Map<String, Object> map = new LinkedHashMap<String, Object>(){
			{
				put("name", "葉問");
				put("age", "35");
				put("gender", "man");
				put("from", "Hong Kong");
				put("hobby", "Tea");
				put("message1", "詠春拳");
				put("message2", "念頭不正,終生不正。〈拳套要求、人生寓意〉");
				put("message3", "念頭主手〈一說守〉,尋橋主腳〈與步〉。〈練習拳套目的〉 標指不出門。(拳法〉");
				put("message4", "來留去送,甩手直衝。");
				put("message5", "撳頭扢尾,撳尾扢頭,中間〈飄〉膀起。");
				put("message6", "正身子午,側身以膊〈為子午〉。");
				put("message7", "朝面追形,而〈追形〉不追手,以形補手,以手補形。");
				put("message8", "力由地起,拳由心發,手不出門〈手不離午〉。");
				put("message9", "避實擊虛 (遇實則卸,見虛即進)。");
				put("message10", "畏打〈終〉須打,貪打〈終〉被打。(不畏打,不貪打〉");
				put("message11", "轉馬手先行,上馬手先行。〈轉馬上馬,樁手先行〉");
				put("message12", "留情不出手,出手不留情。〈留情不打,打不留情〉");
				put("message13", "不挑不格,消打同時。");

			}
		};
        // 文字列連結用
		StringBuffer buf = new StringBuffer();

		try {
		    // TestMapクラスのメソッドが使えるよう、TestMapクラスをインスタンス化
			TestMap testMap = new TestMap();
			Map<String, String> objectAsMap = testMap.objectToMap(map,Ippman.class);

			System.out.println(objectAsMap);
			buf = testMap.createText(objectAsMap);

			System.out.println(buf);


		} catch (IllegalArgumentException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}

	}

    // EntityをMapに変換するメソッド
	protected Map<String, String> objectToMap(Map<String, Object> jsonToMap, Class<? extends Object> entity) {

		Map<String, Object> objectAsMap = new LinkedHashMap<String, Object>();
		Map<String, String> sortMap = new LinkedHashMap<String, String>();

		BeanInfo info = null;
		Object obj = null;
		try {
		    // Ippmanクラスを、Mapを引数とするコンストラクタで、引数にjsonToMapを指定して、インスタンス化
			obj = entity.getConstructor(Map.class).newInstance(jsonToMap);
			// Ippmanクラスのメタ情報を取得
			info = Introspector.getBeanInfo(entity);
			for (PropertyDescriptor pd : info.getPropertyDescriptors()) {

				Method getter = pd.getReadMethod();
				if(getter != null && !"class".equals(pd.getName())) {
					objectAsMap.put(pd.getName(), getter.invoke(obj));
				}
			}
			System.out.println(objectAsMap);
			// Mapをソート
			sortMap = convertMap(objectAsMap);


		} catch (IntrospectionException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
		return sortMap;

	}

	// 文字列連結するメソッド
	protected StringBuffer createText(Map<String, String> map) {

		StringBuffer buf = new StringBuffer();
		String space = " ";
		int capacitySize = 30;
		String text = null;

		for (Map.Entry<String, String> entry : map.entrySet() ) {
			if(entry != null && entry.getKey().contains("message")) {

				buf.append(space);
				text = entry.getValue();
				if(text.length() > capacitySize) {
					text = text.substring(0, capacitySize);
				}

				buf.append(text);

				if(text.length() == capacitySize) {
				  buf.append(space);
				}
				buf.append(System.lineSeparator());
			}

		}

		return buf;

	}

	// Mapでソートできるよう変換
	public LinkedHashMap<String, String> convertMap(Map<String, Object> map) {

		LinkedHashMap<String, String> collect = map.entrySet().stream()
				.collect(Collectors.toMap(k -> (String) k.getKey(), e -> (String) e.getValue()))
                .entrySet()
                .stream()
                .sorted((key1, key2) -> key1.getKey().length() - key2.getKey().length())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));
		return collect;
	}
}

で実行すると、肝心のMapのソートができていないという残念な結果に...文字列に数値が入ってる場合のソートの厄介なことこの上なし。

f:id:ts0818:20181118003856p:plain

 

ちょっと、調査が必要ですかね...しかもラムダ式が入っちゃてるから、Entityの項目にNULLが入ってると落ちるますしね...あとクラスのフィールドにクラスとかあったらとか想定してないソースコードになっちゃってますしね...頗るポンコツですな

何か上手い方法が無いものか。

www.leveluplunch.com

⇧  上記サイト様によりますと、今回使用した「reflection(Javaの標準ライブラリ)」以外にも「Jackson」、「Apache Commons」などの外部ライブラリ(別途jarなどをインストールする必要あり)を使用することで、EntityからMapへの変換は可能のようです。

ソートに関しては、

https://docs.oracle.com/javase/jp/8/docs/api/java/util/Comparator.html

Comparatorなるものを活用していく感じになるのだとか、使い方がよく分からんです。

ka-ka-xyz.hatenablog.com

⇧  上記サイト様によりますと、Comparatorは、並び順を変えるだけじゃないみたい...

 

2018年11月18日  追記:↓  ここから

ソートだけはできました!

teratail.com

⇧  teratailさんの力により。 

package controller;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

import entity.Ippman;

public class TestMap {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		Map<String, Object> map = new LinkedHashMap<String, Object>(){
			{
				put("name", "葉問");
				put("age", "35");
				put("gender", "man");
				put("from", "Hong Kong");
				put("hobby", "Tea");
				put("message1", "詠春拳");
				put("message2", "念頭不正,終生不正。〈拳套要求、人生寓意〉");
				put("message3", "念頭主手〈一說守〉,尋橋主腳〈與步〉。〈練習拳套目的〉 標指不出門。(拳法〉");
				put("message4", "來留去送,甩手直衝。");
				put("message5", "撳頭扢尾,撳尾扢頭,中間〈飄〉膀起。");
				put("message6", "正身子午,側身以膊〈為子午〉。");
				put("message7", "朝面追形,而〈追形〉不追手,以形補手,以手補形。");
				put("message8", "力由地起,拳由心發,手不出門〈手不離午〉。");
				put("message9", "避實擊虛 (遇實則卸,見虛即進)。");
				put("message10", "畏打〈終〉須打,貪打〈終〉被打。(不畏打,不貪打〉");
				put("message11", "轉馬手先行,上馬手先行。〈轉馬上馬,樁手先行〉");
				put("message12", "留情不出手,出手不留情。〈留情不打,打不留情〉");
				put("message13", "不挑不格,消打同時。");
			}
		};

		StringBuffer buf = new StringBuffer();

		try {
			TestMap testMap = new TestMap();
			Map<String, String> objectAsMap = testMap.objectToMap(map,Ippman.class);

			System.out.println(objectAsMap);
			buf = testMap.createText(objectAsMap);

			System.out.println(buf);

		} catch (IllegalArgumentException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
	}

	protected Map<String, String> objectToMap(Map<String, Object> jsonToMap, Class<? extends Object> entity) {

		Map<String, Object> objectAsMap = new LinkedHashMap<String, Object>();
		Map<String, String> sortMap = new LinkedHashMap<String, String>();

		BeanInfo info = null;
		Object obj = null;
		try {
			obj = entity.getConstructor(Map.class).newInstance(jsonToMap);
			info = Introspector.getBeanInfo(entity);
			for (PropertyDescriptor pd : info.getPropertyDescriptors()) {

				Method getter = pd.getReadMethod();
				if(getter != null && !"class".equals(pd.getName())) {
					objectAsMap.put(pd.getName(), getter.invoke(obj));
				}
			}
			System.out.println(objectAsMap);
			// Mapをソート
			sortMap = convertMap(objectAsMap);


		} catch (IntrospectionException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
		return sortMap;
	}

	// 文字列連結
	protected StringBuffer createText(Map<String, String> map) {

		StringBuffer buf = new StringBuffer();
		String space = " ";
		int capacitySize = 30;
		String text = null;

		for (Map.Entry<String, String> entry : map.entrySet() ) {
			if(entry != null && entry.getKey().contains("message")) {

				buf.append(space);
				text = entry.getValue();
				if(text.length() > capacitySize) {
					text = text.substring(0, capacitySize);
				}

				buf.append(text);

				if(text.length() == capacitySize) {
				  buf.append(space);
				}
				buf.append(System.lineSeparator());
			}
		}
		return buf;
	}

	// Mapでソートできるよう変換
	public LinkedHashMap<String, String> convertMap(Map<String, Object> map) {

		LinkedHashMap<String, String> collect = map.entrySet().stream()
				.collect(Collectors.toMap(k -> (String) k.getKey(), e -> (String) e.getValue()))
                .entrySet()
                .stream()
                .sorted((a, b) -> a.getKey().length() == b.getKey().length()
                      ? a.getKey().compareTo(b.getKey())
                              : a.getKey().length() - b.getKey().length())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));
		return collect;
	}
}

f:id:ts0818:20181118222220p:plain

⇧  詠春拳の教えが、ちゃんと、message1~message13 の順番で並んでますね!

詠春拳の実力者であるイップマンについては、


イップ・マン 序章&葉問 Blu-rayツインパック

⇧  上記の映画が面白いです!レンタルなら、100円 ✕ 2 とかで借りれるかと。

『イップ・マン3 継承』はまだ観れてないから観たいところです。 

 

2018年11月18日  追記:↑  ここまで

 

今回はこのへんで。