Edited at

Javaの標準ライブラリでなるべくシンプルにコードを書くための覚え書き

More than 5 years have passed since last update.

お仕事で自分や他の人のコードで発見した無駄なコードを、よりシンプルなコードに書きなおした時のメモ集的なものです。


String関連

Stringクラスのチェック系メソッド。


// 大文字小文字の違いを考慮しない一致。toUpperCaseで揃えたりしない。
assert "abc".equalsIgnoreCase("ABC");

// compareToにも大文字小文字の違いを考慮しないメソッドがある。
assert "abc".compareToIgnoreCase("ABC") == 0;

// 空文字チェック。空文字列とequalsとかしない。
assert "".length() == 0;// java5まで
assert "".isEmpty(); // java6から

// ある文字列で始まる。s.indexOf(a)==0とかしない。
assert "abcdef".startsWith("abc");

// ある文字列で終わる。s.lastIndexOf(a)==s.length()-a.length()とかしない。
assert "abcdef".endsWith("def");

// ある文字列を含む。s.indexOf(a) > 0とかしない。
assert "abcdef".contains("cde");

その他のよくあるチェック。


// 特定の文字(列)を2つ以上含む。
char cm = ',';
String str1 = "a,b,c";
assert str1.indexOf(cm) != str1.lastIndexOf(cm);

// Stringに限らないけど、equalsをORで連結しまくるより、リスト化してcontainsがシンプル。
assert Arrays.asList("aaa", "bbb", "ccc").contains("bbb");

// ある文字列の出現回数。もっといい方法がある気がする……。
String replace = "xx";
String str2 = "axxbxxxcxx";
assert (str2.length() - str2.replaceAll(replace, "").length()) / replace.length() == 3;


正規表現関連


RegExpIdioms.java


// String#matches(String)は完全一致
assert "a,bc,".matches("[a-z],[a-z]{2},");

// 特定の正規表現を使いまわすならPatternをコンパイルしておく
Pattern pattern = Pattern.compile("[a-z],[a-z]{2},");
assert pattern.matcher("a,bc,").matches();

// 部分一致はMatcher#findで。
assert pattern.matcher("0a,bc,123").find();

// 大文字小文字の違いを考慮しない正規表現による完全一致
assert Pattern.compile("[a-z],[a-z]{2},", Pattern.CASE_INSENSITIVE).matcher("A,BC,").matches();

// 埋め込みフラグ使ったほうがいい気がする
assert "A,BC,".matches("(?i)[a-z],[a-z]{2},");



全角半角変換(Unicode正規化)


// Unicode正規化できる。全角半角変換テーブルとか-0xFEE0とかしない。
assert Normalizer.normalize("abc123", Form.NFKC).equals("abc123");
assert Normalizer.normalize("!#$%&()", Form.NFKC).equals("!#$%&()");
assert Normalizer.normalize("アガペー", Form.NFKC).equals("アガペー");


配列、リスト関連

最大、最小とか


// よくあるやつ。一目見て何やってるかわかりにくいのでつらい。
int[] ints = { 35, 87, 65, 56 };
int minInt = Integer.MAX_VALUE;
int maxInt = Integer.MIN_VALUE;
for (int i : ints) {
if (minInt > i) minInt = i;
if (maxInt < i) maxInt = i;
}
assert minInt == 35 && maxInt == 87;

// 最大・最小を取得はCollectionsのユーティリティメソッドで。
List<Integer> list = Arrays.asList(35, 87, 65, 56);
assert Collections.min(list) == 35;
assert Collections.max(list) == 87;

// 要素がComparableを実装してないならComparatorを渡してあげる。
User alice = new User(3, "Alice");
User bob = new User(2, "Bob");
User carol = new User(1, "Carol");
List<User> userList = Arrays.asList(alice, bob, carol);

// 最小取得
User min = Collections.min(userList, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
// Java7以降はプリミティブラッパークラスにcompareが追加された
return Integer.compare(o1.getId(), o2.getId());
// return o1.getId() - o2.getId();
}
});
assert min.equals(carol);

// 最大取得
User max = Collections.max(userList, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getName().compareTo(o2.getName());
}
});
assert max.equals(carol);

配列のリスト化


// 複数の要素もしくは配列を、java.util.ArrayListにしたいとき。
// コピーコンストラクタ的な感じ。1行で済むけどArrays#asListで1個余分にリスト生成する。
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));

// addAllの引数でArrays.asListするなら、Collections#addAllを使ったほうが無駄がない。
// list.addAll(Arrays.asList("d", "e", "f"));
Collections.addAll(list, "d", "e", "f");

Arraysクラスのメソッド。

System#arraycopyよりcopyOf, copyOfRange使ったほうが見やすい。


// 配列のコピーを作成
int[] intArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int[] copyOfIntArray = Arrays.copyOf(intArray, intArray.length);
int[] copyOfRangeIntArray = Arrays.copyOfRange(copyOfIntArray, 3, 5);

// 配列のequals
assert Arrays.equals(intArray, copyOfIntArray);
assert Arrays.equals(copyOfRangeIntArray, new int[] { 4, 5 });