中文字幕一区二区人妻电影,亚洲av无码一区二区乱子伦as ,亚洲精品无码永久在线观看,亚洲成aⅴ人片久青草影院按摩,亚洲黑人巨大videos

用java8函數(shù)編程生成字母序列

發(fā)布于:2021-01-21 13:42:33

0

255

0

java jax倫敦 教程

我偶然發(fā)現(xiàn)了用戶提出的一個有趣的堆棧溢出問題。問題是:我正在尋找一種生成字母序列的方法:

A, B, C, ..., Z, AA, AB, AC, ..., ZZ.

這可以很快被識別為Excel電子表格的標(biāo)題,它正好做到:

到目前為止,沒有一個答案使用任何java8函數(shù)式編程,我認(rèn)為這是一個挑戰(zhàn)。我們將使用jOOλ,因?yàn)閖ava8流API沒有為這個任務(wù)提供足夠的功能。

但是首先,讓我們以函數(shù)的方式分解算法。我們需要的是這些組件:

  1. 字母的(可再現(xiàn))表示

  2. 上限,即我們要產(chǎn)生多少個字母。請求的序列轉(zhuǎn)到ZZ,這意味著上限為2

  3. 一種將笛卡爾積中的每個字母與先前生成的組合字母進(jìn)行組合的方法

讓我們看一些代碼:

1.生成字母

我們可以這樣寫字母:

List<String> alphabet = Arrays.asList("A", "B", ..., "Z");

但這很low。讓我們使用jOOλ生成它:

List<String> alphabet = Seq     .rangeClosed('A', 'Z')     .map(Object::toString)     .toList();

上述產(chǎn)生一“關(guān)閉”范圍(java8-流發(fā)言與包容上限的范圍內(nèi))的字符之間A和Z,映射字符串和收集它們到一個列表中。

2.使用上限

請求的字符序列包括:

A..Z,AA,AB,.. ZZ

但是我們可以輕易地想象將這一要求擴(kuò)展到產(chǎn)生以下甚至更多的需求。

A..Z,AA,AB,.. ZZ,AAA,AAB,.. ZZZ

為此,我們將再次使用rangeClosed()

// 1 = A .. Z, 2 = AA .. ZZ, 3 = AAA .. ZZZ Seq.rangeClosed(1, 2)    .flatMap(length -> ...)    .forEach(System.out::println);

這里的想法是為該范圍內(nèi)的每個長度生成一個新的流[1 .. 2],并將這些流展平為一個單個流。flatMap()本質(zhì)上與命令式編程中的嵌套循環(huán)相同。

3.將字母組合成笛卡爾積

這是最棘手的部分:我們需要將每個字母與每個字母組合length一次。為此,我們將使用以下流:

Seq.rangeClosed(1, length - 1)    .foldLeft(Seq.seq(alphabet), (s, i) ->         s.crossJoin(Seq.seq(alphabet))         .map(t -> t.v1 + t.v2))     );

我們再次使用rangeClosed()產(chǎn)生范圍內(nèi)的值[1 .. length-1]。foldLeft()與相同reduce(),不同之處在于foldLeft()可以保證在流中從左向右移動,而無需折疊功能具有關(guān)聯(lián)性。

換句話說,更容易理解的詞foldLeft()是:命令循環(huán)。循環(huán)的“種子”,即循環(huán)的初始值,是完整的字母(Seq.seq(alphabet))。現(xiàn)在,對于該范圍內(nèi)的每個值[1 .. length-1],我們crossJoin()在到目前為止“已折疊”的字母和一個新字母之間產(chǎn)生一個笛卡爾乘積(),并將每個組合連接成一個新的字符串(t.v1和t.v2)。

結(jié)合一切

以下簡單程序?qū)⑺兄祻闹写蛴 .. Z, AA .. ZZ, AAA .. ZZZ到控制臺:

import java.util.List; import org.jooq.lambda.Seq; public class Test {     public static void main(String[] args) {         int max = 3;         List<String> alphabet = Seq             .rangeClosed('A', 'Z')             .map(Object::toString)             .toList();         Seq.rangeClosed(1, max)            .flatMap(length ->                Seq.rangeClosed(1, length - 1)                   .foldLeft(Seq.seq(alphabet), (s, i) ->                        s.crossJoin(Seq.seq(alphabet))                        .map(t -> t.v1 + t.v2)))            .forEach(System.out::println);     } }

免責(zé)聲明

對于這種特殊情況,這當(dāng)然不是最佳算法。一名不知名的用戶在Stack Overflow上給出了最好的實(shí)現(xiàn)之一:

import static java.lang.Math.*; private static String getString(int n) {     char[] buf = new char[(int) floor(log(25 * (n + 1)) / log(26))];     for (int i = buf.length - 1; i >= 0; i--) {         n--;         buf[i] = (char) ('A' + n % 26);         n /= 26;     }     return new String(buf); }

不必說后者比以前的功能算法快得多。