JavaでEntityのとあるフィールドだけ文字連結したいみたいなことあるあるだよね~。
え?無いですか?甘ったれてんじゃないわよ!
ということで、今回はJavaの話です。
結論から言うと未完です、面目ない。というわけで、お時間のある方のみご照覧ください。
Eclipseでプロジェクト作成
とりあえず、Eclipseにて、Gradleプロジェクトを作成します。(Javaプロジェクトでもまったく問題ないです。)
「プロジェクト名」を適当に入力し、「次へ(N)>」。(キャプチャだと、「MapsTest」ってなってますが、自分は、「MapTest」という名前で作成してます。)
「次へ(N)>」。
「完了(F)」をクリック。
クラスを用意。「entity」パッケージ、「controller」パッケージに1つずつクラスを作成。「controller」パッケージのクラスには、作成時に『public static void main(String[] args)』メソッドを追加しておきます。
クラスの編集
というわけで、編集していきます。
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のソートができていないという残念な結果に...文字列に数値が入ってる場合のソートの厄介なことこの上なし。
ちょっと、調査が必要ですかね...しかもラムダ式が入っちゃてるから、Entityの項目にNULLが入ってると落ちるますしね...あとクラスのフィールドにクラスとかあったらとか想定してないソースコードになっちゃってますしね...頗るポンコツですな
何か上手い方法が無いものか。
⇧ 上記サイト様によりますと、今回使用した「reflection(Javaの標準ライブラリ)」以外にも「Jackson」、「Apache Commons」などの外部ライブラリ(別途jarなどをインストールする必要あり)を使用することで、EntityからMapへの変換は可能のようです。
ソートに関しては、
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Comparator.html
Comparatorなるものを活用していく感じになるのだとか、使い方がよく分からんです。
⇧ 上記サイト様によりますと、Comparatorは、並び順を変えるだけじゃないみたい...
2018年11月18日 追記:↓ ここから
ソートだけはできました!
⇧ 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; } }
⇧ 詠春拳の教えが、ちゃんと、message1~message13 の順番で並んでますね!
詠春拳の実力者であるイップマンについては、
⇧ 上記の映画が面白いです!レンタルなら、100円 ✕ 2 とかで借りれるかと。
『イップ・マン3 継承』はまだ観れてないから観たいところです。
2018年11月18日 追記:↑ ここまで
今回はこのへんで。