プログラマメモ2 - programmer no memo2

[java]順列 お手軽 2015/05/10

Javaです。
順列です。
組み合わせの列挙なのですが、
書けといわれてすぐ書けなくて。。。。
>_<!

困ったときのapacheさんです。

Math - Commons Math: The Apache Commons Mathematics Library
Collections - Home

Mathにあるんだろなーと思って探したんですが、どうもランダムに生成するのはあったのですが、たんに組みわせを全部とりだいたいという ニーズにあわなくて、するとCollectionsのほうにいい感じのものがありました。
ちなみに、最新のMathとコレクションの現時点でのバージョンは、
                 [org.apache.commons/commons-math3 "3.5"]
                 [org.apache.commons/commons-collections4 "4.0"]
 です。


PermutationIteratorはcommons-collections4からあります。
※使うのは、PermutationIteratorですよ!!

出力結果
[0, 1, 2, 3]
[0, 1, 3, 2]
[0, 3, 1, 2]
[3, 0, 1, 2]
[3, 0, 2, 1]
[0, 3, 2, 1]
[0, 2, 3, 1]
[0, 2, 1, 3]
[2, 0, 1, 3]
[2, 0, 3, 1]
[2, 3, 0, 1]
[3, 2, 0, 1]
[3, 2, 1, 0]
[2, 3, 1, 0]
[2, 1, 3, 0]
[2, 1, 0, 3]
[1, 2, 0, 3]
[1, 2, 3, 0]
[1, 3, 2, 0]
[3, 1, 2, 0]
[3, 1, 0, 2]
[1, 3, 0, 2]
[1, 0, 3, 2]
[1, 0, 2, 3]

以下コード

List<Integer> list = Arrays.asList(new Integer[]{0,1,2,3}); PermutationIterator<Integer> iterator = new PermutationIterator<>(list); while(iterator.hasNext()) { System.out.println(iterator.next()); }



1文字目を小文字にしたくて - groovy 2013/10/12

groovyです。
capitalizeはデフォルトであるんですが、その逆のuncapitalizeがないんだなーというわけで、どうしようかなと悩んでたのですが、commonsにあるのでそれを使おう。

import org.apache.commons.lang.WordUtils String.metaClass.uncapitalize { WordUtils.uncapitalize(delegate) }

metaclass使って文字列処理を拡張してみます。
便利ですね!!

で、ほんとはどういことがしたかったというと
xxx_yyy_zzz
のような文字列を
xxxYyyZzz
というふうにしたかったわけです。

こんなコードを用意してみました。

conveter2 = { s -> s.tokenize('_')*.capitalize().join().uncapitalize() } assert conveter2('xxx_yyy_zzz') == 'xxxYyyZzz'

うまくいってる気はする。

便利ですね。StringUtils 2013/01/06

apacheのcommonsのStringUtilsは便利なのでよく使います。
null safeなのが使いやすい理由ってとこでしょうか。

試したのは、org.apache.commons.lang3.StringUtilsのほうです。
ちなみにorg.apache.commons.lang.StringUtilsだとdeprecatedがでますね。

capitalizeは、英語の文頭とかで先頭一文字だけ、大文字とかするのに使えますね。WordUtils.capitalizeは、語ごとの先頭を大文字にします。

Aaaaa bbbb
Aaaaa Bbbb
上が、StringUtilsの結果で、下のほうがWordUtilsの結果となります。

 indexOfDifferenceメソッドが使えます。
ふたつの文字列を引数にして、何文字目がちがうかindexを返してくれます。
文字列の変更の差分を取得したい場合に使えそうです。


toStringの実装がめんどうくさいあなたに 2011/05/07

Javaです。


toStringの実装が面倒なら、こういう方法もあり。
出力されるスタイルは好みがわかれると思うけど。

public String toString() {
return org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(this);
}


以下の方法で複数行で出力

public String toString() {
return org.apache.commons.lang3.builder.ReflectionToStringBuilder
.toString(
this,
org.apache.commons.lang3.builder.ToStringStyle.MULTI_LINE_STYLE);
}

