2018年06月27日

別クラスの同名フィールドの内容をコピーする

あるクラスのフィールドの内容を、まったく別のクラスの同名のフィールドへコピーするメソッドです。
(同名フィールドは同じ型であることが必須)
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

public class MyClass {

public static void main(String... args) {

// コピー元のインスタンス生成
MemberA memA = new MemberA("Ichiro", "Tokyo", 25, "fishing", "ABC");
System.out.println(memA);

// 同名フィールドのコピーを実施
MemberB memB = new MemberB();
copyFields(memA, memB);

// コピー先のインスタンス表示
System.out.println(memB);
}

/**
* 別クラスの同名フィールドをコピーする
* @param source コピー元のインスタンス
* @param target コピー先のインスタンス
*/
private static void copyFields(Object source, Object target) {
final String prefixSet = "set";
final String prefixGet = "get";

Set<String> methodSet = new HashSet<String>();
for (Method method : target.getClass().getMethods())
if (method.getName().startsWith(prefixSet))
methodSet.add(method.getName().substring(prefixSet.length()));

try {
for (Method method : source.getClass().getMethods()) {
if (!method.getName().startsWith(prefixGet))
continue;
String curName = method.getName().substring(prefixGet.length());
if (methodSet.contains(curName)) {
Method newMethod = target.getClass().getMethod(prefixSet + curName, method.getReturnType());
newMethod.invoke(target, method.invoke(source));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
クラスMemberA
public class MemberA {
private String name;
private String address;
private Integer age;
private String hobby;
private String company;

public MemberA() {
}

// Eclipseでgetter/setter/toStringの生成、
// フィールドを使用してコンストラクタを生成
}
クラスMemberB
import java.time.LocalDate;

public class MemberB {
private String name;
private String school;
private String friendname;
private LocalDate birthday;
private Integer age;
private String address;

public MemberB() {
}

// Eclipseでgetter/setter/toStringの生成、
// フィールドを使用してコンストラクタを生成
}
タグ:JAVA Eclipse
posted by Hiro at 23:19| Comment(2) | プログラム

2018年06月23日

さくらブログについての問い合わせの回答

タグに登録したアルファベットの大小間違いを修正できない件について
さくらのブログのサポートに問い合わせたところ、
「一度登録すると変更できません。ブログの仕様です」との回答をもらいました。

posted by Hiro at 18:57| Comment(0) | 日記

2018年06月16日

Java コレクションクラスについての備忘録

自前のクラスをArrayListなどに入れてまとめて扱うことは多々あると思いますが、
同値判定にかかわる部分ついて押さえておかないと、
期待したとおりの動作にならずつまづくことがあるのでメモしておきます。

サンプルのソースでは呼び出し側のMyClassで、自作したMyComparableClassのインスタンスを各コレクションクラスに挿入し、
別のインスタンスを使って「既に存在するか」のチェックをさせます。

結果は一番下に示した様になります。

判定に使われるメソッドについてまとめると以下のようになります。

(1)ArrayListとLinkedList
equalsが呼ばれる。

(2)HashMapとHashSet
hashCodeが呼ばれ、同値だった場合にequalsが呼ばれる。

(3)TreeMapとTreeSet
compareToが呼ばれる。

equalsとcompareToの関係についてはこちらで詳しく解説されています。
「equalsとcompareToが一貫性してることは強く推奨されるけど、BigDecimalは例外」だそうな。

■自前のクラス MyComparableClass
/**
* Comparableを実装したクラス
*/
public class MyComparableClass<T extends Comparable<T>> implements Comparable<MyComparableClass<T>> {

/** フィールド1 */
private T field1;

/**
* フィールド1を返す
* @return field1
*/
public T getField1() {
return field1;
}

/**
* コンストラクタ
* @param field1 フィールド1
*/
public MyComparableClass(T field1) {
this.field1 = field1;
}

/**
* このオブジェクトと指定されたオブジェクトの順序を比較します。
* @param other
* @return
*/
@Override
public int compareTo(MyComparableClass<T> other) {
System.out.println("compareToが呼ばれました:" + field1.toString());
return field1.compareTo(other.getField1());
}

/**
* オブジェクトのハッシュ・コード値を返します。
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
System.out.println("hashCodeが呼ばれました:" + field1.toString());
final int prime = 31;
int result = 1;
result = prime * result + ((field1 == null) ? 0 : field1.hashCode());
return result;
}

/**
* このオブジェクトと他のオブジェクトが等しいかどうかを示します。
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
System.out.println("equalsが呼ばれました:" + field1.toString());
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
@SuppressWarnings("unchecked")
MyComparableClass<T> other = (MyComparableClass<T>) obj;
if (field1 == null) {
if (other.field1 != null)
return false;
} else if (!field1.equals(other.field1))
return false;
return true;
}
}
■呼び出し側(MyClass)
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class MyClass {

public static void main(String... args) {

MyComparableClass<BigDecimal> val1 = new MyComparableClass<>(new BigDecimal("100"));
MyComparableClass<BigDecimal> val2 = new MyComparableClass<>(new BigDecimal("100.00"));

System.out.println("-----ArrayList---------------");
List<MyComparableClass<BigDecimal>> myArrayList = new ArrayList<>();
myArrayList.add(val1);

if (myArrayList.contains(val2)) {
System.out.println(">>ok");
} else {
System.out.println(">>ng");
}

System.out.println("-----LinkedList---------------");
List<MyComparableClass<BigDecimal>> myLinkedList = new LinkedList<>();
myLinkedList.add(val1);

if (myLinkedList.contains(val2)) {
System.out.println(">>ok");
} else {
System.out.println(">>ng");
}

System.out.println("-----HashMap---------------");
Map<MyComparableClass<BigDecimal>, Integer> myHashMap = new HashMap<>();
myHashMap.put(val1, 0);

if (myHashMap.containsKey(val2)) {
System.out.println(">>ok");
} else {
System.out.println(">>ng");
}

System.out.println("-----TreeMap---------------");
Map<MyComparableClass<BigDecimal>, Integer> myTreeMap = new TreeMap<>();
myTreeMap.put(val1, 0);

if (myTreeMap.containsKey(val2)) {
System.out.println(">>ok");
} else {
System.out.println(">>ng");
}

System.out.println("-----HashSet---------------");
Set<MyComparableClass<BigDecimal>> myHashSet = new HashSet<>();
myHashSet.add(val1);

if (myHashSet.contains(val2)) {
System.out.println(">>ok");
} else {
System.out.println(">>ng");
}

System.out.println("-----TreeSet---------------");
Set<MyComparableClass<BigDecimal>> myTreeSet = new TreeSet<>();
myTreeSet.add(val1);

if (myTreeSet.contains(val2)) {
System.out.println(">>ok");
} else {
System.out.println(">>ng");
}
}
}
■実行結果
-----ArrayList---------------
equalsが呼ばれました:100.00
>>ng
-----LinkedList---------------
equalsが呼ばれました:100.00
>>ng
-----HashMap---------------
hashCodeが呼ばれました:100
hashCodeが呼ばれました:100.00
>>ng
-----TreeMap---------------
compareToが呼ばれました:100
compareToが呼ばれました:100.00
>>ok
-----HashSet---------------
hashCodeが呼ばれました:100
hashCodeが呼ばれました:100.00
>>ng
-----TreeSet---------------
compareToが呼ばれました:100
compareToが呼ばれました:100.00
>>ok
タグ:JAVA
posted by Hiro at 19:50| Comment(0) | プログラム