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

ラムダで再帰だって!? 2021/04/04

 java8です。

数年に一回はjavaのラムダで再帰をと思い立ち調べて..あああとなるわけです。

 

モチベーション

ディレクトリにマーカーファイル(目じるしファイル)をおいておきそこの場所をルートまで辿って調べたい。なかったらnullを返す。

 

コード 

再帰のためのお助け定義


public class Recursive<I> {
public I func;
}
  

 

	final Recursive<Function<Path, Path>> recursive = new Recursive<>();
	recursive.func = (p) -> {
		Path path2 = p.resolve(MARKER_FILE);
		if (!Files.exists(path2)) {
			Path parentPath = p.getParent();
			if (parentPath == null)
				return null;
			return recursive.func.apply(parentPath);
		}
		return p;
	};
	final Path fpath = recursive.func.apply(path);

 

 

 参考

https://stackoverflow.com/questions/19429667/implement-recursive-lambda-function-using-java-8

 

マーキングファイルを探して2 2015/04/05
2021/04/17

javaです。

前回の
プログラマメモ2: マーキングファイルを探して

ちょっとだけ改造
 public static Optional<File> findMarkingFile(URL start, String name)
   throws URISyntaxException {

  File file = new File(start.toURI());

  Predicate<File> predicate = (File f) -> {
   return (f.getName().equals(name));
  };

  do {
   Optional<File> optional = Arrays.asList(file.listFiles()).stream()
     .filter(predicate).findFirst();
   if (optional.isPresent()) {
    return optional;
   }
   file = file.getParentFile();
  } while (file != null);

  return Optional.ofNullable(null);
 }
 

マーキングファイルを探して 2015/12/28
2021/04/17

java8です。
簡単なアプリケーションを作るときに、よく悩むのは、設定ファイルの置き場とか、作業ディレクトリの特定なのですが、昔から、マーキングファイルをおいて、アプリケーションから、そのマーキングファイルを探して、そこを作業場所にするという方法をよくとります。

マーキングファイルを探す場合、簡単な再帰メソッドを用意して、特定のクラスから、ルート(parent)に向かって探す方法をとります。再帰を使う理由は、自分がわかりやすいからなのですが、毎回、2つメソッドを用意して記述していたので、それが不満でした。

で、今回、java8に用意されているものを使って書き直してみました。


以下


import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Predicate;

public class MainTest {

 public static void main(String[] args) throws URISyntaxException {
  Optional<File> optional = findMarkingFile("__HOME__");
  System.out.println(optional.isPresent());
 }

 static public Optional<File> findMarkingFile(String name) throws URISyntaxException {
  URL url =  MainTest.class.getResource("/");
  File file = new File(url.toURI());

  Predicate<File> predicate = (File f)->{
   return (f.getName().equals(name));
  };
 
  do {
   Optional<File> optional = Arrays.asList(file.listFiles()).stream().filter(predicate).findFirst();
   if (optional.isPresent()) {
    return optional;
   }
   file = file.getParentFile();
  }while(file != null);
  
  return Optional.ofNullable(null);
 }
 
}


縦と横を入れ替える 2014/06/08

転置行列 - Wikipedia

javaです。java8です。

以前から、そうかなり以前から、エクセルの操作で、行と列を入れ替えて、ペーストするやり方になにかしらの思いがあるのでした。

たまに思い出したように、javaで書くのですが、まあ、すっきりしません。

groovyにはtransposeがあるので、さくっとできました。
def ssss = [ ["1", "2", "3"], ["a", "b", "c"], ["A", "B", "C"] ] ssss.each { a -> println "$a" } ssss.transpose().each { a -> println "$a" }

結果
[1, 2, 3]
[a, b, c]
[A, B, C]
[1, a, A]
[2, b, B]
[3, c, C]

縦と横の値の数が一緒であれば、配列であれば添字を入れ替えるだけで実現できます。
これが不思議なんですよね。この不思議な性質というか、これをコードにおとすとエラーチェックしなければすごくシンプルなんですよね。
ループとか繰り返しとか、関係なくて、もちろん実現するのにはループを使いますが、この入れ替えるだけが、何にか不思議で、うまく説明できませんが。
とりあえず以下
package a; public class TestKaiten2 { public static void main(String[] args) { a(); } static void a() { String[][] ssss = { { "1", "2", "3" }, { "a", "b", "c" }, { "A", "B", "C" } }; int len = ssss.length; // 行と列の数が一致していること String[][] ssss2 = new String[len][len]; for (int i = 0; i < len; i++) { for (int j = 0; j < len; j++) { ssss2[j][i] = ssss[i][j]; } } print(ssss); print(ssss2); } static void print(String[][] ssss) { for (String[] ss : ssss) { for (String s : ss) { System.out.printf("%s ", s); } System.out.println(); } } }

結果
 1 2 3
a b c
A B C
1 a A
2 b B
3 c C

java8のラムダ式の練習がてらに
package a; import static java.util.Arrays.asList; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.IntStream; public class Test2 { public static void main(String[] args) { a(); } static void a() { List<List<String>> listoflists = asList(asList("1", "2", "3"), asList("a", "b", "c"), asList("A", "B", "C")); listoflists.stream().map(list -> list).forEach(System.out::println); // 結果の入れ物 Map<Integer, List<String>> map = new HashMap<Integer, List<String>>(); // IntStream.range(0, listoflists.size()).forEach(i -> { List<String> list = listoflists.get(i); IntStream.range(0, list.size()).forEach(j -> { // getOrDefault List<String> l = map.getOrDefault(j, new ArrayList<>()); String s = list.get(j); l.add(s); // putIfAbsent map.putIfAbsent(j, l); }); }); // 結果の出力 map.entrySet().forEach(e -> { List<String> l = e.getValue(); l.forEach(s -> { System.out.printf("%s ", s); }); System.out.println(); }); } }

結果
[1, 2, 3]
[a, b, c]
[A, B, C]
1 a A
2 b B
3 c C