GrowthList - 成長するよリスト 2008/09/11

Javaです。
java.util.Listのインターフェイスに、indexを指定できるsetメソッドがあります。
これは、インデックスが範囲外の場合、IndexOutOfBoundsException 例外を発生するようになっています。

気分的には、サイズが足りない場合は、補間してセットできたらいいかなぁと思うことがあります。

そんなクラスどこかにないかなぁというわけで、さがすとapache.commons.collections.list.GrowthListというのがありました。
このクラスに用意されているsetはIndexOutOfBoundsExceptionを発生させません。

Collections - Home

それで、自分のニーズにあわないのは、補間される値がnullであること(まあそういうものだろうという気はします。)

そう思ってうろうろ散策していたら、org.apache.commons.collections.list.LazyListというものがあり、
decorateする際の指定の仕方によっては値がない場合に任意のオブジェクトを返すことができることがわかりました。

参考
2006-07-03 - a geek

次に、getするだけでサイズが大きくなる可能性がある....
それはそれで仕方がないか....

以下コード

import java.util.List;

import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.list.GrowthList;
import org.apache.commons.collections.list.LazyList;

public class TestCollection {

public static void main(String[] args) {

List<String> list = LazyList.decorate(new GrowthList(), ConstantFactory
.getInstance("o_o!"));

list.set(8, "aaa");
System.out.println(list);
System.out.println(list.get(5));
System.out.println(list);
}

}


結果
[null, null, null, null, null, null, null, null, aaa]
o_o!
[null, null, null, null, null, o_o!, null, null, aaa]

java ファイルのコピーや移動のコードが面倒ならCommons使います。 2008/02/13

ファイルのコピーや移動のコードが面倒なら、Commons IO - Homeを使うのも手です。

おそらく問題ないと思います。

一意なiteratorにする。 2008/01/31

Jakarta commonsのcollectionsです。

コレクションにあるた値で一意(ユニーク)なものだけ取得したい。


org.apache.commons.collections.iterators.UniqueFilterIteratorが使えそうです。

package collections;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections.iterators.UniqueFilterIterator;

public class TestUniqueFilterIterator {

public static void main(String[] args) {
a();
}

public static void a(){
String[] ss = {"1", "1", "2", "2", "3", "3"};
List<String> list = Arrays.asList(ss);
Iterator<String> iterator = new UniqueFilterIterator(list.iterator());
while (iterator.hasNext()) {
String s = iterator.next();
System.out.println(s);
}


}
}


結果
1
2
3

XMLConfiguration デフォルトでの値の取得方法とXPathを使用してとる方法です。 2008/01/24

CommonsのConfigurationです。

Configuraionは、いいAPIだと思います。

デフォルトでの値の取得方法とXPathを使用してとる方法です。



import java.io.ByteArrayInputStream;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;

public class TestXMLConfiguration {

public static void main(String[] args) throws ConfigurationException {
a();
}

static String s = "<root><a><b>test</b><c>test2</c></a></root>";

public static void a() throws ConfigurationException {

// xxxExpressionEngine
XPathExpressionEngine xpathExpressionEngine = new XPathExpressionEngine();
DefaultExpressionEngine defaultExpressionEngine = new DefaultExpressionEngine();
XMLConfiguration xml = new XMLConfiguration();

xml.load(new ByteArrayInputStream(s.getBytes()));

// (a) XPathExpressionEngine
xml.setExpressionEngine(xpathExpressionEngine);

System.out.println(xml.getString("a/b"));

// (b) DefaultExpressionEngine
xml.setExpressionEngine(defaultExpressionEngine);

System.out.println(xml.getString("a.b"));
}


}


expression engineを指定することで、パスの記述方法を変更します。

デフォルトだとドット区切りでパス指定を行います。

LinuxからWindowsのIIS付属のFTPサーバーにアクセスするFTPクライアントのサンプルです。jakartaのcommonsのnetを使ってます。固まらないと思います。 2008/01/21

どうもLinuxの環境設定によって、FTPクライアントが固まるようになる場合があるので、それをさけるために、enterRemotePassiveMode、enterLocalPassiveModeを続けて呼んでいます。

この呼び出し順序でも動作が変わるようです。

サーバーがWindowsなので、setControlEncodingを設定しています。

多分、動くと思います。

org.apache.commons.net.ftp.FTPClient

よかったら動かしてみてください。


import java.io.IOException;
import java.net.SocketException;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

public class TestFtpClient4 {

/**
* LINUXからWindowsのIIS付属のFTPサーバーに接続します。
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
FTPClient client = new FTPClient();

// エンコーディング
client.setControlEncoding("SJIS");

try {

client.setDefaultPort(21);

// (1)
client.connect("アドレス"); // FTPサーバーのIPアドレス
// (2)
client.login("Anonymous", "passowrd"); // FTPサーバーのID,パスワード

// (3)
boolean isRemotePassive = client.enterRemotePassiveMode();

// (4)
client.enterLocalPassiveMode();

// (5)
boolean isOk = client.changeWorkingDirectory("/");
System.out.println("isOk" + isOk);

// (6)
FTPFile[] list = client.listFiles();
for (int i = 0; i < list.length; i++) {
String name = list[i].getName();
String group = list[i].getGroup();
System.out.println("group : " + group);
System.out.println("name : " + name);
}

} catch (SocketException e) {
throw e;
} catch (IOException e) {
throw e;
} finally {
if (client != null && client.isConnected()) {
try {
client.logout();
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("終了");
}
}
}

FTPClient簡単なサンプル 2008/01/21

使っているのは、commonsのnetです。

import java.io.IOException;
import java.net.SocketException;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

public class TestFtpClient {

public static void main(String[] args) throws Exception {
FTPClient client = new FTPClient();
client.setControlEncoding("SJIS");
try {
System.out.println("開始");
client.setDefaultPort(21);
client.connect("localhost"); // FTPサーバーのIPアドレス
client.login("Anonymous", "passowrd"); // FTPサーバーのID,パスワード
boolean isOk = client.changeWorkingDirectory("/");
System.out.println("isOk" + isOk);

FTPFile[] list = client.listFiles();
for (int i = 0; i < list.length; i++) {
String name = list[i].getName();
String group = list[i].getGroup();
System.out.println("group : " + group);
System.out.println("name : " + name);
}
} catch (SocketException e) {
throw e;
} catch (IOException e) {
throw e;
} finally {
if (client != null && client.isConnected()) {
try {
client.logout();
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("終了");
}
}
}

Java コレクションを演算できるのはやはり便利だと思う。 2008/01/13
2008/01/15

コレクションを演算できるはやはり便利だと思う。
CommonsのCollectionsはまだジェネリックに対応していないようですね。




import java.util.ArrayList;
import java.util.List;
import static org.apache.commons.collections.CollectionUtils.subtract;

public class A {

public static void main(String[] args) {
List<String> a = new ArrayList<String>(){{add("1");add("2");add("3");}};
List<String> b = new ArrayList<String>(){{add("6");add("2");add("7");}};

//差
List<String> c = (List<String>) subtract(a, b);
System.out.println(c);

}

}


Groovyで同じことをしてみます。
import static org.apache.commons.collections.CollectionUtils.subtract;

def a = [1,2,3,4,5,6,7]
def b = [1,2,4]

def c = subtract(a, b)

print c



Groovyだともっと直感的にできるっぽい。
そのまま引けばよい。

import static org.apache.commons.collections.CollectionUtils.subtract;

def a = [1,2,3,4,5,6,7]
def b = [1,2,4]

def c = subtract(a, b)
def d = a - b

assert c == d


といってもこの使い方でよいかわからないけど。

あと、共通の値を求めることができるintersectは、Groovyに用意されていた。
で、commonsのものとあわせてためしてみた。要sort。
import static org.apache.commons.collections.CollectionUtils.intersection

def a = [1,2,3]
def b = [1,2,3]

def c = intersection(a, b).sort()
def d = a.intersect(b)

assert c == d


グーグルのコレクション


Rubyのほうをちらりと見てみたら、いろいろできるようです。
Rubyリファレンスマニュアル - 機能別索引

JRubyのコンソールで試してみた。



関連

Arrays - Computing Union, Intersection, or Difference of Unique Lists

Commons Configuration XMLConfigurationの値をMapにうつす方法 2008/01/09

Commons Configuration - Java Configuration API

CommonsのConfigurationって好きなライブラリのひとつです。
アプリケーションのコンフィギュレーションで使わせてもらっています。

XMLConfigurationで設定した値をMapにして使いまわしたかったので調べてみました。

XMLConfigurationの値をMapにうつす方法

MapConfigurationを作成して、ConfigurationUtilsを使ってcopyします。
思ったより簡単にできる!!

サンプルコード

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.ConfigurationUtils;
import org.apache.commons.configuration.MapConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;

public class Sample {

public static void main(String[] args) throws ConfigurationException {
XMLConfiguration xmlConfiguration = new XMLConfiguration();

// {
// DefaultExpressionEngine defaultExpressionEngine = new DefaultExpressionEngine();
// xmlConfiguration.setExpressionEngine(defaultExpressionEngine);
// }
xmlConfiguration.setProperty("aaa.bbb", "ok");
StringWriter writer = new StringWriter();
xmlConfiguration.save(writer);
System.out.println(xmlConfiguration.getString("aaa.bbb"));
Map map = new HashMap();
MapConfiguration mapConfiguration = new MapConfiguration(map);
ConfigurationUtils.copy(xmlConfiguration, mapConfiguration);
System.out.println(writer);
System.out.println(map);

}

}


結果

ok
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<configuration>
<aaa>
<bbb>ok</bbb>
</aaa>
</configuration>

{aaa.bbb=ok}

VFSを使用してftpでファイルのコピー 2007/12/28
2008/01/23

Commons Virtual File System - Commons VFS

VFSを使用してFTPでファイルのコピーを行います。
org.apache.commons.vfs.FileUtil.copyContentを使用しています。

!!このコードは効率が悪いです!!
あくまでも参考です。

VFSを使用するといろいろなファイルシステムが透過的にみえて便利そうですね。
もう少しAPIが簡単だといいのかなぁ

僕は、最近は、ライブラリ導入するときにはまっさきにUtil系をついついみていますね。

import java.io.IOException;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileUtil;
import org.apache.commons.vfs.VFS;

public class CopyOfA {

public static void main(String[] args) throws IOException {
FileSystemManager fsManager = VFS.getManager();

FileObject srcFile = fsManager
.resolveFile("ftp://username:password@ADDRESS/home/nakawaka/test.file");
FileObject destFile = fsManager
.resolveFile("ftp://username:password@ADDRESS/home/nakawaka/xxxx/zzz2.txt");

FileUtil.copyContent(srcFile, destFile);
}

}

commons configurationでのメモ XMLConfigurationでの出来事 2007/11/13
2007/11/14

Commons Configuration - Java Configuration API

org.apache.commons.configuration.XMLConfiguration
を使用していて、下記のような例外がでた場合には、

java.lang.IllegalArgumentException: prepareAdd: Passed in key must contain a whitespace!
at org.apache.commons.configuration.tree.xpath.XPathExpressionEngine.prepareAdd(XPathExpressionEngine.java:211)
at org.apache.commons.configuration.HierarchicalConfiguration.addPropertyDirect(HierarchicalConfiguration.java:303)
at org.apache.commons.configuration.AbstractHierarchicalFileConfiguration.addPropertyDirect(AbstractHierarchicalFileConfiguration.java:112)
at org.apache.commons.configuration.HierarchicalConfiguration.setProperty(HierarchicalConfiguration.java:545)
at org.apache.commons.configuration.AbstractHierarchicalFileConfiguration.setProperty(AbstractHierarchicalFileConfiguration.java:130)


ExpressionEngineをDefaultExpressionEngineにすると例外がでなくなった。

DefaultExpressionEngine defaultExpressionEngine = new DefaultExpressionEngine();
xmlConfiguration.setExpressionEngine(defaultExpressionEngine);


プログラムの他の実装で、

XPathExpressionEngine engine = new XPathExpressionEngine();
HierarchicalConfiguration.setDefaultExpressionEngine(engine);

している箇所があったので、それが影響したようだ。

java splitとStringTokenizerと... 2007/07/25
2007/08/03

年に一度は何故かはまるjavaの文字列の切り分け。
単純にStringのsplitを使ってはじめはよろこんで、何か、思い通りにいかず、StringTokenizerを使っても、思い通りにいかず、最後に実装をjakarta コモンズにたよってしまったというパターン。

カンマ区切りでためしてみました。

シナリオ:

カンマ区切りを行いたい。値がない区切りデータも受け取りたい。


ターゲットの文字列は、
aa,,bb,,,,

結果
StringTokenizer
[aa]
[bb]
-------------
split
[aa]
[]
[bb]
-------------
commons StringUtils splitPreserveAllTokens
[aa]
[]
[bb]
[]
[]
[]
[]
-------------
using indexof substrin
[aa]
[]
[bb]
[]
[]
[]




使用したソースです。
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.lang.StringUtils;

public class TestTokenizer {

public static void main(String[] args) {
String s = "aa,,bb,,,,";
System.out.println("StringTokenizer");
a(s);
System.out.println("-------------");
System.out.println("split");
b(s);
System.out.println("-------------");
System.out.println("commons StringUtils splitPreserveAllTokens");
c(s);
System.out.println("-------------");
System.out.println("using indexof substring ");
d(s);
}

/**
* 途中の値が入っていない値、お尻がとれない。
*
* @param s
*/
public static void a(String s) {
StringTokenizer tokenizer = new StringTokenizer(s, ",");
while (tokenizer.hasMoreTokens()) {
System.out.println("[" + tokenizer.nextToken() + "]");
}
}

/**
* お尻がとれない。
*
* @param s
*/
public static void b(String s) {
String[] strings = s.split(",");
for (String string : strings) {
System.out.println("[" + string + "]");
}
}

/**
* この値の取得が求めていたもの。
*
* @param s
*/
public static void c(String s) {
String[] strings = StringUtils.splitPreserveAllTokens(s, ",");
for (String string : strings) {
System.out.println("[" + string + "]");
}
}

/**
* この実装はたまたまみつけたもの。この実装だとお尻がとれない。
*
* @param s
*/
public static void d(String s) {
String delim = ",";
List<String> list = new ArrayList<String>();

int delimCharIndex = 0;
while (s.length() != 0) {
delimCharIndex = s.indexOf(delim);
if (delimCharIndex == -1) {
list.add(s);
s = "";
} else {
String subString = s.substring(0, delimCharIndex);
list.add(subString);
s = s.substring(delimCharIndex + 1);
}
}

for (String string : list) {
System.out.println("[" + string + "]");
}
}
}



20070803 H氏からコメントをいただいたので掲載

String[] strings = s.split(",");



String[] strings = s.split(",", -1);

とすれば「カンマ区切りを行いたい。値がない区切りデータも受け取りたい。」ができます。


あっなるほど。

java CollectionUtils - コレクション同士の演算 2007/07/24

jakarta commonsのcollectionsです。
コレクション同士の演算です。
なかなか使う機会がないので試してみました。


集合の共通部分(intersection, meet)または積集合(product)を計算します。
A∩B

です。

package ccc;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;

public class C {

public static void main(String[] args) {
a();
}

public static void a(){
class D {
String s;
public String toString(){
return s;
}
}
D d = new D();
d.s = "i am D.";

List<D> a = new ArrayList<D>();
List<D> b = new ArrayList<D>();

a.add(d);
b.add(d);

/* 積集合 */
Collection<D> e = CollectionUtils.intersection(a, b);
System.out.println(e.size());
System.out.println(e.toArray()[0]);

}
}