pax_global_header00006660000000000000000000000064134207437440014522gustar00rootroot0000000000000052 comment=84c607c51d9febd0e0345647b753bdb70d591381 vavr-0.10.0/000077500000000000000000000000001342074374400125565ustar00rootroot00000000000000vavr-0.10.0/.gitignore000066400000000000000000000003731342074374400145510ustar00rootroot00000000000000# -- Maven target *.versionsBackup # -- Gradle .gradle build # -- Eclipse .classpath .project .settings bin # -- IntelliJ IDEA .idea *.iml # -- Visual Studio Code .vscode # -- Mac OS .DS_Store *.log # -- Java hs_err_pid* *.class # -- Emacs .#* vavr-0.10.0/.ide/000077500000000000000000000000001342074374400133755ustar00rootroot00000000000000vavr-0.10.0/.ide/README.md000066400000000000000000000004601342074374400146540ustar00rootroot00000000000000IntelliJ IDEA ------------- The following IntelliJ IDEA settings contained: ![Export Settings](./img/idea-settings.png) We reformat only .java files. ![Reformat Code](./img/idea-reformat-code.png) After the code is reformatted we have to generate sources: ```bash mvn clean package -DskipTests ``` vavr-0.10.0/.ide/idea-settings.jar000066400000000000000000000120021342074374400166260ustar00rootroot00000000000000PK ՅJ codestyles/PKɲvJcodestyles/Default.xmlIOI/NHMUKMUrIMK,)QRзPK PKrIcodestyles/Javaslang.xmlU0WDT]iHű-۔QDS UlK%ګ;^nU[hS>VS[`tEaiPH Xr}n?%>%C s p\.TIiO 4ʉsTDuhghhC%p߄]pUf ;/9 &5 L"-$3$CzN-utrbUSa7y%m"L3H {#m}Æ(^BCU>àMnhh,A͎L1لVkblu9rS}2/2.w伀."Sϥd lAۧc!Kk /+Ld5 \3Q *u21pMq oip{S1bSq<Ջh޵k1|y2+b639.6PKa8=PK ՅJfileTemplates/PK ՅJfileTemplates/code/PK ՅJfileTemplates/includes/PK/K'fileTemplates/includes/Vavr Header.javaeRak0_ȧvW퓗f̬8-QsH$ͿqFÌ,;98ϗ*>[WQQ0Ιx{UleC}afq˭L_vݷ8>J\vTY=!T)23YF>M٧dz x􎄃jn VR9t-+]% y%p%:@(?fH#c=C].YӦ'ݒsg+w'NDj'R[5XƒԼ ˞u33@SwE8)Y#gi>$/idNM̱ZcM$${4{cru68IغJBmΒ\G%\5!4HV#td­:XS PK*5PK ՅJfileTemplates/internal/PKmFJ*fileTemplates/internal/AnnotationType.javaS.H,*NP K,+RHMLI-J,KTRLSPptvtwsuUPSS@RUPR,HLNLOEVNK*(MLVp+I-JKL)hPKHWcdPK+J!fileTemplates/internal/Class.javaS.H,*NP K,+RHMLI-J,KTRLSPptvtwsuUPSS@RUPR,HLNLOEVNK*(MLVHI,.PK(%<`PKjFJ fileTemplates/internal/Enum.javaS.H,*NP K,+RHMLI-J,KTRLSPptvtwsuUPSS@RUPR,HLNLOEVNK*(MLVH+*hPK#_~PKgFJ%fileTemplates/internal/Interface.javaS.H,*NP K,+RHMLI-J,KTRLSPptvtwsuUPSS@RUPR,HLNLOEVNK*(MLV+I-JKLPK#\^cPKpFJ(fileTemplates/internal/package-info.javaS.H,*NP K,+RHMLI-J,KTRLSPptvtwsuUPSS@RUPR,HLNLOEVNKPK8dKePK ՅJfileTemplates/j2ee/PKrIfileTemplates/Singleton.java]0} _p o`ֲԦ-x }w+?F|3*Ԇ`-e [‚Am);" K$$Y0\JIKEK`,Z<ޓ I 1k@\2S6Ȣ<zŐKGX8>z.ǂv2wθoUojX5;'C tA]1<9@>L[iAlt?X<)3k^cPK@MPK ՅJ inspection/PKrIinspection/Default.xml @F{e ^Ͷ(MrlaW>L"j`sqSm3hK$) CJ,( uxB!ֳCnLy 1HbTz!J`FNF=zb"\W,7yi<{;#k6çb_=l#.z)QhX՟b'8m'pe;PKPKF0K installed.txt=10 @ݧ Stt+1J6 GB%o<ucy>tIoYA5,$RJHj jɳHj(3wy];.L PKW5jPKF0KIntelliJ IDEA Global SettingsPKPK ՅJ codestyles/PKɲvJ )codestyles/Default.xmlPKrIa8=codestyles/Javaslang.xmlPK ՅJfileTemplates/PK ՅJfileTemplates/code/PK ՅJ/fileTemplates/includes/PK/K*5'dfileTemplates/includes/Vavr Header.javaPK ՅJ^fileTemplates/internal/PKmFJHWcd*fileTemplates/internal/AnnotationType.javaPK+J(%<`!OfileTemplates/internal/Class.javaPKjFJ#_~ fileTemplates/internal/Enum.javaPKgFJ#\^c%fileTemplates/internal/Interface.javaPKpFJ8dKe(afileTemplates/internal/package-info.javaPK ՅJ fileTemplates/j2ee/PKrI'3 fileTemplates/Singleton.javaPKrIٳv' options/code.style.schemes.xmlPKrI@M" options/file.template.settings.xmlPK ՅJ inspection/PKrI inspection/Default.xmlPKF0KW5j  installed.txtPKF0K IntelliJ IDEA Global SettingsPKvavr-0.10.0/.ide/img/000077500000000000000000000000001342074374400141515ustar00rootroot00000000000000vavr-0.10.0/.ide/img/idea-reformat-code.png000066400000000000000000001441041342074374400203120ustar00rootroot00000000000000PNG  IHDR)iCCPICC ProfileXYXUK)]ݥt7PPD@PPQAE(X *6{}{5kk C5qvqOr@ ^>ё:-|ĦZZ_h k{F:HR !TQ@B lm̲-{[=k@"@!qtAj 5}|`AuvEl%xNǦWV!EGz%?.aC@]0Ĕ(B1noXc%h=t07C1bCtvi-[Ř`oR}8.<|NVo\m`[?L';mo9Z;/,bm79 ?v[a ":@{_o~_pn:tmwfFZ#~F4Dn;Nq@fLwcm sEoARv!$Ďw pm;?tj@*G[q[-Bka059FY2Fw;߽ p8c!Nu(@#3C~w\=k(v;>Ֆ-4ҿ 0Z3[#Vb4P(w  H`QOt0Zo cp{,&#'vXx[_k"Y5r@:t#ҹ̄W[3wo[BP;AuշN""IA1<:nc#GVZFͽ}{lgCLE[`t;[&,'|bIq۲`S] YԀ60 x C9ǃ d\pT 2h-`qs-X_DBܐ $Bʐ&dC @P,:BP)tBmMh@ #0%sB f=$8΃K* ߄qx ~ @^DQF+GH~$)F+H;|0:71Lf?0sӌy,c~aXq* c3&ln_q8NK\0.ww Wfq+x</[1LI%|7~ ?_#P C+!F(&\$td4dddVddddg͑ %& '&O%/!BG3 EE E E]iotbz)c)(k({(P~ҦrʣEjHO$}ef=5 ;uu15K4d4B4z4^4ihhѬZцH;@O'Dg@KNWMwnף?H~ `̐paaQё1q ab2a egjd`ɬǜ|yyEŏ%e;+kkk s6  [<[[;{{#$!aˑQ1ıiy6W01.nznM c܋<<:<<%:e#dcq#NZeS%}(JfIE3KAp+`ebUdZ: ڦ浭^;vvv?uquuvXT4,yЅ%ȥzunݙ'I3AqysʫkĻ{G[_mc ~~~o4J>WXԄl:ևs,ؗ+O=1Ub^zRѓ륁ee嫧|OUhW\̭~:3Fgqqկ:sN\yքL]pV":.nK#/^r>46,^:h{Mڕ˛rV6Ӷv7j:x;:;Ȼһ6Wz"{nܜ}z6ߺsݎՁ{ZRiXqQѮ1?4y88n9>:0GS}yd䏧)ϰro_EZKMx{웎ÅEŹo,e}W^>>n|:s/++/}ƺv;ߝ_ǯ׳H/UAO5P@?9q;)rGo `C'4d()jhhhiv3_bŰywrp^}+nR⫔9*y]hr)j*Z>:Ѻz' -o22׳p ΰ)oAWӘnovǰgWw$?@ b!aG##"آI/{bc3MK *sLzgCdYّ9չGÎV <[qΉ撩R2rSO`$8whZ-E󺽗/WmȿV-cnv:LJgҷџ~@nA@K\LRhMw8GH(BMRR\R̹X8y=~?)RNwp;]s>p/H!}1z'LKlNzE8UTqr*ij#k_(Q~rlk9]FNLzwI^[M}gJ %04rgډ7'?/k^e,²ִm 6nԈ Xk*U''dtAB3"B2::ip&|A$9!3 Z1tX-l8 vG%qKx|@$(\.CDp1JeT* )Z&f6W|^{31|eLe"2bbƲZ&=c.7ɓk@`Ȋؘ]$eZe{_(|T(3JɨKkihitvUgD:KpR!fksV36l}H,j;yq{Mu;_83.7L,\2B"R4M=f!-"!=;^}EߦX8(ޖirh6P.+ySE5N/`?MTvn?[;\zzNw7^pH8=O*~!3:3>'>0dG+?$tW$ Ah?}@{U΂'.HryBwL/4bѸSqٸxr?I$dLddis┕TT8b5NAhh'qUL:L3̙,,llSEƜ^܆<<U|\kB-§EN*(3p "z MLUa;qX Wſ!Β"ɞP(֥rZ$fnH[LI@S69 $96=[~ܙZmZnpudvv+~; 1=|o}4p҃q Gi/<79t9 S Ӫ3گ4_+Y[{K|.]>s+`יkkm-?CGϢ_R6|7/'u|@`_ll|BB~llY& ]g묡}?-ddiTXtXML:com.adobe.xmp 485 435 @IDATx `UՕ>A+`D"b,i-6NqtZ)PԚiCL4`#^@k{;'{n^ܐܽZkO:{s$            G4@D]4um s^l|c#A@s si}8%@P!.v{ LA% f V7ks in }3/mDA pSڂm#M @E-Հq#mZ0A@h܈@y#lд@FM0,M@khCPKRv<(b@A-D[n Y0%lhI۪ A@VZ2ص햰 @\~&A #\04ې4Wj.ßhJbp#lROn~+TSlJ]csPS@h/ߘ::MZoLm5T.~TFkrC p#pQ6MǼ=7}u[ SzRAfDAiֳmXmFƶ^s0Nl2m/EW@h-'ͥcVĻQ1:Orlt]A@ho6Ua5>ce1KcWNXѮ@B  4p9ѷiqk{cٴfiL[}| ;%n?vuE&F)_];//>d's"ڟM:Z+P4:|3v2'@_[]A@@sdV|+ce9gmT5Am%;1xVv|p_uu-i>I=A@hd`qbۗN |+]+/Ar@U=GyKOڷ%;Y0hо)ysVs-Auhbꊿ|ɝU+];@tKOطӵ9uTY:8Ny\JWhzJ_rA@N/=+,Wf :x o+}%3ږ[2hbNJfٕYDUutu[v%A p|Yx,>V\_u-2]/P]s] k79NG'7B9uR%s]h'|MˮA@C.PS2V23Ϫ̼ktqj7AJ؞OΊfU_<]O%@ 6}Z}uYf ө=_zf]ٗLy˶m3fLի!IOnr|o -wԩpAjjoKt6'UzJKO͹mq9ԱE3/=3߮ˬh[C II HPѹ<ށs$t{IY̷+2E2͇}ݥK_w9XE  1 Lty$}s@f hRipu]䋯͚7WPfuJrnS*W<Pd{:cF>} .py=P޽;>7h+Ʃ)CؕT!ީ(Dѥ ^R!x zFߍ' 놘&ik:$mtCTPU[o?Y [+TAQ\Ft킸;F#[%Ic|;jd~O1ե `ϝ|_RT_91tӜ԰lt͹ٖYn[nm#$TANϬ*纊VemP2Ǐ o_Jx!@Ak q y +fŒW*h8#VW??цoOD!t~: Y1[=Ojkcp;1e>a"w~K) ?7I1s?ǰຘ3{~PD{Ng_ny=kjpz@}  #pu:S篠Kt zwDEW9.tՃl Μ:+5"]Kj:.XEQ rn~t PыßF[ _WCy=~}o1.)%zQ%j@?5//RSú=~x- %A33d lG̦df]s)u]sf\Vf<Ӫ9Ysp`Nʜ=d޲6Ɔǽ uiǔ%ݺ=̫aզU`Y7:V6!Gulׁ?Fu906>3ƚ! m:׽)|N3?۾|At+/fÂbƗ?[|=?/KŹ'%߈oy8SLNI bly߀aWG/? :,ǣwt,e?g뗴}^:Q8i>vO! {ݕXr&4 ~=,;0ip7z2O}uwvA]2_.2&% /l]~콸 ~OE,aѯ@R sŹ:K_Ehkk6,W ɱ=N_N~_w&Շpg.҅w}r܇ۺs;boKީUҍk'V왓8zjo!;ĕ/a0{1!ém>ur:"Rôھ ݎάԹ?x󲏨ߣHғhȸ CF)(㶯Wy=z!]LJ*0:$1S |3OOgǡӺ@FhlP6wY++˭dFuȐ!;W~WƤe-Nģ$6k|O&4?Ź+.yub6}WN{ƜǾQj?{fR"Ƌrig;+:;c_x*0ix%j# HL_:Omfm'n+Q=u{%2N;7Htn󥖢v]]ٿ?Y':'huVWWCRrh$l5nV9׍vwS8:UG zC)?B>},rm%=@]kj='B Z?tpefU&ɊosRϬӠؠP#)sR,ȩkx+ 1T:qqơ=ScI5?ؿNhG9H!~URe3_v9cVOv4 eEY:O\Ux\{J6& Fs.sF+nneúvXמרԕlckgckC Fo ܑCd7wxI]]wL|adCUw8Ų?cg.̱o`]mrtZ)fc8s YwW8V׊O; 闟@J:leSWSaǞ"p~fh]߾t.!"GKۆơ=ݪ\Mw@#l<;mÛGaFw@%޷0?Įi~ >.|\߭S/'c6r}XtZU)YZ)rފx4wRţ]?dBTGO?=<ڄ>_26y)Ȥúlge TV_[ּB?.a].t'cEIǫ+WYU5y?.$5 'I3LQx:t\MOtwm['WrBO}ծDvla۠{ӴInс$}cE^6l✤ыd9 h='LsjUtc HroULUn+| ѽYƎ[hϑÇӻAYbUn橲9׃Uκ]Z?uKRso_ 5QTUFTYWeL > Ay7;u+W,wS[͍+|ܜ)`'UKPv%#|o 'oYy\ϴRn頬;iG1䜛iUVu^ʠ䂀 pcj<۹/qD_+Ze\mݜAY)]hsuOVe9>JKKeє$@G?3RAUlYy*6tzz~ IIi@5`FA@~8]BglKuڟ@t٪'玵fp2:OѬgNJno'eA@G@cVVrnΠS=ݎLTYYH. ลws窷_$z~m5gPۘ`s%S͹ҕ\ P^V[hL;Ӓ}h-߭oss<ǫ2wQ2UYf]SrZjlP'6mWYvT*W:rfū-+rvZWZ1wƨQs$&aΨQXWϬI^ k_ce1orqKىJeEVn^+ذ̀kXa;SOY%au;lX7梭\~[aцxks_sYwjW6l30WaH}GnuCvV>G*.Zgv_i:ǢM7B{oDB;_VssC;'5ϛs]f(jJz<;}^-񞲹SzY}9:JO嬫[p Uc'{bKNQeW ,C& +2|W[( sA^⢳虔wb =8Ua ԄuC„dOzZ!pX'@,GU?4H+ /T!2zRڟJiO/ QQQǖG7v,ʊyEº`Drx~2ITź.u2ϩ>=}GNey NWϢ={#N}.5߬ɚH$%x`>wꩾ؍چ||▷~ey?|>LsDLo;v^To==/Q;[&tf1Gy'z+^۔eI]tt5况DPЅz $<:OgډNr[ 8w. { NĢW^$׌#<$#s"XSi.־ _] `Hk+1CJ]Z_)wSmB=}l2sXԣ/-a?TLq fmC^,1p79QĖ}S}a.{"Yd.9Ǽx쇧׊Ueui&"3UL7 s_geÕLd9ƃn|$&ogb˃p]633Aμb 71U=%|/a wۋy;æ5_57G~,k PkMxyϰo3MiӑnqX"l44ԹMʪ%yJyKn_+ShúUYz@soP]e01c&5ބFFX_XK :JX^K) KyJ&wj1;vJD\zrLlVھ,U՛ǎZr18]# ?"j!,PȐC͆}1O`l{ _L>ÎVfgb~ex7s_eBL>1IvaXH?$k1wvmBY[Cfm"䑮+ 6}LaR؄=; + v#Rﶭ s6cgф vo7zFTX>yYEkksXiۿXTsX1faldUY<筚4Ƨ} (;;VX_OJWE+f[2(9:gU3_/3]_̹qR~x<ڲݨWMzzNY(%7n@y2##Q>J.?e > IG5Sߊ02t@8JPr9C\ )%jEh?Li_(7IP;[r!wϣش-u fMRh6&* vX_'cyK4*R3,ms5ˤ'Q9\å4?TbzRD[d:v}LJlډxbPa{6-;G_:<ʦѼtb~WՕ+zjXr5r^,D3`]A|Ӭk|TGOsLO1&$JLʽ 9J7@*U,g>8s!_)yj)5qUO_e3geVU苇BܷC820u!&'we! 𮑆8-=PDAeKW* [tpnVFݍvq^r8&n߳.:+h:CWd 5QV<4v%[0 ׋z9[ƿgOY\+ޢA5mOŪLz^am {u{®q4ogC)v+p`6|ѵŋb+U YtBX89}5kau!UW>6^quaގV<+fҷ˹'s.O1a}jIzJ.g:h<jX?^S4^Jv{Z>$cSJ9 OޔpY%]Re%g+8+a+dF*GYy)*,Ǜ'Ӽ{R"5|WŪ,G}cIV?ga%ؙokSQ6ẟ</GG\<:ejy>pS'9kJkyM/.>&M(dNȢ{\g[n*[^5vTMC̩Lq;;p|Ntz7{]3́劧N}q@#*)ڜ+ʕ\/3O?,04AiK@SSc 6| r e-~C+16֠I6HN,7;6e.<ԸH~g˛/*–Wu]ZWm-\b}9`+sa.'"=}"͒;$s?ټ d"1m@}fn\p|,i_޽{| v?}<KT^J F)Ϯ[ytB9VCGDa(G7IKǣi}q2zxcb=@l2bb_Yz H”GAj|Pկg|gmDžqWg"}BCq^6r6oásO'C¼|@B@*{+-Xml'؅DLZO/f$<l+:@Z39"wt9e#~zO)u[wYot5*Xwye̝qx?ed. F&].xq62fRXzW$ EYlQmul [ BfptS7{f<5YCߊŸ~EkIx<=VJ8~LĊ?Z#}01lGW ,Z}qd%+NabFJ,fLtUOA@/jWyGfX)7 Բ/pl5._&knA"s@v>B5 ƧyɁOa"p]NDH7Iw&ӈIlt9|X[Q2A@ ʦ8q؇\jya>`N>\<ts1.rp"&6w5j]Jh:T!K| `'o"/' +/@³kI 7ͣ0IC ܰe(߀PtL{ˮUU+_\ܵXnO"IzXbR^2*G<e^e%}u5^@]h /ٲVs޹HL;qwʅ+hoPS m ˹} :cbԄu=ILaWEA)%N3 z ` <#;Q̓ X &6x9EgJ!.6}סa'~MBMEϾ 3@X;H- 渕γsuV9ʹqQ4-Esz4t9}7*Uj* ⵉztkWJ/D]@lFrZF jj?Gcw4#* doC$ uy::7OTY4h[NJ)ōOH(npU"d#r Q А  %}ݘa*?~l>rvylg,\y3K`v͜cްdR]tdFVQâ1-r^z&d]dž륌L99EY^YbV-׵_/vN6dt0-"mهF`ק7* xlHL_̀;^{" kd:ȆwCP 1w~Zٰ~}1&$5edH [Ic`<ea^z"AnY,~3K_BIU^8ם2GNyIYmFVWͫ!izbS oflmAF73( d#^6;W2/ /[] e,0~)c/_'j}+{XbUY]Ckf`_(l} HIn7CODꌭ~3_5WۭDI)c3B(h5LF 5* 1뻳Okd̜iҽ8D!C#.K%'MzNgYOFI8zQ11k^BVD,})Æ: %yy(>sD)ϧn3_>ҥ7nE,GI/|)ކXEE$,w`CDGy1R+~Ool_w O\}Pv wńkXՋ׳z:SxdOZQS$FwϭB7Uջ&^䵵Z$ p0/ڐY@:5W-nz5 g zB# i徾p鷻h&~~֯ y fu) @E@o/ Asޚ^eDw d*7"=*;2SIeş+Tğ7P! #GVJO7'Ji-+7UdE٘` oӫ_e71x9#ÚoÇøXm1ڂ`E8O{+Cޟ0wL yu-Ii^ 8( 7Ǯ/`3Z >(,.WcGQ1=%k_"ٯ"xS<{ᏱvK>7_.!T;6%cdZG6zN\& A[d?6q ]2bArs5W54醚 8vV>,_XF/@IDAT!Z23`y,>2cUVLI%ٴ  W.q ~!Y)w !!٫?fa;w:S@,] nZQKn)<:S5p[ւ٤i"yj!7l̃H\ s#N ofrFu]ez(h[^161Vyp6Nujzku4z]Co_ %_Hnox1t8u6^Az\^5瞗9d΅J2Ōz dh\ܒU+u3xuͷ͹*9@pӧONyЧF`m͆zյ0. aAm/Ρez8V_)b3mG "bc=堅RDy91x Yqom@z166w%7Ɣ+{~~~toTbZϙ6yU|UY4h[NJ)YgX mڹ_ÇoPd A@rcPk:%%%֭.tɶW\'!A~VӏyON"Ҕ p! A9HܹsHNNFxxܹmreoE)\1胑_$~ L\c5< SO3,ڂ $ :׭Fa]i\G+l,y ^ČvP鼕ⷵs|ڈǧA@e1ad]$e,]yI,gdž)(LeI@MX7$LHeE ab0"90^_&5dql(@Rl bjCFw36ֺ~Tx,vAjQR/C#c*) _:f,  akk<7`<(#GbV-2dX+r~(b>Dc g0'!>kލyk##ٵon̜W1oMUSCLl reVܰ9'8]_}GsXI`L_\h4^8 ^pj/h܄4y;Vȧ@ڕFFD9mv&6b+Hۗ_BbS I~ex7Ag2/ ZyOZS=W ~)b(ހe,@S-r=R_|CfF"!FWaxDϦʂw5 3/A@M~RZ0F*-0; %yy@d8Nr? %`y()*Aj/V.t̚ ĻҀ5ٯ| IcIO$bSՏ|RZ;0V#DoZtK(+ܷxCaaˏXZ6JA_[Ԍ!lAc8~gY!A]# A&ZiwF6#\<=M5GwC|̟_/s6'$i==t'CJ=̥(~3SA$=nuM{eE~_g>dԻP$>絯r3d4&LhSP^LJy 8dn~ ^es xrœZy.2? w6vIj[P7)n]ZO]`iIIiK%Ӧr8O{R+Cޟ0wL y@ gr}WeW!gK bFq)d.G^A1 0gL_z2q$EyX9.6શ͂ ìk]T|)%1힆|( [] ]ռc PVIR:Ϯ?`J(,Cɹ*T_DЭdpI&kd$ϯ7]~kNNuyj}L6OOU PMzݾЊKcX`FyiJmІ>,x  ^wp[LO6B_Ū%HL2db&]mu1"q2dݎ ~:Omڋ)ϱ$s.\ϼ!c\z= ЎV::ϊV}uʃ>)ǹMEi^KeW4=Ih\heE Je|LeG nݎO_ A%nj$A=!peˬ4D *itw ͎6%  @ A9A\A@ r A qCA@,  $HP7A@ r A qCA@,  $7z@L:u /_F]sk:tΝ;O>~ڂpA@ A2*gΜAxx8JSL\6Hz n 4 ME_rqqq eƥZ:}]CH9;խ~ۘ8,a%Hn& RUu}tĝʉ2;g:WHQc)\jX_n9a^ ZyiGnrOI'O7tclXv-Uѐkh'r^]G+.N=tI߅k,+ν{p뚰^ߍؽ31z{wnëYpĨZ6o{pZw>cm/5/6F }`{)mN[6-ꂀ ! +e I}bNrT>Q܂ &adkUuolǎ>­3' U8~z sp@d 5:8_넁KT]B[9;|pYƺ]‘+;!68 ^@\TLgؙ4?/Ýʶ R ሎ~zSG9p9[GJQQUCUa@lJNdEF#n`g"a׳[PuUV:C~y|6=YQu$.Vנ2<.] V]BWC~AH^芋>myJZ ʭjQ J$=qSPT9y 'N\p{ )Xw W](4[b3_+G~lD<\yX e ǥ{F{2W08FHZ~Wf|;5a*(+/ۻ w[0_FR3mFVeC0mU`淑W7ߞ 8oƖu RA@z%`ÓGd7֋+3b 6PTeĤoいhh7"gAK'(۝t3WmY4,,A@ha$(07|EA/; D$pKGcW>^ /{+>)9 (r;(;PX\Uv1A%a" 8~VŽ0i+H9 ن_؏q/f_ez8Y) 犑6l)ZV7Ӿ4acF- O1΁8ydoݍDG^O_=Ҥ;^nC0/42LnwbhQ) #'#|6V){rPp}fŐHؤr nPH1ɸ[V OZoTh%x 4DcoO@#mIp)ZX\QQCp!0z)'o8**|qBۼh FcWCО{}F}e>>NӦ.FFJGO@jtLպJ#F$$|LZ[J}ČgcXk8p*hqލؗAm GZY)70ި=ʓ)Ugϒ5<G)oHZ =A+QE!#zaہc89) $aaT|hc}1lx:ObӪtGNךa FLнXWqHׯ3}}zc);_e/,ҕҐ{o֭z$֡<Kw8q6 bE7تߔAJ@߈f5V{>)Ɲ)Zǟ|J. -Fgɀ;>bZGNV\fbhŷ7캅0>[7io۲rpf$|yy (Wz }qc[uņtiA ȷ`R ЭW zu[CEH cު0GÝk8OGwz>S(s@{pKl( |tG8?U[n @" Aun0"%֦k(=#} zyИ{{ ^).iۇv=-c02٨^QD^ 68 3{vbSn G Bؕ3(WbIcBT9۷&1="Ӈ>^UYtzc_r2ޑ:v +W)"wT)\AGBU80H.x~(?ߙU)CB)m~ZѷFGx55Gɯg@ 1^[=jX~v@,V?پnGg_ovcԱƅP[jOՔ| @+! A _(J';"ڋ-{=n R+\PԱ޻ϴ s X<] VBD_zk(Ox+MN1 c۞n<N {qODi;;aS6( SIԁ}ؑ{Jc'oߠA 8p ' Tlމ^F?#lSM;(]PEݼx*۶ Ç߂\揾@zgI o30P-_Жw7ܮAγsupSV93ӊǹ:XGѼӦhUYϙ晶ӧ_ל3O3])*빙2PpXv<%YGRP УG3 (Yy+%양yIZ׿b=3roh#7NDonz0ΏKܽ jOt~|6(KM&iU9}6DOnttxQykO_ *26}ǟGMׄ\n^VDq|5U EԀ9{ە ` +e9s'tFGEh:[ ,jS  `A@A,  $HP7A@ r A qCA@,  $HP7A@ r A qCA@,  $HP{so0eAāz- z{VPjmKm_zkZ[UW^[J*ZAcbȠ'OXY{}$yV~<0E@P-PE@P-y"t"(e("(y1s17qǔLWNWE@葲g%w5a~m=3LF!z[/3)s<|ex~ 7,[ oTƋ?^("Оkak6DbUY1ƓϼC 1e;&~sw3n+{Oa'摬&E@P:zl%7z7H%t0w>Y3 SKxL="!&H9|n1)CͰ1ˬ;-, (" FFV#xё®#u,LxRmJ;~gh(s=͗0i0'1d/`kSE@p۷UF,+\<:[OA'6m򔹰 oˢ|||Nl#F(r!qqC׽L1N=֔"(4)"(@ E9VAPE@ Z{(" ZdE0E@P-PE@P-y"t"(e("(yZ[2@*nAg^C!PXX#8ݻwᅬ{GN~N#/Zwb o>簂#L]A-,2dH0^o D|׮]K<\v[>ƐOM֜vܻr" o/]Jap7l]{@8kiRC!yf+܉&=m[^xh`ߝ2_1]&>?dl] (>ǟ3AtlXj9mz[>ڏF`!{*M&\s'صkv׭ـʉ+”#]G_{'4PY.Ba^2|0'QU{aƳeEkl}Fs*t'KwǪ K/a9]=nܸRhEUW]N5kF@r^}Io9`\~8R#p@"s|&;&wc5̍'e+kf)g;5Q=.ƷpeZSp~%P:%qə:{Y1oXqI}y_מc.oa(.n: .A3[30cܻ/u sf~qaJl +E"C@O_Pi/!'f/ހx7up aa$~n /.Njb,<~l rc{Lml;l$>] 1ؐW=/w;<5ސ{sѹ|݂m֯Z3O15K"sv}Lܨh`ʷbr3qw+&^šwye)\f݁YM5 isZ\l'^[Mܭ3/x巰o㚠 O ʕ^pʊ"V#嶺b{2Y [ |0nŘ{w0b{0'^130d|G1'J@tt7Gl3`Xv37`̘6 q]]pM)O4-b|qǙ r^8RTu+M;m+ס^4DiCSgwo֜ [*T1SϟAt\vCO|ļi'*&ٿ)-Gɸ~Au+xw1KE} E}LjY ӿ,wbטӸ~x򹬂އٺcSh.0Zmȱ̹~5gY<Ƣ"mÆwǰSbfgLĤ&b9lnnjo8ФMpacX2pXR;](>گo7T/\ <>m_ES7~a?>qOf<;o<{s@ūK~;s^5~?W7|h^4>ƙy Z3,*?2?e7= s>SA0žusESI~+ /Ocͺ 7q{g?{ .]}w)C1/tV]+p {}]Fߐ` kӽp™]BoG^/rW摸wO; y}(Pi'z÷鎹#M3_<97_,J~|7~s8rǛ&p6>_a5d0܈bL4C&g\}!d9n,aۧ»]0yh머sY?V[CyKm5<-6XݻHᣊwQ k^Y&lN<E=%_*G^;&'l|)f (+ _v8+0^R/t^ 4s,Y }g@6Ee*M|Nǜwޜ͸ߜd~&ϜNO!}ۯ?o\؇M`9ObW/~gzpmμ N[^#V^|D*Ɨ7 ^@2p`Eyy9y6>oV:M># Pc>[EG* ^(vyёBmTdmw;Cmڴ { '0'oqf.F~#w^ųvŀAE!4qb1fa}s젹{@cnJ+]?{Ƿ#;3nL٬W>Lz=fNc3f2^ tu<}ꩧ6O>}>68~iUVJ>ӟ+:f[b+J39Rihnݺ58Sb"_:6ly[E-1mOjS@`Ǝx9l(oo+';ː~5")+Wc+lM3~1fbfM[͖5_ 7g[fZ;7m;Vmͦ l\r6 fUkpSu?_^Xg~nwpI4I<`waa7c j݋q5G6ض+n@] IF}P/|pLU3ˆ$޹0⹅ѧV\{M-5q5wAY0W3[GU}fmrv!P_.3#<j65_|U9E ?Тi" TϹ:3?U?4Kcpߘ>o3:ml+Pv'yۏme#2|Rӹ荼w wm@'Pح70ݭ6`ǁCr8xŵ x۲%+Qb?|n%_{Oָ Ε8X񠇩WL=s_핥P a' ʷ`wm G^X_\c6T{nBTZ4P\Xmj EepNDA#.jIEho/QԳG B\wĿ_4yӇ p6)/ߞ"cr-_ 7Ϝٝ_܇4(ăO}Kߺɦ7'_wb^;K plh'+f~ Sy1qlѹ8Z{*4 .\I ;J<GN?0{T5\= Q f=7y^\v0eqR`؂'&Lw-櫇5pk8yΚfGk5dQבr,n#egk'BԘg]͞ڰ8OYSwnCm~uVdGڵzj\1f*QSa|9^za\\oG0(Ok|qwrߴ2(?8-xr g]$ҹkeP<8I] [\}Sw7•}mxYf?ģ 6fV ˷(o—yf_[v.1 ˾kp?22.pncͮ'"}\;f2W^jq,Ն?h܎M{H9VQ}p7Ӌ5V^=Ƿ>+ѷ/<7$}9?nCstؾ 5n)xK`_k7Csq f.bmގAR1 혢&"3]USo¢f,V]Lm4L N lwMދ ͩ0 0ed'TmpZ۞ZkW^@f>>}?Ʋ>+vVAc`Y[qV6/۽;y7lj,zdfp;+Λx'n'{D}q~8_nIK+cF&ړ;g(%˅9}qb4tUR99r6غWLu\ɘu,&{9Ȼ ŴхxBL כkˎ}kXGH9O;5]*47׽1s6{NyZʎ Wvs</j9܇Տ$NN,rvB?@iAŜ{NHhNh7MdUN_yu>^t0By#>"۔d:7 <`[سؼ˹o ={xӜzfѱ{4oF\.8ix\۰Kpxv2֬Y'f-õK&/Ϯ][EG* ^(t]^t0}D#bW=i;RNڼ*h\dNm7+Ft}0z@R۲? /J'M􏔫v㴞U6!=RhkC3.IDATʣ,mm>}?^2tP[[0tܶ9R7u.jt4"}Fc;0X"($m!SE}fl\D4-V /+m WuظlqvnxE$1?*+xKN.8~Y8R`صs\&8_:HCvA'`٬' ̙[sz|"IΦvb_F#дKa|<Sn{:}=WW'\pBL=㙇)}`YGFO71~ 6ZeZ"c1șc13'3ѵ8*\郘qT}|ܜ#$G##b)oߩ3(Ĺay'Ghs.yZ>_^բ6k-t=cܳ9|ϥE9k2rʻR2=N!f=7y\; 9<8 凘|R1|H7KOfiw^ Oe4j\o-wBlp7<<*;VLtsڰ\Ag<+>fO.Q=Nx ے܂'%Sig!壝2yM>kߕwZl \s;O"`3cn9̙Z ]|/cʸa(_4&\v=J|!m.kF=+ 0E,oxiw%q@2O?_rr"H*LǙH`e)>T6E[յ`NJȻUu5*X߆e=R 쯑ƓI $Wc,h;{7?jQnV@PJPMt8<۰b Ԛ#Ʋ{_ѣ}ObXsy/Eզ()L~˸LL^to}=s*Dci)g(ט:ԃX`a_-B5MQlкA6zn6co +u`_a@[ )^hg:CQ3M԰߼IO__ۜ;a>m@{Cyb`^埞9Rgױ07Zh+ޜy Z!LoIJ5g(/]htJނïmo˰i8Gʇ1B.& K;f߻8f+u'iknzp٩_[Y'Vq_~͝;X1">n(ز]97پ .=,Um-S^G+7at7Q2iS%_ 7ay{e=?̹ohNJ[סt iʐ;e{1~eu˞jŇw|vNJ[~b=n >V+N'הy}7[ DB<OFաxq9CsP0Su Xޘzxv4q(Swy700μqs\SŅo2xWp۶9W= _\pLNjTf^(+ˋΦ݅syo` |Cn|^yyyay:\uxN1Cj|U'ו㣚A`͚58qbU-{e֩w2ͥgޱjۇ]LGR7d.]#G?΀.9n A-5=q^ϧ4y ,݋` .ř:ͥ)ILBr>H7Z3d9IoDL% (~,81 bnb䘠["G:*qr6,?\_Q̣l3Ei8G!}q|?A)ak>ߜa<[qiJ_-8(GJ0[nݺy=zM:?7x<|G@vB<Ȕ S+܉&q[z3w?ZCUԖq'ՙs%]2qib!s˧ L_g g}Qz++?xwqI͛{GȌgm@#b._C S>#;w ~GYΐōۭU`NܳW}RRevPrФ֋PDg͖E` Bmp|:?) +Oimݺ5Xx:0S=lؼ6dȐw:rlձw;UUVa޽7=zg~Tge{ESk; Q|y oBk5.jSvŤ,ʉI3'E7 u}qY[(L rqWBTl,PUVVbӦMs̼!|> yGȇB@וy4rdbӿ(^;[B\{AK˼uߧ۵l{=玬6OA\rRƍ뗓vQNgR, 0}:xcOˣb>+? _CMJE pW̶_Wǎ нk.<TU7K-2N`Wy<֩ģZԇZhhwE@9ۼسNfRMitgWce&1ZGlNvlɷLcڠx["j'"q`!`h5S[>:ayIG;]ּٍsxb٨-qu9ߊ;A%Pۀn^E@,L-Xr6_"(mmgGksetn[ E9DLAޖ%։?"(mݷ?Glqi6rDE9rcI ඿˛WVzP"(@Ca{[z.G<>{Z( p3ǎ|@z۶mNWE@h27#}r.z]Dny2kl6@>I.[G++P&JE@PK,?;%EYFƋN(}x4΃t;m]/6RY8i]{saŋO0ؼrDsiSE@h;Կ0/jkͣeX)}LP9Ŗ.]<]9bDv…ͯ41ﮮ2ob^rE@PZ^C޲eʧz꙯~Oc5P.6bS<]\%.aI|v[-Yغ(^l6%[*<3;.?b]xSA$,<ˋΦ-J l=LvO"("+2Ζ'y/: ./EJ)yY4|_%QME'KMa]Z+F헇p`R|;ɐQ6.D&%ܳ -Eץ'uy))wǦ)(]tm]-xD/Ps - Os),\K2c $z(mj82Ιɀ81)6»A^O+Zy)rls,NmǛƂL4Ro'4&>JE@ݴlBG^WMue) /:)#lvN%, 6?Gt.ʜh*Ey:{an[&o7ƕP+٨2㸈^0jۘ_"(BNym>jG-܎6oۅ*"Ju&PJ4]M?*W3[6 08ɮqҡ\R}<ݧ˳oCxe``X6TVE@m?F:}֑-vArD|6 {?,_6r1#Jhz{dxeqsaԋp! qy e.1:I["(m?tbˋm#)u,T6 1ӗR6&-ˢ̉EӴO&-e _) ee΃~l" Mh;ccS 6/P&q I?E@Fz/:RMmej\_.P-,_/Y, s,ߥRI1:ir1ua d|>J;myWEV(mN(J[.lw2K}޴\eNP'j6$JrQoNj ʶ_A8)Іml2>M.ljzE@myxDEBE'zEP4e^.4Ε/m6WLeKYbCr]|mH1Mt6Q'a.z(KqQM|Ԧ(@m d<"#[" -bwuQI'y6>P:07#]EYIqs96(W\}%Fh`hsLQ qulOHˮM|\ύSYP:I6kgEQnOcSFA 6/r!vR6Rz+tr9pXa'Cۗ|,6e>= lRӏzMۋ:߸7g{B:\vmҸ~nʊ"б,NlL^d^taVB8ԇ\_W6ylⓐkxfQ~C|OYt&Mx:6ы,IiXRd͎)M'Ƕű*+@Dۼ泻:[&/ME긍mEFGvOG;'|d?';[~Nꔆ'B$4*=ixI^t>?T)2٦,REfBE磶)16E@Prl#~lM\“r[j˶ε%66)KdTa\W&\׶)(@p{\- oSq nOl" /TlR$Nh+G-U  eiϕ,G>^t.6O+GmyiK}E" d3:(m]dr*o%>rTbm^@[֋죶J٦nqeIm^E'rԝo.Mx:vQ急ؼ=pW/8WdKٲ BN$7˻Z|\?Wf4чɢ'u}m"l'}q-L=d#ko>ǧ|N&TxFgmw[oOZ|EɤhDŻ68sy}+O K en"qa:4MKHq3EP:ML6W#u([PmYdT(*zF{X3-@R9p-Jg/劖RyY S&6>6l3!%>}:ۮ"(@@v.WgGQ셹mY nN.v6/qa:*2'BRNZ&"4EV|糱o_A1O:6wazƩ( &&uԉtRl& />»T⣨;ME/>.{Nh.2' EN@`X;O(sJ%eu'vkɳNxڼS'ͧ-L/qJE@F9|z e6uy>V >ILy2~Rmvͧ(l#ry|}я6m\yq[xه,t룶)KcT[:1"vqGc}l]]Tqmqx!zb`.&MHMTe;76NQ+҉&>DoC*P韲])l?[C6/ďM|]>0:vԎ+"v:O}k(?&Sd'N͋4LΟlYIJ ѹm+ROqcۏlgc:OQhBۤY'z"{iEJ_Ix]tWgl'Oыrܖoܜ9+a$Xx\J OVqv!Ndl*-X2y6 )I3yjE@GF>񢳩SӉWvͻC4]*Ҹ'ؾ6~c BkE׶z)6e0ٶ Of=Ox6}~MZE@-QYۖ]||k0V?]lj#I4]M7,W͢A&K9@ O*9i۸%+S /cYl>j\2KH8>H*"8R񢳩dYR-Ȃe.oӵlSui,AG+rbTO*WK1kxHP[l߄ZE@PG vg|lŻ6Xdn.[XhYŞvQ`KNeԻ:š7؋9OxF񮍲4Ԧ(@k#=uEGjlһ~>CzIfާi2훔vQu٥I(t]؅J^)B%VdR6l'eħEʢi_yE@PA v9]0 OjՇɢs:gn6[%-˗,F튀"v,uu,|jONGxzl#|l:ͧ}2۹>բ,AL+$>dsuV\9J>-'N&9ں٦vW^P@@m]- /4.Q[/<ݤ[G>Le$(snu>ٓPiv Eɶ^xK0'f$4?4R"(!\ɶ^x z2';l곋~6/q>Ҧ*q EHtQgP&t֖xҟ22Ml _\ʊ"d~%su,|*uyWxsR'Mb4XKƋGl{Mm^|my6ۖ$>ͧo*(@'۲B9}4ζ?Wt>jx$oBi?YlNj.l :'e(޵Qfc$Ϫ"QHXb\-'nS纡L.ymsy^K4 ~xe/8$l#=LNJ>E@Ht FXes~lbEm0vغX|>?Wg dOcw(K1ESʣ6E@PHxz[NƋ=/' ^'g|/La>9PՉMmޗG>[֓g$4~\w}TVE RD|.L 圄Q6;KLֻQk&cJH?ٛGFPC Yq]-'Rŕ}؄Fض(޵QfHh>lM^)"_Dr2^BaLG;LHeړ,qr(ٶ /^h::;&+I|mOߎU^PtH.盉qdӍM^>E n0?W%6 uQka:N"(@㳻(ٶx^]OΝ?.q(9f3 QXjEd|XdqjWE -(aq>yۖ'SLhkhrQ ]-gxtKN"(mdgwuQr\'޶ӅJMm|. F*9|}zW%6'0l'}|T(@ Jѹ>lĖx'kKYUH%oO2L'L-W"(D ">6Ϲg*rnnh*f\TrGl.2rs xaKCE@H@JT0O-7QK-zJ(_-.[>/HmT\Me (mTN*M7ӻ:W\+|tԳr$,?Sm>Qa6>CR aqb&mɾ9nͥ(-@Ίg 8\L#&>6Mߎ[bj>}\AFm`bmt\NwL(mIa>}>R^`2 M_bіOTL00= q|7f+OTjSE *8qD|zN普M]MKnbN_ba0=űGdbզ(@k#IAJeS-݇uu-](/Y\=]/>6MߎU^P@*O6{qQ9* '&Ovdl_E@hRȒfj'rO:1L\iVT1LrdJh>)@G5S&}f+k39$WF4_ Bƕoy2ZY(@G [/dmdhem@V\-9eȹ-}(UE _V/s7tmjʛ PgE@P/*DʶTZb-GHE@hDl>2^OmƸ[όW&PE Oh}fw[/4mama}4XP:mе1z4`xW*E@PBh؞Q{-du^S^P@(J(ū^+"hwE]AXu乻E@7}ɇJB؄cE@P2ECdiIPv4u4BP.Z\ӑ+"("("("("("("("("("("FaKџ^IENDB`vavr-0.10.0/.ide/img/idea-settings.png000066400000000000000000001512241342074374400174240ustar00rootroot00000000000000PNG  IHDRd3)iCCPICC ProfileXYXUK)]ݥt7PPD@PPQAE(X *6{}{5kk C5qvqOr@ ^>ё:-|ĦZZ_h k{F:HR !TQ@B lm̲-{[=k@"@!qtAj 5}|`AuvEl%xNǦWV!EGz%?.aC@]0Ĕ(B1noXc%h=t07C1bCtvi-[Ř`oR}8.<|NVo\m`[?L';mo9Z;/,bm79 ?v[a ":@{_o~_pn:tmwfFZ#~F4Dn;Nq@fLwcm sEoARv!$Ďw pm;?tj@*G[q[-Bka059FY2Fw;߽ p8c!Nu(@#3C~w\=k(v;>Ֆ-4ҿ 0Z3[#Vb4P(w  H`QOt0Zo cp{,&#'vXx[_k"Y5r@:t#ҹ̄W[3wo[BP;AuշN""IA1<:nc#GVZFͽ}{lgCLE[`t;[&,'|bIq۲`S] YԀ60 x C9ǃ d\pT 2h-`qs-X_DBܐ $Bʐ&dC @P,:BP)tBmMh@ #0%sB f=$8΃K* ߄qx ~ @^DQF+GH~$)F+H;|0:71Lf?0sӌy,c~aXq* c3&ln_q8NK\0.ww Wfq+x</[1LI%|7~ ?_#P C+!F(&\$td4dddVddddg͑ %& '&O%/!BG3 EE E E]iotbz)c)(k({(P~ҦrʣEjHO$}ef=5 ;uu15K4d4B4z4^4ihhѬZцH;@O'Dg@KNWMwnף?H~ `̐paaQё1q ab2a egjd`ɬǜ|yyEŏ%e;+kkk s6  [<[[;{{#$!aˑQ1ıiy6W01.nznM c܋<<:<<%:e#dcq#NZeS%}(JfIE3KAp+`ebUdZ: ڦ浭^;vvv?uquuvXT4,yЅ%ȥzunݙ'I3AqysʫkĻ{G[_mc ~~~o4J>WXԄl:ևs,ؗ+O=1Ub^zRѓ륁ee嫧|OUhW\̭~:3Fgqqկ:sN\yքL]pV":.nK#/^r>46,^:h{Mڕ˛rV6Ӷv7j:x;:;Ȼһ6Wz"{nܜ}z6ߺsݎՁ{ZRiXqQѮ1?4y88n9>:0GS}yd䏧)ϰro_EZKMx{웎ÅEŹo,e}W^>>n|:s/++/}ƺv;ߝ_ǯ׳H/UAO5P@?9q;)rGo `C'4d()jhhhiv3_bŰywrp^}+nR⫔9*y]hr)j*Z>:Ѻz' -o22׳p ΰ)oAWӘnovǰgWw$?@ b!aG##"آI/{bc3MK *sLzgCdYّ9չGÎV <[qΉ撩R2rSO`$8whZ-E󺽗/WmȿV-cnv:LJgҷџ~@nA@K\LRhMw8GH(BMRR\R̹X8y=~?)RNwp;]s>p/H!}1z'LKlNzE8UTqr*ij#k_(Q~rlk9]FNLzwI^[M}gJ %04rgډ7'?/k^e,²ִm 6nԈ Xk*U''dtAB3"B2::ip&|A$9!3 Z1tX-l8 vG%qKx|@$(\.CDp1JeT* )Z&f6W|^{31|eLe"2bbƲZ&=c.7ɓk@`Ȋؘ]$eZe{_(|T(3JɨKkihitvUgD:KpR!fksV36l}H,j;yq{Mu;_83.7L,\2B"R4M=f!-"!=;^}EߦX8(ޖirh6P.+ySE5N/`?MTvn?[;\zzNw7^pH8=O*~!3:3>'>0dG+?$tW$ Ah?}@{U΂'.HryBwL/4bѸSqٸxr?I$dLddis┕TT8b5NAhh'qUL:L3̙,,llSEƜ^܆<<U|\kB-§EN*(3p "z MLUa;qX Wſ!Β"ɞP(֥rZ$fnH[LI@S69 $96=[~ܙZmZnpudvv+~; 1=|o}4p҃q Gi/<79t9 S Ӫ3گ4_+Y[{K|.]>s+`יkkm-?CGϢ_R6|7/'u|@`_ll|BB~llY& ]g묡}?-ddiTXtXML:com.adobe.xmp 682 356 8c@IDATx @UUWDC,1IS,s'FGm7ڔ/+sbjB'lp*p*0O|_ܻ/=^^"]^k?"}9$B@! B@! B@! B@! B@! B@! B@! B@Vݫ0mէW&'B@m4E@*ϸg6"B@4. p-x`- "! Bhl[ <[ϗ M! hd>xm\kW#ŝB@!Њ5ti.gF"B@"h=߃aϏt)BU8a_5:>}Z4 ! =s<>tΧ9}4脉B@! 4G@}4DYS6! B@4U`T~Mï_%kM17oՇB@! A)>|ZjpXji~|āB@!j4Vp4 j@i֗賾c;! m@cpkH Ucl W$5t,/) ! @CFP{W-!jG_a2}ykI΀|izmg+mB@! @"А`͛]6OrfKyo>l5WT~lmI |idx_+B@4 Ƽkf%)mSΟY^Ûv+2gk'ׁ{u[nJ ! h-2ŷ'VV2>g|zkWz*W_7u;}OmVr_dV: _N7fޜ}5ŗB@sII*ļW2]su[rS<ӵjEfQup|K}S ! _5OzVr;[u<}+}f5֛2ǷUYfW6uRr2}zJ_r! B5@g%q[:):ۙu/omf[ IJnR4ts(g[_I-mF6]S\! ];{6̪βtTq2V$v%ohQƞ]<"0ǧ']+YfWWm }e]إKk{y$" B@! hjjj>/=ztɓ'09``(esUݓNmdW]t~yQէ'=+Y=T Rׯ_ٳgh/Sf! B@, ⣦du]G V(yU=u.gAB_y3ڔ/wxw4hВ3gx\h7IB5xVeNh׮]Vo 1n =s; ȓDu`!;K\1ctX?w4dtO|w,UcqA|x7}pe,*x)-}{!c;Ox{h2.^2ӗlĞcgq7!8w8x&}J?' 5Y@^n!GVu8j~.ŘB]p,^3!K!+ us;-ھ4[hv 5n8;v=qu-Ӎvz@gFaC+qdv+ߟ 0\>V.' C35p)J?+{Nܯg[vdо# {'.+w[Gɚ帡+Ps;W5NɅM[Џ[ܣթXMr\z}^+thc%rU˭XˍKAѨ9r~vل~a9y\HFɺ8붼?>P9p2u~ Wt_\ Sh?=~ c#'N6t3z w@ǝxG0 {K\`C׿'f_8-IJN(\+hi@cE ]Q,Jj(*][(4=5J+ң_Ԭ?w:VÍ:ZܧS\E_55tk1J*_μt֡7չ8V9rjAmTceIMi*;nd>p>x<~x?9I:wҟ;'wy\Q5VL+<+{Ԅ@&s*6UY}9YɭdؙuqTOʜ.jc.WuÉ~q+#_AuQZ#2"K.u?:Yދ{R]_x*Ϯ/ikrN-n>Ƣf0z\1뱕̚JKg+B ^QSz%wO)׹GV`git75D T+w:ҾݝS dgG d7| )~6|` nK뽯6Vbo~#ywLS뼿`g$]7s;@۱+$}Xַ=?ֶZNtTT:O϶b4O:c ʖ˕ ո K\\r]%UW9U.W?m/[uR^uUY)Ε\JuzcFDkqࢋQuÝыӭmúV>t۟ȁ:eq(]\yn:{ =fLi`t XuR{"pwꈃ_f㏯'OGƗ:٧ŏhS݊Cpt^>G3h ^몱)qa|Mww)̋twO ?Ɗkv}CNi# ZϿcǰxb5`zm0vo{ӘطmZ*4ڱ;x_W7cmxy}keu>? })|Y3'5̓˼J[Nl͜N}iG2[ b +/c~rkj;%mşg|4*Ɉprؕ)ʹSYJ༹VT= Jder%39FTCw׌N7ofޯA*.cmƍRj z?_TRv`oz@Y&;r?r:͟]_z /ƽknpM8a샸.%ѳĩcG3$_b|o=u3U ē/V'۲sBgb[uu'5~5G=~1Ao:qZ¯N3W9F[0ZNƭع^M[Η.SVl\$L/]Le3lJ)^A?=ۘܰ2%oZY-'B`gR <0/e)&ӣxF׮e23HE%9<,yBuR}\h[Tr=b(ʜeI6̝|ѷeVe%uuu)$<3PǏS aa~)Z%BB\x te5]U?x{VGcύmħfc#?BPiP(6?^zj#| :p ,,ksj(C.D~3A ,UYϩRGr\:'շf鋎a+쒷vmSrhS6MqRu9_Xv πs܁^J:Y5 6we眀9 YWO\f]sݞ˪,ozS p6.veUW6J[f*Pr! 8a97:s,dׁ FYGT@rUuY'kuTn@UyPz*sQ2UcϞ=4% ! s ow"_MkusuXrC/s]Ovmrcx&]W/=9 3믿1B@! 7#鱏ys棂Rc_Gכ/vXs&'sTuI[ٛI]! 鱏鹧yYL%U6窽IZQUe.:+9Wrs]I.B@Fp]O .Weued\We)Gד:r_U5:H`u^V6,S8Ds;F)B@! hV~c&sRMYT]/<ɕ=ʇS#͓psGEQ9z]wrզ*W~Tݜ~,B@Du^2'%s?mF鹻5ݷ+zzكz1(;UseJ_r! B@62N*Ze,mJ>NeL4Ejի9g])nIj)\)e! B@&GNd\V%9q۔\si\t`u&j,{T$! BЃT}8s6L/IVJ,yC95u%*+IN! -G8lWes|d@$sIͺVo@!e`? vO!gZv- Xmv)9%~mfgcf$F,/u쭘o%ESy,\J?+Pա( VpLV/sYc~{ Om;#wLSgĹ1PN*}wԚjWoΟ'cdC{ 1Cc6t>9%8\)**)+9fS妺_ ^vgurUW92zI˟ŒľòOy.w"Eb7Q W ֒O`B:Fk@WX#qG_ΧQOIAP'uOt>ߎ*6F`׏_7E~ϼVÎA}n,m4@ݱw. uS+12-'+p7tB{_kp}_ߓ}|›pY=gyQ"ǠӭwH<ec1߮'t#10&#Ө*h 5t2doIo2NAC__Ӏ̧u{Ro2ڞ| ;#r?n r2"/f|xh0]?6O~<4/4(P,vO6 mjvc?PM׈qk1!(bF13zdggJ|Qrнt3wFak+4! G6/(-x%ؐC9 ӳm_rcOC C|8wQΧցq9,=Ͼ eX2|o#O! @[!ҳ1ŇG]ϭ`MϦb7nCe=k]I(َӓ|H+}Gc!OJCRC&&y]d_~b.)qS7dKО#PsOu}a1F%knzm\ : CVr! @&`(^粞f}nKY狾K1/z(x7yrz]9A< FL؞#'peJ9sLz9џ@)=xY~ 1Eoc杳ae8k[c5lU'!Ƨb0tàĮ1`\.m?@M_U^8mA0yʽßvHu;n69\"Ԍ ';34UUWTy3G)ڸRǎ8W_N'k;ު?Onw(F:Ga.KuCڻ+7UB@VNcN*1?e~eڔp}:RcFqHNĕ?U9grz]ɭr;Uiix8풱g\e() ?P: K_{I9eL7LORJ IaϾq\C^6 GkʦM?(x=I E̮?bsУ W]sfA|ڵJ2~c?q4/;uOw&PŹcq'ouSqBud*Umz,ZOS:z5~J{n|VWtrUe>}1۸ϘWT$<{s|Dx+%;Lxbܵn=,#"! @k#Kcdf,o1&*TuXtX`=C9ɢ}q7}p0_>;fa/nqa"}C$Mٮob2ݨSL__&HVO> GK{q 0Fȩ&$gg;_?{T9ZK[0mexkdM@稗Tn7GZfb|A2.! Ku:=Ky7 s]7霥0_@8/TG(8Wnd~٠#4zyO42ztke>nTYeCZ|t%dOh<' ! ZHP5c2ou+;F/+Fٱdc'Smzn.ZePue`}.D%Suz8po7q:2sB[=cYYh˷lڻ:>]1cezً]ݖ[X(]ͅ]Ź5ˡ(+9оKC=~<ظ?SٸB޽4}tp rjPuJu9*gSѰ\9lL%e[\퍱NS NS,g}z]/+MwmoO ޵ > Gkcfnn,VwɁ}YVߊI祯'e7O}mC6vȺl\B us0d*WvIOZ8.\HKҷ;d=QeTj%W*g4{UXc'.6ծo%-ÇP! ME`֭qmLS9\ b٦Q}G͕6lUm\\?\r! B@Vzb$5WU7]ϕͬ۠zsVk,J Xb,B@F*ޱ C6s]mrc_WMeeզ˭dʆ=A,r_z^:һڇ^GGњTE,B@ H}2զVMm<s]]WUo%ݪ˔\WzsS\v%3κ77pđB@!pcyu2s`dz;[L:W*0C4rYU/usA5teeg:D/ +ṿO:!vpL'Qr@½X#vRuV^ D;@Bt=S)|YSLB@>q^wMz1v_{Tk{\,CyV7(g;R#S;AC TWsJW6Fͷuk,\Dc|N*>|\:UYI8+wޙKt'\kcˆ(kX]JPeGQB@! sU˔UmȚcE1&^W`t'۸9PXQeF`ڿG%?.'YzY6$#=aI\x[CV^Ы8҂\ E!_|(9ʐ蟘`Z[g`C~l(nJN[0,43PPXȞ(;q#*-XD"S],>HB@UG+φP8RVtVf2C{*+&A Vy%}`~;,.%Fp뗂׷= RQ\Hu{n^~HMOb|#ya&!z:ǧ c< 5o ؓdu--qF K]>{ S`UpXc԰Z?TynVRB@!f x{t|V2]5(o 1>lg6*c?ju5WW^1kw8C]\%!CRkL)+܀G)H{bgjLFڂ(du=C&Gν۔G5Wdt='o֔+02\n sĆ>JO{l1٨yY/ X:C})7Vr6,8}u_"B@!pغu+װw> kg=(9fsj'5.8s]f.sqL-aE4$*٠ mFnI7NJоxlꝢbgFx 0ڮ<ΗRri'܋ԘڇWze/"B@! 8R!.i*rG]{O~Fv [usr`RXw$.ZnpK67}B@s@؈uyeS`] Z;eWίL |H!1lI! =˾b}8i*)I! B7mvBcTtt(B@f$pEchoB@!dṬrOykdwNkC;/B@! y#9gdz'-r_8?&ulG8BW~«$! B@4.qo)Pmv|נ]p:{ >v:.#$B@!`G5\_|UCo 5QOvq,UvMRq[<)H>+^Di9JsVࢋRU/'Y3"%5sz4 )]eYsP+ h9s 2r:l!B@! Z TpO8QITgj8>V2z1j}]#&`᪵@d$ۍsR0 梎֩J~IA̻q%}.l1a]5ř>zQUx|4q`4lWd)4d ?>zL_㟡h ! 8 ȥ8)J76~\N/-mHFz0ҔHN]_H0|â@H8b"ciA.v}_}"K /@ya>v@eHgOLJ?a xy?< #Gq!"g,Ct@|\J (@D\' 8H`_CzH7'y(9Z1_'+2L{\FBl_q \{rw@eɩNѷ"bHڏ+㞥<LHDmRB@!qJ+ZsN`WRVÂqZawXQ6`]A*;KNbOmO`œ5ZIXIw[9/Ľ׹c8U[G35d栈V`OSG\W!*:n"nd.u 1LI{WRJhR2N^SjPqB+ckxn,h ?y)^\8LoLbI Ԟ>% 醕#mu6@R[?i#<)i2R}5jR@IDATCOdxe? ӐI1WɄB@:nF`B|U?UrzU5W{ΆD``P}" Q 1"Kmv3u6OЯp uH"d݋٫19>i V;5)H2y>wEަt 8"%&#=9 ~,F_@T\t]?u%6d!,hxo'SCN5;9#o2sjyއFt$Cm[zi R뗦 V|p vf8ohT߲{#- Xu )ٍ+4<}3WBLZ9Sd2`v<1$3PB@M~Sfj/58Sy};C7asA_P~$_DAPST0{ňؑx Hx#ؽ{QcrD@؞^¬,ҞX Ԋ~fqO4E0:[iS&ꛦcsoq@X;BŒUL!H8;e87kGy)hï͙""QPdm+e b< XW+x ".7aUԻhH~l7.V[om^TOS.#p+*΃ g5%"tQO! mlImm wP 끒 \;GNŲ[ M7.d %Ŵ,3Oc$2ٱ'8}VӦcbbͧvgq,sֽLNjo&d 1qtX.ې4uXq 9,UF"_B9'"6ޱs#؄6J?mޫ*9u|9]jSl3vCB@6ZZk__$";/nGTwGkZM+tXk=رb*,C=8JGU*v*RlW;r^67cƸbRlKs#OK12%QH8;ץ3"#vGDR^XCKoLTM@D( h5X3~*5)cc>l'G#1qp,K6>4z{l-:S/KB@6BF649Pֽ<;!kO;;tW޷Z1cfѦus0us-(@~f,N-Х L"yyݼ НL LFD Q|jCΆQ~cW٦ u qYS=9yú2 /z;%׾ij1}5Kh3iwǏKæyبz.*,D6nIX|E%g&l%iȘ>QuV%{$]ꟖS$zW$܆U 1gJ6RVec!Ó(.k}bq̏gNY4N?z8̟\sЪ- 8_ <:&9&^;Ǭ1vt>ı2nTmeuS?dgl':f{*B@ieVe%\SUTYϹlsx䜫sk:pvڅÇ7+7Nj O>9i bmY9JKiVj/VN'F{]ZU;ĺ{p2]{Qzu9鴒{ hu8Rw%LA׹X2:M<}]M+5Vs<{ߔU.^z$! hn݊5ݻ A=펃Gd:0Jι빹u>8^WrCcU6u.?,Zܒ@oԡ}(;E"6 `6]yb/ХLO1)m =xZ)~xQ 3zڿ9ѷ !'?Vc/(^*ETBMoJGYsup?rZuUs.jTsWTyiU??񞂂Lj`ݦUh`;p[?ܒ$Ø{S6z$B@JJB@! --ȀB@! =B@! h$PmE%B@! 7S5;p=jY~]=;؎OuqE! BA@|8H)At|pYt?=qRiq)|y~t'^B@!l$Pmꜯj>[z:Ξu!00`/"7QD=YU 닱|{cX1(R-Mނ#\iӛλ1+VүB@6H6ioOs#T sWpACq}`ܿ>~q!V &FY_μ)}YOj8HUJ܍qf*^B@ H?~KUP]]=*qq9tk$ejKRzDĒ: *C:b޾Z^Z}GC((,DdXGQ.=;p2T?Fg{tP 6-&" $oy wB@!ТH(`WRVÂqZaw(=9)ĔT _yZ LV0-Z-껓^jsH]) hxl4 msOv`MሄC 7Ņt$Bl#<HBΫjpy; I:3PV,dee!33ՋS, 59-y{"oS:7!3ۉxL^A*CF^l\= 1kOʘlnBމ;31r<|Ŧ`i雰f_l\rCcy;F:-KSv+>$dB@󇀬6\_Ͼg .{_DU; 3!VUz/@XIE_%.C!Cl 1n3"0j=`ym~rҸ".[i/mE;Cˍx4|y!j5{0+^y{}F5ƈYn 8lZ_RB@!  649 ]0eXW!8r,wݺ]hmKryz&捡ߕB JU8Ӧ1t'V|l_T+{e[U$Jg\QB⯂Z;4`~#@梒-bƸ4.MUjk6u#)6L!sַ)HMªlڲKMHuygy*֌ #o/`:v&ʮ$! B| ·1rڭ{7vB֞vwٱoOor%=0(´#+yY/ X^0V+׾PL Z?Oe&6aܜ `>I! 5_]:s%_^^?jl_ c/!Y(,?t AdB@!  ڀ^{TPP»}`\p%zt_tJ94z^JČE83id;.}$OCV^pEm_sd# lgUۧ1h+xyjLR?l6 K $,Z? E?4$ctT!ݴUs܃ س$! B|!ˆI+]fUV2LTY弢k.+`UP9Wu=2ߜRsڵkoެD@zo7J Ћh|I? QQYMl0#1 'F{Iii#mEgBB@!֭[ѿojnݻw9 n㖑4,\Fsn.+5m溒sΉUv2զ% mFnI7NJоxl/E3@U#l*m:ҿd3{u'B@! @K @1Koֹ'kPPi[@IуXmf2Q! BAP Nʇ$+QHpȄB@!`IxJB@! --ȀB@! =B@! h$PmE%B@! 7S5;pެhY~]Ouޑހ:<:"]CkRB@! & 5נ]p:{ > ]:G8OGo"B@$ j|U!ҬP ʏ_g/z 7XmKzMjOVb_"7=V:)|_J4Ō4o C&gjAAyA&pԉ'ZB@4Gg4rA(AC TWs orX꟧ d:[%XKzԕHIA$JϪJ^>l,.ET}M;4zGKfbzz3! Kvym]Jj UZQwƏI֡AsNY뮔3=$/|(9ʐ蟘`bߑ8z 3Qkr {bO s&9տODAҍCy~.JT O$yIB:5 q7?F?^wc>)@UKQ! @ !Bq^؏Z]UkpU5W{ΆD``QwJ򑓓,dff"z9z{*܀%&#o^mJGr$dRL#;OlUl|0eS~ 7o=Ғ+_pRcqc;vC|YmbIB@! Z"YQmY1.8!}_%]:b3]~4ݻ#v`!Ce.I4>u =VuRqїuɴ PH-KSP1i"fDaF;{<8F;1q?-3FV *,Ry#x4|y!U1Xw `((9FQ~1b⥆m濢[EG+J'0~͑""y/dX58yٛ0LW2vlHgHf :_27W;?>#B@! 3h[WO. 끒 \;GNŲ[ MSZ.gbY] JU3qiS\˜v)uR^WUrɩ,zqeV }eI*+s4ןFKs_5_#5:qo`qCN[y@?o؄!JTIQu%]t2bͥ$hYQ[gVRJ#ߵO׸vT|SKn]MGjf 旫Z홞bcR~2Y_&۴a9.\MLPJ@ (nE@4{5JURJJ۷?m?X V30k.Jq+)*'cmXȇ6g>| \C3>4 hin26`E]'n9[KkR#[sc+6UPJ@ D!רFcT:{ũ^b:f|x&C^|ʌ۩&lX*? ^rI7խ;vߠ2./mѴдƿ}9#ۦHMb\4#VI+3>깩q};~ 6a(>M-Cp3mϔ"ښpAo9[V?̓pr\}ظ|b~&rux54U ߮ lX?pE8'֐n\h~wqjl4ƀcNCpZu,y3cnj0q=r\6o*ߏXWbv)%hO@LRĒTNVLj-|jRjR4~p U5k6:1롅^qɘٓP\IȒ5=*zݒqqʫ™j844o\T/Z Uc̢Z̬L3D~& ]Sb:MʁkEjʱwMx5F٨2k)pJ9cmV/p|'nۍK^qY{vmyΟxsL6w9z=8eY#OIG>lԽTo?0b*%hGg;&@7עRz pܐ޸~w0z>bfs%oMuOzI4IdWti;̈G^;kףar̺cR5Ij3m[ʵ,/Zw"3n-^ZU(3 zJo5y27&IU5$9_^^if1dMEk=r ]bxJۭa9NeB/O{0m^csrUV{>naSL`ېY~(fo^?J //(%&)x=B861k>!i쇾}UWv.t2ؼ~rl~U/!).>$@Ͳ+P|L.dGxzKx$R/ yMIyGŦl2M7UoW]sbM+11ٽ=6>a+l}jGkqqs1zge΂Κm֐w&9x@gQP?mr_VVᇘT#^#vzxlӶπ~^?m>5GlddeWyAk^)wijnW,5v[PJ@ (?e/F!mV>MW ?xm*~s֜Ԇtۜ+=,x }r5ޅɳfa9`ю{Ǽ Hid3#eXP΋_3وFK6m!M+1^Kcxn\{V3#:\=frJ >~+IYK`r}u^ ؿyic0gYGS@?Q>>E (%@D4*b9Pzؠ#;\?ufK/;sHg\մH⤣q}٧& ǒ$ͽ~Vc꥘~,cg T7t+j6.ݡF1ߴ܈eb;+`wLxԡ@̓6f, q ߂M,(x S967 J) \CY_A"jrܱAskMjP?As:߀5溁po5*%p3.*m =#q[QPXj=&\IhRH"݅E99 6c֌Ɉ}ƾ Un¤m#@vS.\|j|C+eeIS'eyOcz->S;l/k''O,@EYOf^5dM`]:v]L$5zk_.N%\g~kXØ>5펋ؙ}o9+1~H 'lk[c.Ǖe|J*J@ (%| D`#m.m$F`%ѵuŰN!$.%锽 پ}FF.7nĘ1c"fni~*=-=0sڥEƋdBn4(-)I|q9ίƨ{pؾhߍ +)ޮ6ywP&si2G^qu5RߩCo|l0n-ˀ~s߀[ZE_}ZPJM`ժU1bc4h%Ƶ{_mCMIv6|v$ԃlO[$A``ΪXv_3ُ6Y/vg-\Eo5#9ѯ2 *{|'i+&fh^} *E#]tq}&4 EUJ+%@8:SV\1Fo4,錨M5SvtU? /(4$~*M"Q'Tx_1~;)%@3wHQm$"s(r~b*KWYGo.@ (%@ YI-J@ (%PJ hs[RJ@ (% qPJ@ (%4QmI)%PJ@ 臩8>14g>~>߿z|+8zPJ@ (%bjG%+G'F1Mw(槰|#N?9q;]93mp$WY]D_z+U[5 d۷/C={_2ɪi\iCz0!~UErWc#rJ\Rxb ؁* RuK8FXX,= |*T8dv5=wP'}3'~ebM 54?mѾĸlu1bSg7K o^Wp6wz;"'ZirQvw0~$׆%xfGf9qrpį ~r97sqi1q$1'G{WzI*ɸJIOۏ/S+%&^5 ^k15-c7Tz|UPz@FY;LG1旗 !>4c47g`$.pK1cfWN)bYwA-K!Y>|EP^>,j֮l1w(GV6yw36o\3o?ns(|}V˿9^gc\| b&XvLS=^}|.ϟ1v2%vITx^?^7aܗA0T`k)$u}><Ѷ&F/N1f|x&sT{G/zv ־ʏ;ﻀAe'9Mu]7 9i4m?4mGio߅G@ȶ7mZuooGs[TSZtFK j_02nJr,37^:5zO^s;-QXu ~bU,m"}b$K<|[䵚֧ZjA rJgR{l,ćSVs$STΟ!ʰfM(Ǭ⪊;NG_>wϞ罶'NGOjC9)Rf\4}q܇* WcuB2IcwNZo9~\ǛO%v6gp؟1m66$ΜZ[8 k+kُ`\U\B%.* kG{WsR2=%5^ >B861egojHz"bSʱWa^| Y?X|ϜiEk̕1~85.į mB7Mk.:/6`Ӯn^U62}{r|kZkT1RFjUhT~2 +L&ӤM ZS,}: .hsAIqq9A)짽^k9c9 u6"թXK캙ĹaK|̿(Y/ni#XF6mxon5#^~ld<ּ5]r=ZݒPu6]:;~֦sJ>ΙR|2lӔQǝ?c$pķ?]3/ 5~DK^+/WamX{a9?oq.:T߅I}.2J@&y8nڅ('ᶧvÆZ+6i [濏Ջ:4kI0[[ܽ33ECaqj|y<#P< Yx ;M>ym>59$:8^ak>Ip_v^/1]>}8wE,:ulϱ㭫bK\d O4⮩?#Eaf(B~aZY9zSoȰn[CLćI[λNKs/bf|8l,.6CGB 6jf|ࣷn\ 68d 0f2'^XK rߠߜp󣉴|iX2y>-"Vvͼ}%.ke8k8dk bm@b<-v?^ Zڼ;#|aic0ooq~|~ynj֙&L"ٻ Ѩv$.c+ qQm$UIhRH"SՅ_ke *?|@j3f͘ (Iu&4yk )c.KnX\x&.eIS'ѥ{yOcg|lV_ļ)b%~(6 b״̺ \n16 9/TZɟh߿KNC}m/[Sjc(zi\uyK=>z؁c^݃8|frƜYU/~h頴˸˯-W]0a~ic|]bf՚Ddvr쵙Eyy-(R:~*TSK|<28.+ǂQ6Lj_l.ﱷdi/vn36k'',Qbͥ$hhY6|)=d$ץ$<;`02rٸq#ƌ)O4cuCOSt4iGǏw8eIDAT.- oLy Ѽ߷$'_QQằ}X|\7|%% _6lݯO9:\34N5ޯ[99fOlfH˹il.¡G}Z{6ո7ਯ_WV3b=œ6m"W¸#ۯ6$uۏ֒sn#*lM>#]&W,2cWc۪U0bgРAIkII6i':I:یm五A:PEϨ wYSt&u1S&른|A. HD_ejטA>}F^hW34FAI*u\#3Mñ%EUC?~ט7ȧҸiCɝG밉GS{&c^|1SG_W{ 5z:SV\1Fo4,錨M5SvtUsQܾ}Kx)((~9 Vm2ш (>| #8)?T_g~ 1}EnڄO/V_ ;LLzsus9w<Ĉ+MbZ\( +isl#7uRu)9e?9!eץDE (%P j{iQJ@ (%P9G@՜PJ@ (%DU%PJ@ ($jNnNJ (%PJ@U=PJ@ (%r&9-:)%PJ@ (MTPJ@ (%I褔PJ@ (%4Qc@ (%PJ ' hۢRJ@ (%DU%PJ@ ($jNnNJ (%PJ@U=PJ@ (%r&9-:)%PJ@ (MTPJ@ (%I褔PJ@ (%4Qc@ (%PJ ' hۢRJ@ (%DU%PJ@ ($jNnNJ (%PJ@U=PJ@ (%r&9-:)%PJ@ (MTPJ@ (%I褔PJ@ (%4Qc@ (%PJ ' hۢRJ@ (%DU%PJ@ ($jNnNJ (%PJ@U=PJ@ (%r&9-:)%PJ@ (MTPJ@ (%I褔PJ@ (%4Qc@ (%PJ ' hۢRJ@ (%(T ZQ-J@ (%PJ@U #,VPJ@ (%:uL%PJ@ (P"%PJ@ ( jgP1PJ@ (%B hHPJ@ (%:&A]TJ@ (%%j(" PJ@ (% vuS (%PJ &4@ (%PJ3huL%PJ@ (PTv܉?{՛={D޽q衇i-gerrfQ'ݞ/2{7{a"lDa={Ǩ8g7XtK4n߾СC1`ћ6J`߾}رcmۆݻwcРAQk*:+ej2,v/2{<v>Ps.y_O4eoB8ͯ}G:zH_x|S&~aoGblޕQ.GIj'>nڋd_2yc:בX"^V!ZL]oo얬<ٝzpz*0r>C|ݿde'^/;\;T早qœL(su%ݶ3}ڕ fwg5QM/}pҹhR_$SZ}zsmsK7OR[v%5-˭gM\r#1q8vpȰMpIO +iˋfǘFr.4vL24g1b;qJ}0a®jbӇɃ?e$Sk&Pz©3Tt#;u|b>a׼nN^\G>oЌ)N'pM25 fA-sѩqbXqǏq%ش U 3Uk_{?l}5[ۺ?6XVf+^EVX^UaoOոF $WTQ4ժjA򗞤5ic4ݱ}vny?pb&\{8G~L}d[vqIв~Ԃg|?43?wh}u8 0dwJcj McZL_\w7˾VQz8}ܱmgly1#<(n[f'A`w65؈)AWWRb=.;3tŻ<ٛBo~I. ߓ ^8cx9uG8la-3sZ0 `:!`hxHy55nzc;dahIܚ%هCoⓖCϟ1jOXH}} ~Xy㿌Q\G%Lk}>h3T<ÎXd1 I<q_ φ&Y>u?~|^ 1Q^n--5I5wz,eyS`̑M>/fC6}jkL)yb/ݷg/ԡ3}%3k92ڄ7μ. U+0=kQ;$I&^\[7>E ̙+a𰶉{=O:S܌Wf\Ti#Xa+qd%ᅡYc&s; Lb7b\5!>;=M2;goǹӆɆC_ͭxbfYNoxdͯv=~1V}1cc8 4n~ x$↞:KC}&稚m6;¿}C) o6Iq;SV8np&]1`μ~ľ{b#?c_c=_Cc^~g;tBckmßдހZ' &WN_64诖24E0k_7׳SZ`?Ozؼ㳅ΨY,8d?5gS_Zn?UMzz==Ƚq-A >kvzɨxZhJo}u +GϿZdr_^kb[ a'W^zpYR0;gḒ2QXKNG=qC-8f3e uATxo*ٲ>L$ٹoM[u0?J#G?6!׶õG8dia*΁Xfkk;_afx. .8ylwz7u4ϸOmٵ΍7pp)q$h@ECWC _Paδ%c؈oMl7y(&xV,=,i;>9P1EGNJOs+WWxRi]esҬˎ†iE5? O7c4VN!PԇoqZǟ~S/ {Dh7ۮyJ-]u[GnǸ0e缟-(؃L 8÷e>;co?l,c:_]9;j,zbsqY=dUyX-"׮SmԩD<F@6ws߇6-[3=kN9P .a>CZ^uoljq'52&f7Xns=;[3sVkcߧ˘aNW'SO=3pjԚvUr.mt|޸x`.Wz6I}^|+fqickua<)!<a=p|쳑p71ڍR, ̾?OʭsX26f/Wlf:,ޥ]ޢ|޼f%) &lދ>||/0_MB,$6>%,I>\nY8xAlyd7&KuǡӞ:O7/{_s[㦚Z\e{*8sەO>L#чyxW\92_\WS'Yowh?%XF$b>@oxJtZ Auע8j)^[4z|+pb[q_aՕg~{fC*_}u/Fp7V9'$.zǴ v" .*W3y"b5Ϧըn}"Tؚsse1eZҙ,MĂgρ=8|Յc~o>Oz IB|n[ C|b}p[tAv 5(⊑66|#36)Iolz42W^Q3;Ѹ}i)DC>f;ԴXz˟L[|cB}͚58Wzו&oozPZ:۞Θ}sMg/~JiRZ".ͪކ {.Ŷ:n|{ '+(ʜEm`[cFbWrSv&4hР437^>N9ott6fԸN6*6[:nY5,G'VitT2EF ٘"|8p`M#GaCTn-ih/-_Wڛtw%{tT|z,;jrTOzzf%Jb[ķ57AR#6=;"',lAo&|^ɍ8eOo8tNN0; a~ H)QJw޼EE/Yb<ӎ1yfb|^=|~C;j&6<}qB';;tjs)Q%aGrĴC6v؁^z A\™[||Gf[|O%K,sc=eb:c]/2?s[^E@n2y>H8f\e&*1+sM&JLPC#m.m$}q$]cJ$mס]^>II_ 9\H|{~5M-%P`c䠃G?<tO~{/?Vew|^ٌ_?4x_ 5Ug?KԢ1ר~n37I&Ֆ|-*IQ2*\ _J>uTl)mNu*&V) +isl#7u[%o'\')T󇩲҂z;p 3j =zx *QMC/˅ڿ\XK2skz$~鵒kTmmMT凩d2ILHdo6K [$]KY/B-uNRYl O9 "Q[deծPJ@ (@@=~zuʶQ;$&d Qw!@u%PJ@ tغM-ذZj/`~?WJ@ (%*iwa1vfD5 oۨnR (%P]_#rd}v]6YϊjB,LAs{ii8J@ (%*\9+8^+}Qe&# 8Qe'c 5)%PJ 8uSvrJsIُJT\p:pd[w}SPJ@ (%٬rxi27b[TiOqM\r}Ii{yR (%P]~U^̉lܦ%SX_#7u=pK[^[[XQQQt1|:ѢPJ@ (<'@I#UUU_ԬΪI:|$ dbKc] ^Df&J'OP[ǡk۷t7<ȦC9dHXPJ@ (%]uO<R繳4۬\X%%q,41N2/$G7.\'I XZ3'$uTκglt;c侥Mu%PJ \_]::KNdu6[R.C)8)x͉\THL'L 붴aP](\H$Q6i. 'eݥ$\XgIvs ǨTJ@ (%R#`c%ő7v))뜌udㄔm$F~*O<1Rr-)m2Sl'd-/uC6yetYlm݆lr,թuS;~Ra%tPZPJ@ (s9FzЍr uK?,9$Hc%dz$;-H&W;_&U` 6,yr~uNd,lKEsi1mf$cnK6jg}ZWJ@ (%\26]RHwdEwdk!c]vKuҦ]HTu@MJn'q&mA:bű$;sR˒clcI}Eql#+%Pp's*$7d~>OKŎaK b˘d2e<Cqa7G>: 8d%BuZQ:˘ܩ-☇yQv+%P `F&% N:XJu9?IgI9VD5 ҢeG}0Sol񶤃 ''6NPwv8A%ۤ乑uvQ:֩]PḠ)%Pm r:FFs%Hu~T7$ dz;q?+6-[*O0I:-FIvuSIlNB]1QXnsiNA7qdXmq-PJ;02NNI纔lcPGmg PE\ZO c[&=Հ&lP%ݯ>]v:pK:ő'%Mƛxe8֕PJ@ tg8S[Y'Rm~'Yvgu4Ncbs}Ò^2$PQ2lc|KI %F\Iے$GEcI*R.^+Fx+%P vmya;X7%$c?c.dI.lOF7NܞD5ީQh>[ >HxUG *d五4/quj:K:թP?ZPJ@ (%yU\:ۤ$o$)ui}auSv1l'iug+Q'F%yA2)cэm\vs骓 'S_\IbNFu*l>ՕPJ@ (PWl.dLB]:HnsչT:K˺%;XƢtQjӗ(-9dNgR]:H2a:Tu΅REKcPJ@ t''mII?ץ.exiAK~*Rr';"Q%X$ R:E&d'uP;I%NBYҘR9tݨiKJTX-vIJ@ (%@ p {mκKMڹ.p:$dFN~.d{eU0'YRHngrܞɺrrJ}m,}u;i;ήӘFu.l+}+%PՋ󫳝GR&~1܏Fa?I*,Yg\>^KeLJz*M&D*xudӖcH_ |TxX>jQJ@ (%prWt d:awIZ+mTW|~m=&r"4qp !_M9.LFsRjKmͨqlT'%ۃNb.PJ@ dg&I-뜄oK1ldBqR:*QReKZ4/N8bp,]:Rjخ$D]6߶ uz'c֣PJ;JJf"i~X҄ll( X Mh$v2Jcp.Ǻ:չPɖT$;+%W276&Sݶ%E1N n3}nl]l%Qr%Ejvs\dXT)|2tu>.uq$p{N6)e{iW] (%H\vnd1R}\ur%IFϞOjF*4 ˶l/봑|VSڹ΢8BTIK'#˘5a:K;*PJ@ (# s 9m:Ked򳍤+jМHc=F%ب}f-Q-1[R4.J^]1dº-ٟU34iZP$KJ!Іr)DTO)N\L˸U5%PJ# pRStsK}'Vsrd"udbp3$-cݖ4AN$_B%Q]XrJcڲs:\RlTX}%RJ@ (%@(+F\:ۤuWlܒMR %.i.%K[Jz&հ Ф.(u[v+K^ylþQ(RƐNE#fIQ)%P$g>Yg=u)izI)F Y>wǝ9sUZ+bu\OIWx\iҩ g)mNu*26fqGsVPJ@ (%D j.ና66)tGLxv_nr.:DZ?-D&XA6^)%PH%kceݥGRZY:\6IuWFvYx>IO7 gduScF8s9p=H&ԏPJ@ (IbmOF&K$0v\ͥں2E/FڥN:˨6R~٤t*mc-]+%P%Lb劵m~uig% }H٤֩E6[FHኳmAuEV鶏TxNZ0jQJ@ (%:@X6YoKZmZw6ҩpZ+cmieJ㊳mAuűecˠ mթ1b}/PJ@ (%/϶z~ąu? b8֖v_?)J_~1=.}2l+feԓmUWJ@ (%2C /edtWl:6"%G3]ۥ#z&}tUm*PJ@ ("-.}.e#lg)mAsFEƹ[Z38E/ζ|ҞN3TgNtک_ (%T,v.IV!]PU'Ϙ}Ը--K6}ŹM _{E6J@ (%@ -'D_nl~FJ2&$*>b]vT>YsՓQcbԦPJ@ &d1Wl#R'Bq-N>9ؾJ/emL;d'_Pq>%PJxs٣dԉDuWL.L};[6dul[كpۨ2h}hPJ@ (%L%ZA\vۖ:ѱĂ|2.;6r= Q2ź|QlaG2/cѳo2sX%P]@2X2k6Nmvg#;W1Odb۷d;Jx?!T_;gRvXPJ3 d-r,*l,?T+.e8Fde@#dQmd`ʘTlꜴPJ@ (B kIodX8sHT j/N| 7J L4PJ@ (d* OPewxթ-cSwdXam~>?; EmBXAmէPJ@ tA~?]tISㅵ cA9Fde[ՕPJ@ (&l%>(&UQj 묤*q I/!%cUWJ@ (%7dta}v+6~":3Ju(2 DZa2}~%PJ 2%WLŸE.-[g'MmlQi] (%RMtkGj-tLdb limhY)PJ謄,qO&ֵwٖK QsI}*m$t˾TWJ@ (%&tTڧFO+e=L'>i&tƘU)%n:#aKgtf+-IRkYX (%R2Z?ۤL%r(sF$WٚcMj4X (%Pd+VOZG̵#PJ@ (%3H;b0_ΘwgkJ@ (%@ND3L ~'_0|cZ6VJ@ (%Ѝ CstB])JkqnPJ@ (%@&r}]5{PJ@ (%$.uSJ@ (%@&S{sםnZWJ@ (%r@OJ]5YsQٔ?(%P%-0JޯLg-PJ@ tpvu(%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%,a@6W"IENDB`vavr-0.10.0/.javadoc/000077500000000000000000000000001342074374400142435ustar00rootroot00000000000000vavr-0.10.0/.javadoc/stylesheet.css000066400000000000000000000312401342074374400171460ustar00rootroot00000000000000/* Custom Vavr style */ pre { white-space: pre-line !important; } code, tt { white-space: pre-wrap !important; } /* Javadoc style sheet */ /* Overall document style */ @import url('resources/fonts/dejavu.css'); body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; } a:link, a:visited { text-decoration:none; color:#4A6782; } a:hover, a:focus { text-decoration:none; color:#bb7a2a; } a:active { text-decoration:none; color:#4A6782; } a[name] { color:#353833; } a[name]:hover { text-decoration:none; color:#353833; } pre { font-family:'DejaVu Sans Mono', monospace; font-size:14px; } h1 { font-size:20px; } h2 { font-size:18px; } h3 { font-size:16px; font-style:italic; } h4 { font-size:13px; } h5 { font-size:12px; } h6 { font-size:11px; } ul { list-style-type:disc; } code, tt { font-family:'DejaVu Sans Mono', monospace; font-size:14px; padding-top:4px; margin-top:8px; line-height:1.4em; } dt code { font-family:'DejaVu Sans Mono', monospace; font-size:14px; padding-top:4px; } table tr td dt code { font-family:'DejaVu Sans Mono', monospace; font-size:14px; vertical-align:top; padding-top:4px; } sup { font-size:8px; } /* Document title and Copyright styles */ .clear { clear:both; height:0px; overflow:hidden; } .aboutLanguage { float:right; padding:0px 21px; font-size:11px; z-index:200; margin-top:-9px; } .legalCopy { margin-left:.5em; } .bar a, .bar a:link, .bar a:visited, .bar a:active { color:#FFFFFF; text-decoration:none; } .bar a:hover, .bar a:focus { color:#bb7a2a; } .tab { background-color:#0066FF; color:#ffffff; padding:8px; width:5em; font-weight:bold; } /* Navigation bar styles */ .bar { background-color:#4D7A97; color:#FFFFFF; padding:.8em .5em .4em .8em; height:auto;/*height:1.8em;*/ font-size:11px; margin:0; } .topNav { background-color:#4D7A97; color:#FFFFFF; float:left; padding:0; width:100%; clear:right; height:2.8em; padding-top:10px; overflow:hidden; font-size:12px; } .bottomNav { margin-top:10px; background-color:#4D7A97; color:#FFFFFF; float:left; padding:0; width:100%; clear:right; height:2.8em; padding-top:10px; overflow:hidden; font-size:12px; } .subNav { background-color:#dee3e9; float:left; width:100%; overflow:hidden; font-size:12px; } .subNav div { clear:left; float:left; padding:0 0 5px 6px; text-transform:uppercase; } ul.navList, ul.subNavList { float:left; margin:0 25px 0 0; padding:0; } ul.navList li{ list-style:none; float:left; padding: 5px 6px; text-transform:uppercase; } ul.subNavList li{ list-style:none; float:left; } .topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { color:#FFFFFF; text-decoration:none; text-transform:uppercase; } .topNav a:hover, .bottomNav a:hover { text-decoration:none; color:#bb7a2a; text-transform:uppercase; } .navBarCell1Rev { background-color:#F8981D; color:#253441; margin: auto 5px; } .skipNav { position:absolute; top:auto; left:-9999px; overflow:hidden; } /* Page header and footer styles */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } .indexHeader { margin:10px; position:relative; } .indexHeader span{ margin-right:15px; } .indexHeader h1 { font-size:13px; } .title { color:#2c4557; margin:10px 0; } .subTitle { margin:5px 0 0 0; } .header ul { margin:0 0 15px 0; padding:0; } .footer ul { margin:20px 0 5px 0; } .header ul li, .footer ul li { list-style:none; font-size:13px; } /* Heading styles */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; margin:0 0 6px -8px; padding:7px 5px; } ul.blockList ul.blockList ul.blockList li.blockList h3 { background-color:#dee3e9; border:1px solid #d0d9e0; margin:0 0 6px -8px; padding:7px 5px; } ul.blockList ul.blockList li.blockList h3 { padding:0; margin:15px 0; } ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* Page layout container styles */ .contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { clear:both; padding:10px 20px; position:relative; } .indexContainer { margin:10px; position:relative; font-size:12px; } .indexContainer h2 { font-size:13px; padding:0 0 3px 0; } .indexContainer ul { margin:0; padding:0; } .indexContainer ul li { list-style:none; padding-top:2px; } .contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { font-size:12px; font-weight:bold; margin:10px 0 0 0; color:#4E4E4E; } .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; font-family:'DejaVu Sans Mono',monospace; } .serializedFormContainer dl.nameValue dt { margin-left:1px; font-size:1.1em; display:inline; font-weight:bold; } .serializedFormContainer dl.nameValue dd { margin:0 0 0 1px; font-size:1.1em; display:inline; } /* List styles */ ul.horizontal li { display:inline; font-size:0.9em; } ul.inheritance { margin:0; padding:0; } ul.inheritance li { display:inline; list-style:none; } ul.inheritance li ul.inheritance { margin-left:15px; padding-left:15px; padding-top:1px; } ul.blockList, ul.blockListLast { margin:10px 0 10px 0; padding:0; } ul.blockList li.blockList, ul.blockListLast li.blockList { list-style:none; margin-bottom:15px; line-height:1.4; } ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { padding:0px 20px 5px 10px; border:1px solid #ededed; background-color:#f8f8f8; } ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { padding:0 0 5px 8px; background-color:#ffffff; border:none; } ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { margin-left:0; padding-left:0; padding-bottom:15px; border:none; } ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { list-style:none; border-bottom:none; padding-bottom:0; } table tr td dl, table tr td dl dt, table tr td dl dd { margin-top:0; margin-bottom:1px; } /* Table styles */ .overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { width:100%; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } .overviewSummary, .memberSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, .useSummary caption, .constantsSummary caption, .deprecatedSummary caption { position:relative; text-align:left; background-repeat:no-repeat; color:#253441; font-weight:bold; clear:none; overflow:hidden; padding:0px; padding-top:10px; padding-left:1px; margin:0px; white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, .useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, .useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, .useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, .useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { color:#FFFFFF; } .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, .useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; padding-right:12px; padding-bottom:7px; display:inline-block; float:left; background-color:#F8981D; border: none; height:16px; } .memberSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; padding-right:12px; margin-right:3px; display:inline-block; float:left; background-color:#F8981D; height:16px; } .memberSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; padding-right:12px; margin-right:3px; display:inline-block; float:left; background-color:#4D7A97; height:16px; } .memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; background-image:none; float:none; display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, .useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } .memberSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; float:left; background-color:#F8981D; } .memberSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; } .overviewSummary td, .memberSummary td, .typeSummary td, .useSummary td, .constantsSummary td, .deprecatedSummary td { text-align:left; padding:0px 0px 12px 10px; } th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } th.colFirst, th.colLast, th.colOne, .constantsSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { white-space:nowrap; font-size:13px; } td.colLast, th.colLast { font-size:13px; } td.colOne, th.colOne { font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, .useSummary td.colFirst, .useSummary th.colFirst, .overviewSummary td.colOne, .overviewSummary th.colOne, .memberSummary td.colFirst, .memberSummary th.colFirst, .memberSummary td.colOne, .memberSummary th.colOne, .typeSummary td.colFirst{ width:25%; vertical-align:top; } td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } .altColor { background-color:#FFFFFF; } .rowColor { background-color:#EEEEEF; } /* Content styles */ .description pre { margin-top:0; } .deprecatedContent { margin:0; padding:10px 0; } .docSummary { padding:0; } ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } td.colLast div { padding-top:0px; } td.colLast a { padding-bottom:3px; } /* Formatting effect styles */ .sourceLineNo { color:green; padding:0 30px 0 0; } h1.hidden { visibility:hidden; overflow:hidden; font-size:10px; } .block { display:block; margin:3px 10px 2px 0px; color:#474747; } .deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, .overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } div.contentContainer ul.blockList li.blockList h2{ padding-bottom:0px; } vavr-0.10.0/.sputnik/000077500000000000000000000000001342074374400143315ustar00rootroot00000000000000vavr-0.10.0/.sputnik/google_checks.xml000066400000000000000000000253461342074374400176610ustar00rootroot00000000000000 vavr-0.10.0/.travis.yml000066400000000000000000000034251342074374400146730ustar00rootroot00000000000000language: java sudo: false dist: trusty install: echo "Don't let Travis CI execute './gradlew assemble' by default" matrix: include: - jdk: oraclejdk8 - jdk: oraclejdk9 - jdk: openjdk10 - jdk: openjdk11 - jdk: openjdk-ea allow_failures: - jdk: openjdk-ea env: global: - secure: HU0QOLEDkYHcjX+PkicGGQ5g2L1/19V2fH13OSn82DOFlIiWmCfhSI8EG/QoWwPDp/HYQ4DH5Lo+ZEhVz5tgEultItyJ38LZJl/YYOzSAiRvTezmDdz+Cdg6SXAwCvgFCTagEJ1ChL5NyenDGDlwPB/drN0HlNNU6igPqNkM8l0= - secure: VByzrX+inH3Z2nq50Hkj1FJnyOjPdsdIo/RUcl6DxUjkYfXP0n3tkPZGFA0PwiDpEwvRcSGLMR7mJ59Bhja5wgqXNhMqV4F0kB2PEFHSC3UmkyMnTSmDBKvP2aT6JLq00K3mYeNV5HiaYV4S7UVNdzZwaPCgc2aVZN8hF4f5/V8= - secure: GWvKpGPBF1b/2tkYzJ/IwKpGd3kjfYpadIFoQOdQS3r6iZkutZ9FhW6vINIRsgcIRHTVha0BywG7m5sJIYo/jmsDbXc2VJFO7EcXkK6k96VZYb0pHjbXqeP/u9/ZfSzeQ4w3qNYUiXztmmrLjbCzG2gV4D2CqOaug2o81mVj4LI= - secure: m91QxOLHBRnJzRyphCivL79i90pE/FO4yg8qTOaDuyTqVXBKnHmdARFOxSMZN9Qn3B3e28xxPaazIsJGCuPXiQKSObqzPLeFHUOa3atUJSckEUW623l1313A9iMFOYbqSBAHFHmiuuAJBwN/E2OnG3BcLZV1FRibW6J1qLRLdJw= cache: directories: - "$HOME/.m2/repository" - "$HOME/apache-maven-3.5.4" before_install: - unset _JAVA_OPTIONS - export M2_HOME=$HOME/apache-maven-3.5.4 - if [ ! -d $M2_HOME/bin ]; then curl https://archive.apache.org/dist/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz | tar zxf - -C $HOME; fi - export PATH=$M2_HOME/bin:$PATH script: .travis/run-tests.sh after_success: - bash <(curl -s https://codecov.io/bash) - python <(curl -s https://raw.githubusercontent.com/TouK/sputnik-ci/master/sputnik-ci.py) - mvn clean deploy -DskipTests --settings .travis/maven-settings.xml - .travis/trigger-build.sh vavr-gwt - .travis/trigger-build.sh vavr-jackson - .travis/trigger-build.sh vavr-gson - .travis/trigger-build.sh vavr-kotlin vavr-0.10.0/.travis/000077500000000000000000000000001342074374400141445ustar00rootroot00000000000000vavr-0.10.0/.travis/maven-settings.xml000066400000000000000000000012311342074374400176270ustar00rootroot00000000000000 sonatype-nexus-snapshots ${env.SONATYPE_USER} ${env.SONATYPE_PASS} vavr-0.10.0/.travis/run-tests.sh000077500000000000000000000003471342074374400164530ustar00rootroot00000000000000#!/bin/bash set -ev mvn test -B # Break CI build on PRs where committed differ from generated sources if [ -n "$(git status -su vavr/src-gen)" ]; then exit 1 fi if [ -n "$(git status -su vavr-test/src-gen)" ]; then exit 1 fi vavr-0.10.0/.travis/trigger-build.sh000077500000000000000000000011031342074374400172360ustar00rootroot00000000000000#!/bin/bash org="vavr-io" repo=$1 branch=$2 if [ -z $repo ]; then echo "Usage: trigger-build.sh []" else if [ -z $branch ]; then branch="master" fi echo "Triggering travis-ci build of $org/$repo [$branch]..." body=`cat < * **Rule 1. You can't tell where a program is going to spend its time.** Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is. > * **Rule 2. Measure.** Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest. > * **Rule 3. Fancy algorithms are slow when n is small, and n is usually small.** Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.) > * **Rule 4. Fancy algorithms are buggier than simple ones, and they're much harder to implement.** Use simple algorithms as well as simple data structures. > * **Rule 5. Data dominates.** If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming. > > Pike's rules 1 and 2 restate Tony Hoare's famous maxim "Premature optimization is the root of all evil." Ken Thompson rephrased Pike's rules 3 and 4 as "When in doubt, use brute force.". Rules 3 and 4 are instances of the design philosophy KISS. Rule 5 was previously stated by Fred Brooks in The Mythical Man-Month. Rule 5 is often shortened to "write stupid code that uses smart objects". _Source: http://users.ece.utexas.edu/~adnan/pike.html_ ### Javadoc * Public API needs javadoc, e.g. public classes and public methods. * Non-trivial private methods need javadoc, too. * A package, which is part of the public API, contains a `package-info.java`. * Unit tests contain no javadoc at all (because they introduce no new API and contain no business logic). * Running `mvn javadoc:javadoc` results in no javadoc errors. * All classes start with the following copyright notice in order to apply the Apache-2.0 license: ```java /* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ ``` ### Packages * There is only one first-level package: io.vavr. * The maximum package depth is two. * Package names are denoted in the singular. * Packages are sliced by domain (no util or tool packages). * Package private classes are used in order to hide non-public API. * Inner classes are preferred over package private classes in case of one-to-one dependencies. ### File structure We organize our classes and interfaces in the following way: * The Javadoc of the type contains an overview of the new (i.e. not overridden) API declared in the actual type. * The type consists of three sections: 1. static API 2. non-static API 3. adjusted return types * The methods of each of these sections are alphabetically ordered. ```java /** * Description of this class. * *
    *
  • {@link #containsKey(Object)}}
  • *
  • {@link ...}
  • *
* * @author ... */ public interface Map extends Traversable> { // -- static API static Tuple2 entry(K key, V value) { ... } ... // -- non-static API @Override default boolean contains(Tuple2 element) { ... } boolean containsKey(K key); ... // -- Adjusted return types @Override Map distinct(); ... } ``` ### Unit tests * Public API is tested. * High-level functionality is tested in first place. * Corner cases are tested. * Trivial methods are not _directly_ tested, e.g. getters, setters. * The test method name documents the test, i.e. 'shouldFooWhenBarGivenBaz' * In most cases it makes sense to run one assertion per @Test. ### 3rd party libraries * Vavr has no dependencies other than Java. * Unit tests depend solely on junit and assertj. * Benchmarks are done with JMH ## Build ### Useful Maven Goals * Executing tests: `mvn clean test` * Executing doclint: `mvn javadoc:javadoc` * Executing code coverage report: `mvn -P ci clean test jacoco:report` * Create -javadoc.jar: `mvn javadoc:jar` * Create -source.jar: `mvn source:jar` * Update version properties: `mvn versions:update-properties` * Check for new plugin version: `mvn versions:display-plugin-updates` ### Benchmarks If you have dedicated hardware (i.e. no virtual machines) and are interested in how Vavr compares to other alternatives, you can run all benchmarks from the `vavr-benchmark` module via `io.vavr.JmhRunner.main` or running the following Maven command: ```bash mvn clean test -P benchmark -pl vavr-benchmark ``` Note: running all the tests will require several hours, during which there should be no other activity done on the given machine. ### Releasing See http://central.sonatype.org/pages/ossrh-guide.html Sonatype-Nexus specific maven configuration: `~/.m2/settings.xml` ```xml sonatype-nexus-snapshots your-jira-id your-jira-pwd sonatype-nexus-staging your-jira-id your-jira-pwd ``` Note: Detailed information about performing a release can be found in the SCM section. ## SCM * Commits are coarsely granular grouped by feature/change. * Commits do not mix change sets of different domains/purpose. * Commit messages provide enough detail to extract a changelog for a new release. ### Branching Model We following a simple git workflow/branching model: ``` master | | v2.0.x release v2.0.0 - - - - - - + - - - + 2.0.1-SNAPSHOT | | bugfix1 | | | | | PR x---->|<------+ cherry-picking bugfix1 | | featureA | | | | | PR x---->| | | | release v2.0.1 - - - - - - | - - - + 2.0.2-SNAPSHOT | | | | v2.1.x release v2.1.0 - - - - - - + - - - X - - - + 2.1.1-SNAPSHOT | | | | featureB | | | | | PR x---->| | ... ... ``` ## Versioning We follow the [Semantic Versioning](http://semver.org) scheme. ### Backward compatibility We distinguish between 3 kinds of (backward-)compatibilty: 1. **Source** - Source compatibility concerns translating Java source code into class files. 2. **Binary** - Binary compatibility is [defined](http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html#13.2) in The Java Language Specification as preserving the ability to link without error. 3. **Behavioral** - Behavioral compatibility includes the semantics of the code that is executed at runtime. _Source: [OpenJDK Developers Guide v0.777, Kinds of Compatibility](http://cr.openjdk.java.net/~darcy/OpenJdkDevGuide/OpenJdkDevelopersGuide.v0.777.html#compatibility)_ Given a version number `..` Vavr * may affect **behavioral** compatibility in **all kind of releases**, especially bug fix/patch releases. For example we might decide to release a more effective hashing algorithm in the next minor release that reduces the probability of collisions. * may affect **source** compatibility in **patch** releases. For example this may be the case when generic type bounds of method signatures need to be fixed. * retains **binary** backwards compatibility (drop in replacement jar) within the same **minor** version (this includes **patch** versions) * is not **binary** backward compatible when the **major** version changes Summing up, drop-in replacements of Vavr can be made for **minor** and **patch** releases. ### Tool Support We currently check for API changes (which may affect the binary compatibility) using the maven-bundle-plugin: ```bash mvn package org.apache.felix:maven-bundle-plugin:baseline -DcomparisonVersion=2.0.1 -DskipTests ``` In the example above we check API changes between the current branch and the _2.0.1_ tag. In most cases the tag should be the latest official release. ### Major release #### Performing a release Performing a release requires admin-rights. 1. get a fresh copy of the repo `git clone https://github.com/vavr-io/vavr.git` 2. run `mvn clean test` and(!) `mvn javadoc:javadoc` to ensure all is working fine 3. perform the release ```bash mvn release:clean mvn release:prepare mvn release:perform ``` 4. Go to `http://oss.sonatype.org` and stage the release. #### Post-Release steps (e.g. for release v2.1.0) 1. [CAUTION] Delete the old maintenance branch (e.g. v2.0.x) ```bash git push origin :v2.0.x ``` 2. Create the new _maintenance branch_ (e.g. v2.1.x) based on the new release tag (e.g. v2.1.0) ```bash git checkout origin/master git fetch origin git branch v2.1.x v2.1.0 git checkout v2.1.x git push origin v2.1.x ``` 3. Update the version of the _maintenance branch_ ```bash mvn versions:set -DnewVersion=2.1.1-SNAPSHOT ``` When a maintenance release is performed, we increase the last digit of the new development version of the maintenance branch (e.g. 2.1.2-SNAPSHOT). #### Merging specific commits into the maintenance branch Pull requests are merged into master. Only specific commits are merged from master into the maintenance branch. ```bash git checkout v2.1.x git log --date-order --date=iso --graph --full-history --all --pretty=format:'%x08%x09%C(red)%h %C(cyan)%ad%x08%x08%x08%x08%x08%x08%x08%x08%x08%x08%x08%x08%x08%x08%x08 %C(bold green)%aN%C(reset)%C(bold yellow)%d %C(reset)%s' # pick one or more commits from the log, e.g. a741cf1. git cherry-pick a741cf1 ``` ### Bugfix release #### Steps to bugfix and perform a release Given a release 1.2.2, we create a bugfix release as follows. First, we clone the repository. We work on origin instead of a fork (this requires admin rights). ```bash git clone https://github.com/vavr-io/vavr.git vavr-1.2.3 ``` We checkout the release tag and create a new (local) branch. ```bash git checkout v1.2.2 git checkout -b bugfix-release-1.2.3 ``` Then we create the new snapshot version. ```bash mvn versions:set -DnewVersion=1.2.3-SNAPSHOT ``` Now the changes can be performed to the repository. After that, we test the changes. ```bash mvn clean test mvn javadoc:javadoc ``` Then the new files can be added and the changes can be committed. ```bash git add git commit -a -m "fixes #" ``` Then we perform the release as usual: ```bash mvn release:clean mvn release:prepare mvn release:perform ``` Goto oss.sonatype.org and release to Maven Central. #### Housekeeping Delete the branch which was pushed by the maven release plugin to origin: ```bash git checkout master git branch -D bugfix-release-1.2.3 git push origin :bugfix-release-1.2.3 ``` ### Release notes For major, minor and bugfix releases we create release notes on Github. #### Useful commands The number of lines changed by author since a specific date: ```bash git ls-files -z | xargs -0n1 git blame -w --since="3/18/2016" --line-porcelain | grep -a "^author " | sort -f | uniq -c | sort -n -r ``` vavr-0.10.0/LICENSE000066400000000000000000000261351342074374400135720ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. vavr-0.10.0/README.md000066400000000000000000000046371342074374400140470ustar00rootroot00000000000000[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.vavr/vavr/badge.png)](https://maven-badges.herokuapp.com/maven-central/io.vavr/vavr) [![Code Scene](https://img.shields.io/badge/codescene-analyzed-brightgreen.svg)](https://codescene.io/projects/981/jobs/latest-successful/results) [![Build Status](https://travis-ci.org/vavr-io/vavr.png)](https://travis-ci.org/vavr-io/vavr) [![codecov](https://codecov.io/gh/vavr-io/vavr/branch/master/graph/badge.svg)](https://codecov.io/gh/vavr-io/vavr) [![Sputnik](https://sputnik.ci/conf/badge)](https://sputnik.ci/app#/builds/vavr-io/vavr) [![Gitter Chat](https://badges.gitter.im/Join%20Chat.png)](https://gitter.im/vavr-io/vavr) # [Vavr](http://vavr.io/) Vavr is an object-functional language extension to Java 8, which aims to reduce the lines of code and increase code quality. It provides persistent collections, functional abstractions for error handling, concurrent programming, pattern matching and much more. Vavr fuses the power of object-oriented programming with the elegance and robustness of functional programming. The most interesting part is a feature-rich, persistent collection library that smoothly integrates with Java's standard collections. Because Vavr does not depend on any libraries (other than the JVM) you can easily add it as standalone .jar to your classpath. To stay up to date please follow the [blog](http://blog.vavr.io). ## Using Vavr See [User Guide](http://docs.vavr.io) and/or [Javadoc](http://www.javadoc.io/doc/io.vavr/vavr). ### Useful Maven Goals * Executing tests: `mvn clean test` * Executing doclint: `mvn javadoc:javadoc` * Executing code coverage report: `mvn -P ci clean test jacoco:report` * Create -javadoc.jar: `mvn javadoc:jar` * Create -source.jar: `mvn source:jar` * Update version properties: `mvn versions:update-properties` * Check for new plugin version: `mvn versions:display-plugin-updates` ### Benchmarks Currently, only basic microbenchmarks are available. To run: ```bash mvn clean test -P benchmark -pl vavr-benchmark ``` ### Contributing A small number of users have reported problems building Vavr. Read "How to Contribute" (CONTRIBUTING.md) for details. --- If you like Vavr you can support us by donating.
vavr-0.10.0/pom.xml000066400000000000000000000574641342074374400141130ustar00rootroot00000000000000 4.0.0 org.sonatype.oss oss-parent 9 io.vavr vavr-parent 0.10.0 pom Vavr Parent Vavr (formerly called Javaslang) is an object-functional language extension to Java 8+. vavr vavr-benchmark vavr-match vavr-match-processor vavr-test http://vavr.io The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo scm:git:git@github.com:vavr-io/vavr.git scm:git:git@github.com:vavr-io/vavr.git git@github.com:vavr-io/vavr.git v0.10.0 danieldietrich Daniel Dietrich cafebab3@gmail.com UTF-8 3.11.1 1.0.0 1.8 1.21 4.13-beta-1 3.0.0-M2 3.0.0 4.1.0 3.1.0 3.0.0-M1 3.8.0 3.0.0-M1 1.6 0.8.2 3.1.1 3.0.1 2.5.3 2.7 3.0.0-M3 3.0.1 1.5.0 3.4.4 2.12.6 2.12 junit junit ${junit.version} org.assertj assertj-core ${assertj.core.version} org.openjdk.jmh jmh-generator-annprocess ${jmh.version} org.apache.maven.plugins maven-enforcer-plugin ${maven.enforcer.version} enforce-maven enforce 3.5.3 Minimum required Maven version to build vavr is 3.5.3 org.codehaus.mojo versions-maven-plugin ${maven.versions.version} org.apache.maven.plugins maven-install-plugin ${maven.install.version} org.apache.maven.plugins maven-source-plugin ${maven.source.version} attach-sources prepare-package jar-no-fork test-jar-no-fork org.apache.maven.plugins maven-clean-plugin ${maven.clean.version} clean-generated-sources generate-sources clean ${project.basedir}/src-gen net.alchim31.maven scala-maven-plugin ${scala.maven.version} ${scala.version} ${scala.compat.version} true generate-sources script plugin ${project.basedir}/generator/Generator.scala org.apache.maven.plugins maven-release-plugin ${maven.release.version} v@{project.version} forked-path false ${arguments} -Psonatype-oss-release org.codehaus.mojo build-helper-maven-plugin ${maven.build-helper.version} add-source generate-sources add-source ${project.basedir}/src-gen/main/java ${project.build.directory}/generated-sources/annotations add-test-source generate-sources add-test-source ${project.basedir}/src-gen/test/java ${project.build.directory}/generated-test-sources/test-annotations org.apache.maven.plugins maven-compiler-plugin ${maven.compiler.version} ${java.version} ${java.version} true true -Werror -Xlint:all -Xlint:-processing -Xlint:-options org.apache.maven.plugins maven-deploy-plugin ${maven.deploy.version} org.apache.maven.plugins maven-jar-plugin ${maven.jar.version} true ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.apache.maven.plugins maven-javadoc-plugin ${maven.javadoc.version} https://docs.oracle.com/javase/8/docs/api/ ${basedir}/../.javadoc/stylesheet.css org.apache.felix maven-bundle-plugin ${maven.bundle.version} bundle-manifest process-classes manifest org.apache.maven.plugins maven-surefire-plugin ${maven.surefire.version} all 4 true ci env.CI org.jacoco jacoco-maven-plugin ${maven.jacoco.version} prepare-agent report test report release-sign-artifacts performRelease true org.apache.maven.plugins maven-gpg-plugin ${maven.gpg.version} sign-artifacts verify sign eclipse-m2e m2e.version org.eclipse.m2e lifecycle-mapping ${eclipse.lifecycle.mapping.version} org.apache.maven.plugins maven-enforcer-plugin [0,) enforce org.apache.maven.plugins maven-clean-plugin [0,) clean net.alchim31.maven scala-maven-plugin [0,) script org.apache.felix maven-bundle-plugin [0,) manifest benchmark org.codehaus.mojo exec-maven-plugin ${maven.exec.version} test exec test java -classpath io.vavr.JmhRunner org.apache.maven.plugins maven-surefire-plugin ${maven.surefire.version} none vavr-0.10.0/update_copyright.sh000077500000000000000000000010031342074374400164610ustar00rootroot00000000000000#!/bin/bash # == # == New-year script, tested on a Mac # == # Prevent sed error 'illegal byte sequence' export LC_ALL=C LC_CTYPE=C LANG=C newYear=`date +'%Y'` echo "Updating copyright notice to $newYear" # Exclude specific directories: -type d \( -path ./.git -o -path ./.ide \) -prune -o # Make sed work on Mac: sed -e # Prevent making backups: -i '' find . -type d \( -path ./.git -o -path ./.ide \) -prune -o -type f -print0 | xargs -0 sed -i '' -e "s/Copyright 2014-2019 Vavr/Copyright 2014-$newYear Vavr/" vavr-0.10.0/vavr-benchmark/000077500000000000000000000000001342074374400154645ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/pom.xml000066400000000000000000000105641342074374400170070ustar00rootroot00000000000000 4.0.0 io.vavr vavr-parent 0.10.0 ../pom.xml vavr-benchmark Vavr Benchmark Benchmarks for Vavr. http://vavr.io The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo ${project.groupId} vavr ${project.version} org.scalaz scalaz-core_2.12 7.3.0-M8 org.clojure clojure 1.9.0-alpha14 org.pcollections pcollections 2.1.2 org.functionaljava functionaljava-java8 4.6 org.eclipse.collections eclipse-collections 8.0.0 io.usethesource capsule 0.6.1 org.openjdk.jol jol-core 0.7.1 org.jetbrains annotations 15.0 junit junit test org.openjdk.jmh jmh-generator-annprocess test org.codehaus.mojo build-helper-maven-plugin org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-surefire-plugin ${maven.surefire.version} **/*Benchmark.java true org.apache.maven.plugins maven-deploy-plugin true org.apache.maven.plugins maven-install-plugin true useTheSource http://nexus.usethesource.io/content/repositories/public/ vavr-0.10.0/vavr-benchmark/src/000077500000000000000000000000001342074374400162535ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/000077500000000000000000000000001342074374400172325ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/java/000077500000000000000000000000001342074374400201535ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/java/io/000077500000000000000000000000001342074374400205625ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/000077500000000000000000000000001342074374400215405ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/BenchmarkPerformanceReporter.java000066400000000000000000000567261342074374400302220ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.Array; import io.vavr.collection.CharSeq; import io.vavr.collection.Map; import io.vavr.control.Option; import org.openjdk.jmh.infra.BenchmarkParams; import org.openjdk.jmh.results.BenchmarkResult; import org.openjdk.jmh.results.Result; import org.openjdk.jmh.results.RunResult; import org.openjdk.jmh.util.ListStatistics; import java.text.DecimalFormat; import java.util.Comparator; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; public class BenchmarkPerformanceReporter { private static final Comparator TO_STRING_COMPARATOR = Comparator.comparing(String::length).thenComparing(Function.identity()); private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00"); private static final DecimalFormat PERFORMANCE_FORMAT = new DecimalFormat("#0.00"); private static final DecimalFormat PCT_FORMAT = new DecimalFormat("0.00%"); private final Array includeNames; private final Array benchmarkClasses; private final Array runResults; private final String targetImplementation; private final double outlierLowPct; private final double outlierHighPct; public static BenchmarkPerformanceReporter of(Array includeNames, Array benchmarkClasses, Array runResults) { return of(includeNames, benchmarkClasses, runResults, "vavr", 0.3, 0.05); } public static BenchmarkPerformanceReporter of(Array includeNames, Array benchmarkClasses, Array runResults, String targetImplementation, double outlierLowPct, double outlierHighPct) { return new BenchmarkPerformanceReporter(includeNames, benchmarkClasses, runResults, targetImplementation, outlierLowPct, outlierHighPct); } /** * This class prints performance reports about the execution of individual tests, comparing their performance * against other implementations as required. * * @param benchmarkClasses The benchmarked source class names * @param runResults The results * @param targetImplementation The target implementation we want to focus on in the Ratio report. * It is case insensitive. If we enter "vavr", it will match "VaVr" and "va_vr". * @param outlierLowPct The percentage of samples on the lower end that will be ignored from the statistics * @param outlierHighPct The percentage of samples on the higher end that will be ignored from the statistics */ private BenchmarkPerformanceReporter(Array includeNames, Array benchmarkClasses, Array runResults, String targetImplementation, double outlierLowPct, double outlierHighPct) { this.includeNames = includeNames; this.benchmarkClasses = benchmarkClasses; this.runResults = runResults; this.targetImplementation = targetImplementation; this.outlierLowPct = outlierLowPct; this.outlierHighPct = outlierHighPct; } /** * Prints all performance reports */ public void print() { printDetailedPerformanceReport(); printRatioPerformanceReport(); } /** * Prints the detail performance report for each individual test. *
* For each test it prints out: *
    *
  • Group
  • *
  • Test Name
  • *
  • Implementation - tests can have different implementations, e.g. Scala, Java, Vavr
  • *
  • Parameters
  • *
  • Score
  • *
  • Error - 99% confidence interval expressed in % of the Score
  • *
  • Unit - units for the Score
  • *
  • Alternative implementations - compares performance of this test against alternative implementations
  • *
*/ public void printDetailedPerformanceReport() { final Array results = mapToTestExecutions(); if (results.isEmpty()) { return; } new DetailedPerformanceReport(results).print(); } /** * Prints the performance ratio report for each test, and compares the performance against different implementations * of the same operation. *
* For each test it prints out: *
    *
  • Group
  • *
  • Test Name
  • *
  • Ratio - A/B means implementation A is compared against base implementation B
  • *
  • Results - How many times faster implementation A is compared with B
  • *
*/ public void printRatioPerformanceReport() { final Array results = mapToTestExecutions(); if (results.isEmpty()) { return; } new RatioPerformanceReport(results, targetImplementation).print(); } private Array mapToTestExecutions() { Array executions = Array.empty(); for (RunResult runResult : runResults) { executions = executions.append(TestExecution.of(runResult.getAggregatedResult(), outlierLowPct, outlierHighPct)); } return sort(executions, includeNames); } private Array sort(Array results, Array includeNames) { final Comparator comparator = Comparator . comparing(t -> benchmarkClasses.indexWhere(c -> c.endsWith(t.getOperation()))) .thenComparing(t -> includeNames.indexWhere(i -> t.getImplementation().startsWith(i))); return results.sorted(comparator); } private String padLeft(String str, int size) { return str + CharSeq.repeat(' ', size - str.length()); } private String padRight(String str, int size) { return CharSeq.repeat(' ', size - str.length()) + str; } private class DetailedPerformanceReport { private final Array results; private final Map> resultsByKey; private final int paramKeySize; private final int groupSize; private final int nameSize; private final int implSize; private final int countSize; private final int scoreSize; private final int errorSize; private final int unitSize; private final Array alternativeImplementations; public DetailedPerformanceReport(Array results) { this.results = results; resultsByKey = results.groupBy(TestExecution::getTestNameParamKey); paramKeySize = Math.max(results.map(r -> r.getParamKey().length()).max().get(), 10); groupSize = Math.max(results.map(r -> r.getTarget().length()).max().get(), 10); nameSize = Math.max(results.map(r -> r.getOperation().length()).max().get(), 10); implSize = Math.max(results.map(r -> r.getImplementation().length()).max().get(), 10); countSize = Math.max(results.map(r -> Long.toString(r.getSampleCount()).length()).max().get(), 5); scoreSize = Math.max(results.map(r -> r.getScoreFormatted().length()).max().get(), 15); errorSize = Math.max(results.map(r -> r.getScoreErrorPct().length()).max().get(), 10); unitSize = Math.max(results.map(r -> r.getUnit().length()).max().get(), 7); alternativeImplementations = results.map(TestExecution::getImplementation).distinct(); } public void print() { printHeader(); printDetails(); } private void printHeader() { final String alternativeImplHeader = alternativeImplementations.map(altImpl -> padRight(altImpl, altImplColSize(altImpl))).mkString(" "); final String header = String.format("%s %s %s %s %s %s ±%s %s %s", padLeft("Target", groupSize), padLeft("Operation", nameSize), padLeft("Impl", implSize), padRight("Params", paramKeySize), padRight("Count", countSize), padRight("Score", scoreSize), padRight("Error", errorSize), padRight("Unit", unitSize), alternativeImplHeader ); System.out.println("\n\n\n"); System.out.println("Detailed Performance Execution Report"); System.out.println(CharSeq.of("=").repeat(header.length())); System.out.println(" (Error: ±99% confidence interval, expressed as % of Score)"); if (outlierLowPct > 0.0 && outlierHighPct > 0.0) { System.out.println(String.format(" (Outliers removed: %s low end, %s high end)", PCT_FORMAT.format(outlierLowPct), PCT_FORMAT.format(outlierHighPct))); } if (!alternativeImplementations.isEmpty()) { System.out.println(String.format(" (%s: read as current row implementation is x times faster than alternative implementation)", alternativeImplementations.mkString(", "))); } System.out.println(); System.out.println(header); } private void printDetails() { for (TestExecution result : results) { System.out.println(String.format("%s %s %s %s %s %s ±%s %s %s", padLeft(result.getTarget(), groupSize), padLeft(result.getOperation(), nameSize), padLeft(result.getImplementation(), implSize), padRight(result.getParamKey(), paramKeySize), padRight(Long.toString(result.getSampleCount()), countSize), padRight(result.getScoreFormatted(), scoreSize), padRight(result.getScoreErrorPct(), errorSize), padRight(result.getUnit(), unitSize), calculatePerformanceStr(result, alternativeImplementations, resultsByKey) )); } System.out.println("\n"); } private int altImplColSize(String name) { return Math.max(5, name.length()); } private String calculatePerformanceStr(TestExecution result, Array alternativeImplementations, Map> resultsByKey) { final String aggregateKey = result.getTestNameParamKey(); final Array alternativeResults = resultsByKey.get(aggregateKey).getOrElse(Array::empty); return alternativeImplementations.map(altImpl -> Tuple.of(altImpl, alternativeResults.find(r -> altImpl.equals(r.getImplementation())))) .map(alt -> Tuple.of(alt._1, calculateRatioStr(result, alt._2))) .map(alt -> padRight(alt._2, altImplColSize(alt._1))) .mkString(" "); } private String calculateRatioStr(TestExecution baseResult, Option alternativeResult) { if (!alternativeResult.isDefined()) { return ""; } final double alternativeScore = alternativeResult.get().getScore(); if (alternativeScore == 0.0) { return ""; } final double ratio = baseResult.getScore() / alternativeScore; return ratio == 1.0 ? "" : PERFORMANCE_FORMAT.format(ratio) + "×"; } } private class RatioPerformanceReport { private final Map> resultsByKey; private final int groupSize; private final int nameSize; private final Array paramKeys; private final int paramKeySize; private final Array alternativeImplementations; private final int alternativeImplSize; private final int ratioSize; private final Array targetImplementations; private final String targetImplementation; public RatioPerformanceReport(Array results, String targetImplementation) { this.targetImplementation = targetImplementation; resultsByKey = results.groupBy(TestExecution::getTestNameKey); groupSize = Math.max(results.map(r -> r.getTarget().length()).max().get(), 10); nameSize = Math.max(results.map(r -> r.getOperation().length()).max().get(), 9); paramKeys = results.map(TestExecution::getParamKey).distinct().sorted(TO_STRING_COMPARATOR); paramKeySize = Math.max(results.map(r -> r.getParamKey().length()).max().get(), 8); alternativeImplementations = results.map(TestExecution::getImplementation).distinct(); targetImplementations = alternativeImplementations.filter(i -> i.toLowerCase().contains(targetImplementation.toLowerCase())); alternativeImplSize = Math.max(alternativeImplementations.map(String::length).max().getOrElse(0), 10); final int targetImplSize = Math.max(targetImplementations.map(String::length).max().getOrElse(0), 10); ratioSize = Math.max(targetImplSize + 1 + alternativeImplSize, 10); } public void print() { printHeader(); printReport(); } private void printHeader() { System.out.println("\n\n"); System.out.println("Performance Ratios"); System.out.println(CharSeq.of("=").repeat(ratioHeaderNumerator().length())); if (outlierLowPct > 0.0 && outlierHighPct > 0.0) { System.out.println(String.format(" (Outliers removed: %s low end, %s high end)", PCT_FORMAT.format(outlierLowPct), PCT_FORMAT.format(outlierHighPct))); } } private String ratioHeaderNumerator() { final String paramKeyHeader = paramKeys.map(type -> padRight(type, paramKeySize)).mkString(" "); return String.format("%s %s %s %s ", padLeft("Target", groupSize), padLeft("Operation", nameSize), padLeft("Ratio", ratioSize), paramKeyHeader ); } private String ratioHeaderDenominator() { final String paramKeyHeader = paramKeys.map(type -> padRight(type, paramKeySize)).mkString(" "); return String.format("%s %s %s %s ", padLeft("Target", groupSize), padLeft("Operation", nameSize), padRight("Ratio", ratioSize), paramKeyHeader ); } private void printReport() { if (alternativeImplementations.size() < 2) { System.out.println("(nothing to report, you need at least two different implementation)"); return; } printTargetInDenominator(); printTargetInNumerator(); System.out.println("\n"); } @SuppressWarnings("Convert2MethodRef") private void printTargetInNumerator() { System.out.println(String.format("\nRatios %s / ", targetImplementation)); System.out.println(ratioHeaderNumerator()); for (String targetImpl : targetImplementations) { for (Tuple2> execution : resultsByKey) { printRatioForBaseType(targetImpl, execution._2, (baseImpl, alternativeImpl) -> padLeft(String.format("%s/%s", baseImpl, alternativeImpl), ratioSize), (baseExec, alternativeExec) -> calculateRatios(baseExec, alternativeExec)); } } } private void printTargetInDenominator() { System.out.println(String.format("\nRatios / %s", targetImplementation)); System.out.println(ratioHeaderDenominator()); for (String targetImpl : targetImplementations) { for (Tuple2> execution : resultsByKey) { printRatioForBaseType(targetImpl, execution._2, (baseImpl, alternativeImpl) -> padRight(String.format("%s/%s", alternativeImpl, baseImpl), ratioSize), (baseExec, alternativeExec) -> calculateRatios(alternativeExec, baseExec)); } } } private void printRatioForBaseType(String baseType, Array testExecutions, BiFunction ratioNamePrinter, BiFunction, Array, String> ratioCalculator) { final Array baseImplExecutions = testExecutions.filter(e -> e.getImplementation().equals(baseType)); if (baseImplExecutions.isEmpty()) { return; } final TestExecution baseTypeExecution = baseImplExecutions.head(); for (String alternativeImpl : alternativeImplementations) { if (alternativeImpl.equals(baseType)) { continue; } final Array alternativeExecutions = testExecutions.filter(e -> e.getImplementation().equals(alternativeImpl)); if (alternativeExecutions.isEmpty()) { continue; } System.out.println(String.format("%s %s %s %s", padLeft(baseTypeExecution.getTarget(), groupSize), padLeft(baseTypeExecution.getOperation(), nameSize), ratioNamePrinter.apply(baseType, alternativeImpl), ratioCalculator.apply(baseImplExecutions, alternativeExecutions))); } System.out.println(); } private String calculateRatios(Array alternativeExecutions, Array baseImplExecutions) { Array ratioStings = Array.empty(); for (String paramKey : paramKeys) { final Option alternativeExecution = alternativeExecutions.find(e -> e.getParamKey().equals(paramKey)); final Option baseExecution = baseImplExecutions.find(e -> e.getParamKey().equals(paramKey)); final String paramRatio = alternativeExecution.isEmpty() || baseExecution.isEmpty() || baseExecution.get().getScore() == 0.0 ? "" : PERFORMANCE_FORMAT.format(alternativeExecution.get().getScore() / baseExecution.get().getScore()) + "×"; ratioStings = ratioStings.append(padRight(paramRatio, paramKeySize)); } return ratioStings.mkString(" "); } } public static class TestExecution implements Comparable { private static double outlierLowPct; private static double outlierHighPct; private final String paramKey; private final String fullName; private final String target; private final String operation; private final String implementation; private final long sampleCount; private final double score; private final double scoreError; private final String unit; public static TestExecution of(BenchmarkResult benchmarkResult, double outlierLowPct, double outlierHighPct) { TestExecution.outlierLowPct = outlierLowPct; TestExecution.outlierHighPct = outlierHighPct; return new TestExecution(benchmarkResult); } public TestExecution(BenchmarkResult benchmark) { final Result primaryResult = benchmark.getPrimaryResult(); fullName = benchmark.getParams().getBenchmark(); target = extractPart(fullName, 2); operation = extractPart(fullName, 1); implementation = extractPart(fullName, 0); paramKey = getParameterKey(benchmark); final ListStatistics statistics = createStatisticsWithoutOutliers(benchmark, outlierLowPct, outlierHighPct); sampleCount = statistics.getN(); score = statistics.getMean(); scoreError = statistics.getMeanErrorAt(0.999); unit = primaryResult.getScoreUnit(); } private ListStatistics createStatisticsWithoutOutliers(BenchmarkResult benchmark, double outlierLowPct, double outlierHighPct) { Array results = benchmark.getIterationResults().stream() .map(r -> r.getPrimaryResult().getScore()) .collect(Array.collector()); final int size = results.size(); final int outliersLow = (int) (size * outlierLowPct); final int outliersHigh = (int) (size * outlierHighPct); results = results.drop(outliersLow).dropRight(outliersHigh); return new ListStatistics(results.toJavaList().stream().mapToDouble(r -> r).toArray()); } private String getParameterKey(BenchmarkResult benchmarkResult) { final BenchmarkParams params = benchmarkResult.getParams(); return params.getParamsKeys().stream().map(params::getParam).collect(Collectors.joining(";")); } public String getTestNameParamKey() { return target + ":" + operation + ":" + unit + ":" + paramKey; } public String getTestNameKey() { return target + ":" + operation + ":" + unit; } private String extractPart(String fullyQualifiedName, int indexFromLast) { final String[] parts = fullyQualifiedName.split("\\."); return parts.length > indexFromLast ? parts[parts.length - indexFromLast - 1] : ""; } public String getParamKey() { return paramKey; } public String getTarget() { return target; } public String getOperation() { return operation; } public String getImplementation() { return implementation; } public long getSampleCount() { return sampleCount; } public double getScore() { return score; } public String getScoreFormatted() { return DECIMAL_FORMAT.format(score); } public String getScoreErrorPct() { return PCT_FORMAT.format(score == 0 ? 0 : scoreError / score); } public String getUnit() { return unit; } @Override public String toString() { return String.format("%s %s %s %s -> %s (± %s)", paramKey, target, operation, implementation, getScoreFormatted(), getScoreErrorPct()); } Comparator comparator = Comparator .comparing(TestExecution::getUnit) .thenComparing(TestExecution::getTarget) .thenComparing(TestExecution::getParamKey) .thenComparing(TestExecution::getOperation) .thenComparing(TestExecution::getImplementation); @Override public int compareTo(TestExecution o) { return comparator.compare(this, o); } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/JmhRunner.java000066400000000000000000000213441342074374400243170ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.*; import io.vavr.control.LazyBenchmark; import io.vavr.idiom.ForBenchmark; import io.vavr.idiom.PatternMatchingBenchmark; import io.vavr.idiom.TryBenchmark; import io.vavr.idiom.TupleBenchmark; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.results.RunResult; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.ChainedOptionsBuilder; import org.openjdk.jmh.runner.options.OptionsBuilder; import org.openjdk.jmh.runner.options.TimeValue; import org.openjdk.jmh.runner.options.VerboseMode; import java.util.Collection; import java.util.Random; import java.util.concurrent.TimeUnit; import static io.vavr.API.Array; public class JmhRunner { /** * Runs all the available benchmarks in precision mode. * Note: it takes about 3 hours. */ public static void main(String[] args) { final Array> CLASSES = Array( ArrayBenchmark.class, BitSetBenchmark.class, CharSeqBenchmark.class, HashSetBenchmark.class, ListBenchmark.class, MapBenchmark.class, PriorityQueueBenchmark.class, VectorBenchmark.class, LazyBenchmark.class, ForBenchmark.class, PatternMatchingBenchmark.class, TryBenchmark.class, TupleBenchmark.class ); runDebugWithAsserts(CLASSES); runSlowNoAsserts(CLASSES); } public enum Includes { JAVA("java"), FUNCTIONAL_JAVA("fjava"), PCOLLECTIONS("pcollections"), ECOLLECTIONS("ecollections"), CAPSULE("capsule"), CLOJURE("clojure"), SCALAZ("scalaz"), SCALA("scala"), VAVR("vavr"); private final String name; Includes(String name) { this.name = name; } @Override public String toString() { return name; } } /** enables debugging and assertions for benchmarks and production code - the speed results will be totally unreliable */ public static void runDebugWithAsserts(Array> groups, Includes... includes) { run(0, 1, 1, ForkJvm.DISABLE, VerboseMode.SILENT, Assertions.ENABLE, PrintInlining.DISABLE, groups, includes); MemoryUsage.printAndReset(); } @SuppressWarnings("unused") public static void runQuickNoAsserts(Array> groups, Includes... includes) { run(5, 5, 10, ForkJvm.ENABLE, VerboseMode.NORMAL, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print(); } @SuppressWarnings("unused") public static void runNormalNoAsserts(Array> groups, Includes... includes) { run(7, 7, 300, ForkJvm.ENABLE, VerboseMode.NORMAL, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print(); } @SuppressWarnings("unused") public static void runSlowNoAsserts(Array> groups, Includes... includes) { run(15, 15, 400, ForkJvm.ENABLE, VerboseMode.EXTRA, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print(); } private static BenchmarkPerformanceReporter run(int warmupIterations, int measurementIterations, int millis, ForkJvm forkJvm, VerboseMode silent, Assertions assertions, PrintInlining printInlining, Array> groups, Includes[] includes) { final Array includeNames = Array.of(includes.length == 0 ? Includes.values() : includes).map(Includes::toString); final Array classNames = groups.map(Class::getCanonicalName); final Array results = run(warmupIterations, measurementIterations, millis, forkJvm, silent, assertions, printInlining, classNames, includeNames); return BenchmarkPerformanceReporter.of(includeNames, classNames, results); } private static Array run(int warmupIterations, int measurementIterations, int millis, ForkJvm forkJvm, VerboseMode verboseMode, Assertions assertions, PrintInlining printInlining, Array classNames, Array includeNames) { try { final ChainedOptionsBuilder builder = new OptionsBuilder() .shouldDoGC(true) .verbosity(verboseMode) .shouldFailOnError(true) .mode(Mode.Throughput) .timeUnit(TimeUnit.SECONDS) .warmupTime(TimeValue.milliseconds(millis)) .warmupIterations(warmupIterations) .measurementTime(TimeValue.milliseconds(millis)) .measurementIterations(measurementIterations) .forks(forkJvm.forkCount) /* We are using 4Gb and setting NewGen to 100% to avoid GC during testing. Any GC during testing will destroy the iteration (i.e. introduce unreliable noise in the measurement), which should get ignored as an outlier */ .jvmArgsAppend("-XX:+UseG1GC", "-Xss100m", "-Xms4g", "-Xmx4g", "-XX:MaxGCPauseMillis=1000", "-XX:+UnlockExperimentalVMOptions", "-XX:G1NewSizePercent=100", "-XX:G1MaxNewSizePercent=100", assertions.vmArg); final String includePattern = includeNames.mkString("\\..*?\\b(", "|", ")_"); classNames.forEach(name -> builder.include(name + includePattern)); if (printInlining == PrintInlining.ENABLE) { builder.jvmArgsAppend("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining"); /* might help in deciding when the JVM is properly warmed up - or where to optimize the code */ } return Array.ofAll(new Runner(builder.build()).run()); } catch (RunnerException e) { throw new RuntimeException(e); } } /* Options */ private enum ForkJvm { ENABLE(1), DISABLE(0); final int forkCount; ForkJvm(int forkCount) { this.forkCount = forkCount; } } private enum Assertions { ENABLE("-enableassertions"), DISABLE("-disableassertions"); final String vmArg; Assertions(String vmArg) { this.vmArg = vmArg; } } private enum PrintInlining { ENABLE, DISABLE } /* Helper methods */ public static Integer[] getRandomValues(int size, int seed) { return getRandomValues(size, seed, false); } public static Integer[] getRandomValues(int size, int seed, boolean nonNegative) { return getRandomValues(size, nonNegative, new Random(seed)); } public static Integer[] getRandomValues(int size, boolean nonNegative, Random random) { final Integer[] results = new Integer[size]; for (int i = 0; i < size; i++) { final int value = random.nextInt(size) - (nonNegative ? 0 : (size / 2)); results[i] = value; } return results; } /** Randomly mutate array positions */ public static int[] shuffle(int[] array, Random random) { for (int i = array.length; i > 1; i--) { swap(array, i - 1, random.nextInt(i)); } return array; } static void swap(int[] array, int i, int j) { final int temp = array[i]; array[i] = array[j]; array[j] = temp; } /** used for dead code elimination and correctness assertion inside the benchmarks */ public static int aggregate(int x, int y) { return x ^ y; } /** simplifies construction of immutable collections - with assertion and memory benchmarking */ public static , R> R create(Function1 function, T source, Function1 assertion) { return create(function, source, source.size(), assertion); } @SuppressWarnings("unchecked") public static R create(Function1 function, T source, int elementCount, Function1 assertion) { final R result = function.apply(source); assert assertion.apply(result); MemoryUsage.storeMemoryUsages(elementCount, result); return result; } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/MemoryUsage.java000066400000000000000000000074241342074374400246470ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.*; import org.openjdk.jol.info.GraphLayout; import java.text.DecimalFormat; import java.util.function.Predicate; import java.util.regex.Pattern; import static java.lang.Math.max; public class MemoryUsage { private static final DecimalFormat FORMAT = new DecimalFormat("#,##0"); private static Map>> memoryUsages = TreeMap.empty(); // if forked, this will be reset every time /** Calculate the occupied memory of different internals */ static void printAndReset() { for (Tuple2>> entry : memoryUsages) { final Seq columnSizes = columnSizes(entry._1); System.out.println(String.format("\nfor `%d` elements", entry._1)); for (Seq stats : entry._2) { final String format = String.format(" %s → %s bytes", stats.get(0).padTo(columnSizes.get(0), ' '), stats.get(1).leftPadTo(columnSizes.get(1), ' ') ); System.out.println(format); } } memoryUsages = memoryUsages.take(0); // reset } private static Seq columnSizes(int size) { return memoryUsages.get(size) .map(rows -> rows.map(row -> row.map(CharSeq::length))).get() .reduce((row1, row2) -> row1.zip(row2).map(ts -> max(ts._1, ts._2))); } static void storeMemoryUsages(int elementCount, Object target) { memoryUsages = memoryUsages.put(elementCount, memoryUsages.get(elementCount).getOrElse(LinkedHashSet.empty()).add(Array.of( toHumanReadableName(target), toHumanReadableByteSize(target) ).map(CharSeq::of))); } private static String toHumanReadableByteSize(Object target) { return FORMAT.format(byteSize(target)); } private static long byteSize(Object target) { return GraphLayout.parseInstance(target).totalSize(); } private static HashMap, String> names = HashMap.ofEntries( Tuple.of("^java\\.", "Java mutable @ "), Tuple.of("^fj\\.", "Functional Java persistent @ "), Tuple.of("^org\\.pcollections", "PCollections persistent @ "), Tuple.of("^org\\.eclipse\\.collections", "Eclipse Collections persistent @ "), Tuple.of("^clojure\\.", "Clojure persistent @ "), Tuple.of("^scalaz\\.Heap", "Scalaz persistent @ "), Tuple.of("^scala\\.collection.immutable", "Scala persistent @ "), Tuple.of("^scala\\.collection.mutable", "Scala mutable @ "), Tuple.of("^io\\.usethesource", "Capsule persistent @ "), Tuple.of("^io\\.vavr\\.", "Vavr persistent @ ") ).mapKeys(r -> Pattern.compile(r).asPredicate()); private static String toHumanReadableName(Object target) { final Class type = target.getClass(); return prefix(type) + type.getSimpleName(); } private static String prefix(Class type) { return names.find(p -> p._1.test(type.getName())).get()._2; } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/000077500000000000000000000000001342074374400236735ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/ArrayBenchmark.java000066400000000000000000000332441342074374400274350ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import java.util.ArrayList; import java.util.Objects; import static java.util.Arrays.asList; import static io.vavr.JmhRunner.create; import static io.vavr.JmhRunner.getRandomValues; import static io.vavr.collection.Collections.areEqual; public class ArrayBenchmark { static final Array> CLASSES = Array.of( Create.class, Head.class, Tail.class, Get.class, Update.class, Prepend.class, Append.class, Iterate.class , Fill.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({"10", "100", "1000", "2500"}) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; Integer[] ELEMENTS; java.util.ArrayList javaMutable; fj.data.Array fjavaMutable; io.vavr.collection.Array vavrPersistent; org.pcollections.PVector pcollVector; @Setup public void setup() { ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate); javaMutable = create(java.util.ArrayList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); fjavaMutable = create(fj.data.Array::array, ELEMENTS, ELEMENTS.length, v -> areEqual(v, asList(ELEMENTS))); vavrPersistent = create(io.vavr.collection.Array::ofAll, javaMutable, v -> areEqual(v, javaMutable)); pcollVector = create(org.pcollections.TreePVector::from, javaMutable, v -> areEqual(v, javaMutable)); } } public static class Create extends Base { @Benchmark public Object java_mutable() { final ArrayList values = new ArrayList<>(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object fjava_persistent() { final fj.data.Array values = fj.data.Array.iterableArray(javaMutable); assert areEqual(values, fjavaMutable); return values; } @Benchmark public Object vavr_persistent() { final io.vavr.collection.Array values = io.vavr.collection.Array.ofAll(javaMutable); assert areEqual(values, vavrPersistent); return values.head(); } @Benchmark public Object pcoll_vector() { final org.pcollections.PVector values = org.pcollections.TreePVector.from(javaMutable); assert areEqual(values, pcollVector); return values; } } public static class Head extends Base { @Benchmark public Object java_mutable() { final Object head = javaMutable.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object fjava_mutable() { final Object head = fjavaMutable.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent() { final Object head = vavrPersistent.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object pcoll_vector() { final Object head = pcollVector.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } } @SuppressWarnings("Convert2MethodRef") public static class Tail extends Base { @State(Scope.Thread) public static class Initialized { final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); @Setup(Level.Invocation) public void initializeMutable(Base state) { java.util.Collections.addAll(javaMutable, state.ELEMENTS); assert areEqual(javaMutable, asList(state.ELEMENTS)); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); } } @Benchmark public Object java_mutable(Initialized state) { final java.util.ArrayList values = state.javaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values.remove(0); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } @Benchmark public Object pcoll_vector() { org.pcollections.PVector values = pcollVector; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.minus(1); } assert values.isEmpty(); return values; } } public static class Get extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_mutable() { int aggregate = 0; for (int i = 0; i < ELEMENTS.length; i++) { aggregate ^= fjavaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= vavrPersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public Object pcoll_vector() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= pcollVector.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } public static class Update extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList values = javaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values.set(i, 0); } assert Iterator.ofAll(values).forAll(e -> e == 0); return javaMutable; } @Benchmark public Object fjava_mutable() { final fj.data.Array values = fjavaMutable; for (int i = 0; i < ELEMENTS.length; i++) { values.set(i, 0); } assert values.forall(e -> e == 0); return fjavaMutable; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.update(i, 0); } assert values.forAll(e -> e == 0); return values; } @Benchmark public Object pcoll_vector() { org.pcollections.PVector values = pcollVector; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.with(i, 0); } assert Iterator.ofAll(values).forAll(e -> e == 0); return values; } } public static class Prepend extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(0, element); } assert areEqual(List.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object fjava_mutable() { fj.data.Array values = fj.data.Array.empty(); for (Integer element : ELEMENTS) { values = fj.data.Array.array(element).append(values); } assert areEqual(values.reverse(), javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array values = io.vavr.collection.Array.empty(); for (Integer element : ELEMENTS) { values = values.prepend(element); } assert areEqual(values.reverse(), javaMutable); return values; } @Benchmark public Object pcoll_vector() { org.pcollections.PVector values = org.pcollections.TreePVector.empty(); for (Integer element : ELEMENTS) { values = values.plus(0, element); } assert areEqual(List.ofAll(values).reverse(), javaMutable); return values; } } public static class Append extends Base { @SuppressWarnings("ManualArrayToCollectionCopy") @Benchmark public Object java_mutable() { final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object fjava_mutable() { fj.data.Array values = fj.data.Array.empty(); for (Integer element : ELEMENTS) { values = values.append(fj.data.Array.array(element)); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array values = io.vavr.collection.Array.empty(); for (Integer element : ELEMENTS) { values = values.append(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object pcoll_vector() { org.pcollections.PVector values = org.pcollections.TreePVector.empty(); for (Integer element : ELEMENTS) { values = values.plus(element); } assert areEqual(values, javaMutable); return values; } } @SuppressWarnings("ForLoopReplaceableByForEach") public static class Iterate extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_mutable() { int aggregate = 0; for (final java.util.Iterator iterator = fjavaMutable.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int pcoll_vector() { int aggregate = 0; for (final java.util.Iterator iterator = pcollVector.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } public static class Fill extends Base { @Benchmark public Object vavr_persistent_constant_supplier() { final io.vavr.collection.Array values = io.vavr.collection.Array.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent_constant_object() { final io.vavr.collection.Array values = io.vavr.collection.Array.fill(CONTAINER_SIZE, ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/BitSetBenchmark.java000066400000000000000000000101751342074374400275470ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import static io.vavr.JmhRunner.create; import static io.vavr.JmhRunner.getRandomValues; import static io.vavr.collection.Collections.areEqual; import static scala.collection.JavaConverters.asJavaCollection; import static scala.collection.JavaConverters.asScalaBuffer; public class BitSetBenchmark { static final Array> CLASSES = Array.of( AddAll.class, Iterate.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({"10", "100", "1000", "2500"}) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; int[] ELEMENTS; TreeSet DISTINCT; scala.collection.immutable.BitSet scalaPersistent; io.vavr.collection.BitSet vavrPersistent; @Setup @SuppressWarnings("RedundantCast") public void setup() { final Integer[] values = getRandomValues(CONTAINER_SIZE, 0, true); ELEMENTS = new int[CONTAINER_SIZE]; for (int i = 0; i < CONTAINER_SIZE; i++) { ELEMENTS[i] = values[i]; } DISTINCT = TreeSet.ofAll(ELEMENTS); EXPECTED_AGGREGATE = DISTINCT.reduce(JmhRunner::aggregate); scalaPersistent = create(v -> (scala.collection.immutable.BitSet) scala.collection.immutable.BitSet$.MODULE$.apply(asScalaBuffer(v)), DISTINCT.toJavaList(), v -> areEqual(asJavaCollection(v), DISTINCT)); vavrPersistent = create(io.vavr.collection.BitSet::ofAll, ELEMENTS, ELEMENTS.length, v -> areEqual(v, DISTINCT)); } } public static class AddAll extends Base { @Benchmark public Object scala_persistent() { scala.collection.immutable.BitSet values = new scala.collection.immutable.BitSet.BitSet1(0L); for (int element : ELEMENTS) { values = values.$plus(element); } assert values.equals(scalaPersistent); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Set values = io.vavr.collection.BitSet.empty(); for (Integer element : ELEMENTS) { values = values.add(element); } assert values.equals(vavrPersistent); return values; } } @SuppressWarnings("ForLoopReplaceableByForEach") public static class Iterate extends Base { @Benchmark public int scala_persistent() { int aggregate = 0; for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= (Integer) iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final io.vavr.collection.Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/CharSeqBenchmark.java000066400000000000000000000230661342074374400277060ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import java.util.Objects; import java.util.Random; import static java.lang.String.valueOf; import static io.vavr.JmhRunner.create; import static io.vavr.collection.Collections.areEqual; public class CharSeqBenchmark { static final Array> CLASSES = Array.of( Head.class, Tail.class, Get.class, Update.class, Repeat.class, Prepend.class, Append.class, Iterate.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(java.lang.String... args) { JmhRunner.runDebugWithAsserts(CLASSES); JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({"10", "100", "1000", "2500"}) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; char[] ELEMENTS; java.lang.String javaPersistent; fj.data.LazyString fjavaPersistent; io.vavr.collection.CharSeq vavrPersistent; @Setup public void setup() { final Random random = new Random(0); ELEMENTS = new char[CONTAINER_SIZE]; for (int i = 0; i < CONTAINER_SIZE; i++) { ELEMENTS[i] = (char) random.nextInt(Character.MAX_VALUE); } EXPECTED_AGGREGATE = Iterator.ofAll(ELEMENTS).reduce((x, y) -> (char) JmhRunner.aggregate((int) x, (int) y)); javaPersistent = create(java.lang.String::new, ELEMENTS, ELEMENTS.length, v -> java.util.Arrays.equals(v.toCharArray(), ELEMENTS)); fjavaPersistent = create(fj.data.LazyString::str, javaPersistent, javaPersistent.length(), v -> Objects.equals(v.toStringEager(), javaPersistent)); vavrPersistent = create(io.vavr.collection.CharSeq::of, javaPersistent, javaPersistent.length(), v -> v.contentEquals(javaPersistent)); } } public static class Head extends Base { @Benchmark public Object java_persistent() { final Object head = javaPersistent.charAt(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object fjava_persistent() { final Object head = fjavaPersistent.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent() { final Object head = vavrPersistent.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } } @SuppressWarnings("Convert2MethodRef") public static class Tail extends Base { @Benchmark public Object java_persistent() { java.lang.String values = javaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.substring(1); } assert values.isEmpty(); return values; } @Benchmark public Object fjava_persistent() { fj.data.LazyString values = fjavaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } } public static class Get extends Base { @Benchmark public int java_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaPersistent.charAt(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (int i = 0; i < ELEMENTS.length; i++) { aggregate ^= fjavaPersistent.charAt(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= vavrPersistent.charAt(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } public static class Update extends Base { final char replacement = '❤'; @Benchmark public Object java_persistent() { java.lang.String values = javaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.substring(0, i) + replacement + values.substring(i + 1); } assert Array.ofAll(values.toCharArray()).forAll(c -> c == replacement); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.update(i, replacement); } assert values.forAll(c -> c == replacement); return values; } } public static class Repeat extends Base { final char value = '❤'; @Benchmark public Object vavr_persistent() { return CharSeq.of(value).repeat(CONTAINER_SIZE); } } public static class Prepend extends Base { @Benchmark public Object java_persistent() { java.lang.String values = ""; for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { values = ELEMENTS[i] + values; } assert Objects.equals(values, javaPersistent); return values; } @Benchmark public Object fjava_persistent() { fj.data.LazyString values = fj.data.LazyString.empty; for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { values = fj.data.LazyString.str(valueOf(ELEMENTS[i])).append(values); } assert Objects.equals(values.eval(), javaPersistent); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq values = io.vavr.collection.CharSeq.empty(); for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { values = values.prepend(ELEMENTS[i]); } assert values.contentEquals(vavrPersistent); return values; } } public static class Append extends Base { @Benchmark public Object java_persistent() { java.lang.String values = ""; for (char c : ELEMENTS) { values = values + c; } assert Objects.equals(values, javaPersistent); return values; } @Benchmark public Object fjava_persistent() { fj.data.LazyString values = fj.data.LazyString.empty; for (char c : ELEMENTS) { values = values.append(valueOf(c)); } assert areEqual(values.toStream(), vavrPersistent); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq values = io.vavr.collection.CharSeq.empty(); for (char c : ELEMENTS) { values = values.append(c); } assert values.contentEquals(vavrPersistent); return values; } } @SuppressWarnings("ForLoopReplaceableByForEach") public static class Iterate extends Base { @Benchmark public int java_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaPersistent.charAt(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = fjavaPersistent.toStream().iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/HashSetBenchmark.java000066400000000000000000000153361342074374400277200ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import static io.vavr.JmhRunner.create; import static io.vavr.JmhRunner.getRandomValues; import static scala.collection.JavaConverters.asScalaBuffer; public class HashSetBenchmark { static final Array> CLASSES = Array.of( Add.class, Iterate.class, Remove.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({ "10", "100", "1000", "2500" }) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; Integer[] ELEMENTS; Set SET; scala.collection.immutable.Set scalaPersistent; org.pcollections.PSet pcollectionsPersistent; io.usethesource.capsule.Set.Immutable capsulePersistent; io.vavr.collection.Set vavrPersistent; @Setup @SuppressWarnings("unchecked") public void setup() { ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); SET = TreeSet.of(ELEMENTS); EXPECTED_AGGREGATE = SET.reduce(JmhRunner::aggregate); scalaPersistent = create(v -> (scala.collection.immutable.Set) scala.collection.immutable.HashSet$.MODULE$.apply(asScalaBuffer(v)), SET.toJavaList(), SET.size(), v -> SET.forAll(v::contains)); pcollectionsPersistent = create(org.pcollections.HashTreePSet::from, SET.toJavaList(), SET.size(), v -> SET.forAll(v::contains)); capsulePersistent = create(io.usethesource.capsule.util.collection.AbstractSpecialisedImmutableSet::setOf, SET.toJavaSet(), SET.size(), v -> SET.forAll(v::contains)); vavrPersistent = create(io.vavr.collection.HashSet::ofAll, SET, SET.size(), v -> SET.forAll(v::contains)); } } public static class Add extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PSet values = org.pcollections.HashTreePSet.empty(); for (Integer element : ELEMENTS) { values = values.plus(element); } assert SET.forAll(values::contains); return values; } @Benchmark public Object scala_persistent() { scala.collection.immutable.HashSet values = new scala.collection.immutable.HashSet<>(); for (Integer element : ELEMENTS) { values = values.$plus(element); } assert SET.forAll(values::contains); return values; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Set.Immutable values = io.usethesource.capsule.core.PersistentTrieSet.of(); for (Integer element : ELEMENTS) { values = values.__insert(element); } assert SET.forAll(values::contains); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Set values = io.vavr.collection.HashSet.empty(); for (Integer element : ELEMENTS) { values = values.add(element); } assert SET.forAll(values::contains); return values; } } public static class Remove extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PSet values = pcollectionsPersistent; for (Integer element : ELEMENTS) { values = values.minus(element); } assert values.isEmpty(); return values; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Set.Immutable values = capsulePersistent; for (Integer element : ELEMENTS) { values = values.__remove(element); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Set values = vavrPersistent; for (Integer element : ELEMENTS) { values = values.remove(element); } assert values.isEmpty(); return values; } } @SuppressWarnings("ForLoopReplaceableByForEach") public static class Iterate extends Base { @Benchmark public int scala_persistent() { int aggregate = 0; for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int pcollections_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = pcollectionsPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int capsule_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = capsulePersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final io.vavr.collection.Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/IteratorBenchmark.java000066400000000000000000000074331342074374400301510ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Assert; import org.junit.Test; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import java.util.Random; import static io.vavr.JmhRunner.Includes.*; import static io.vavr.JmhRunner.getRandomValues; @SuppressWarnings({ "ALL", "unchecked", "rawtypes" }) public class IteratorBenchmark { static final Array> CLASSES = Array.of( Sliding.class, Concat.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runDebugWithAsserts(CLASSES); JmhRunner.runNormalNoAsserts(CLASSES, JAVA, SCALA, VAVR); } @State(Scope.Benchmark) public static class Base { @Param({"10", "100", "1000", "2500"}) public int CONTAINER_SIZE; Integer[] ELEMENTS; scala.collection.Iterator scalaIterator; io.vavr.collection.Iterator vavrIterator; @Setup public void setup() { final Random random = new Random(0); ELEMENTS = getRandomValues(CONTAINER_SIZE, false, random); scalaIterator = (scala.collection.Iterator) (Object) scala.collection.mutable.WrappedArray$.MODULE$.make(ELEMENTS).iterator(); vavrIterator = Iterator.of(ELEMENTS); } } public static class Sliding extends Base { @Benchmark public void scala_persistent(Blackhole bh) { final scala.collection.Iterator.GroupedIterator values = scalaIterator.sliding(3, 1); while (values.hasNext()) { bh.consume(values.next()); } } @Benchmark public void vavr_persistent(Blackhole bh) { final Iterator> values = vavrIterator.sliding(3); while (values.hasNext()) { bh.consume(values.next()); } } } @State(Scope.Benchmark) public static class Concat { @Param({ "10", "20" , "100", "1000" }) private int size; @Benchmark public void vavr_persistent(Blackhole bh) { Iterator iterator = Iterator.range(0, size) .foldLeft(Iterator.empty(), (result, __) -> result.concat(Iterator.of(1))); long sum = 0; while (iterator.hasNext()) { sum += iterator.next(); } Assert.assertEquals(size, sum); } @Benchmark public void scala_persistent(Blackhole bh) { final scala.collection.Iterator iterator = scala.collection.Iterator.range(0, size) .foldLeft((scala.collection.Iterator) (Object) scala.collection.Iterator.empty(), (result, i) -> result.$plus$plus(() -> scala.collection.Iterator.single(1))); long sum = 0; while (iterator.hasNext()) { sum += iterator.next(); } Assert.assertEquals(size, sum); } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/ListBenchmark.java000066400000000000000000000600431342074374400272670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import java.util.ArrayList; import java.util.Collection; import java.util.Objects; import java.util.stream.Collectors; import static java.util.Arrays.asList; import static io.vavr.JmhRunner.create; import static io.vavr.JmhRunner.getRandomValues; import static io.vavr.collection.Collections.areEqual; import static scala.collection.JavaConverters.asJavaCollection; import static scala.collection.JavaConverters.asScalaBuffer; public class ListBenchmark { static final Array> CLASSES = Array.of( Create.class, Head.class, Tail.class, Get.class, Update.class, Prepend.class, Append.class, GroupBy.class, Iterate.class , Fill.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({"10", "100", "1000", "2500"}) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; Integer[] ELEMENTS; /* Only use these for non-mutating operations */ java.util.ArrayList javaMutable; java.util.LinkedList javaMutableLinked; scala.collection.mutable.MutableList scalaMutable; fj.data.List fjavaPersistent; org.pcollections.PStack pcollectionsPersistent; scala.collection.immutable.List scalaPersistent; clojure.lang.IPersistentList clojurePersistent; io.vavr.collection.List vavrPersistent; @Setup @SuppressWarnings("unchecked") public void setup() { ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate); javaMutable = create(java.util.ArrayList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); javaMutableLinked = create(java.util.LinkedList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); scalaMutable = create(v -> (scala.collection.mutable.MutableList) scala.collection.mutable.MutableList$.MODULE$.apply(asScalaBuffer(v)), asList(ELEMENTS), v -> areEqual(asJavaCollection(v), javaMutable)); scalaPersistent = JmhRunner., scala.collection.immutable.List> create( v -> scala.collection.immutable.List$.MODULE$.apply(asScalaBuffer(v)), javaMutable, v -> areEqual(asJavaCollection(v), javaMutable) ); clojurePersistent = create(clojure.lang.PersistentList::create, javaMutable, v -> areEqual((Iterable) v, javaMutable)); fjavaPersistent = create(v -> fj.data.List.fromIterator(v.iterator()), javaMutable, v -> areEqual(v, javaMutable)); pcollectionsPersistent = create(org.pcollections.ConsPStack::from, javaMutable, v -> areEqual(v, javaMutable)); vavrPersistent = create(io.vavr.collection.List::ofAll, javaMutable, v -> areEqual(v, javaMutable)); } } public static class Create extends Base { @Benchmark public Object java_mutable() { final ArrayList values = new ArrayList<>(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object scala_persistent() { final scala.collection.immutable.List values = scala.collection.immutable.List$.MODULE$.apply(scalaMutable); assert Objects.equals(values, scalaPersistent); return values; } @Benchmark public Object clojure_persistent() { final clojure.lang.IPersistentStack values = clojure.lang.PersistentList.create(javaMutable); assert Objects.equals(values, clojurePersistent); return values; } @Benchmark public Object fjava_persistent() { final fj.data.List values = fj.data.List.fromIterator(javaMutable.iterator()); assert areEqual(values, javaMutable); return values; } @Benchmark public Object pcollections_persistent() { final org.pcollections.PStack values = org.pcollections.ConsPStack.from(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object vavr_persistent() { final io.vavr.collection.List values = io.vavr.collection.List.ofAll(javaMutable); assert areEqual(values, javaMutable); return values.head(); } } public static class Head extends Base { @Benchmark public Object java_mutable() { final Object head = javaMutable.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object scala_persistent() { final Object head = scalaPersistent.head(); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object clojure_persistent() { final Object head = clojurePersistent.peek(); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object fjava_persistent() { final Object head = fjavaPersistent.head(); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object pcollections_persistent() { final Object head = pcollectionsPersistent.get(0); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object vavr_persistent() { final Object head = vavrPersistent.head(); assert Objects.equals(head, javaMutable.get(0)); return head; } } @SuppressWarnings("Convert2MethodRef") public static class Tail extends Base { @State(Scope.Thread) public static class Initialized { final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); final java.util.LinkedList javaMutableLinked = new java.util.LinkedList<>(); @Setup(Level.Invocation) public void initializeMutable(Base state) { java.util.Collections.addAll(javaMutable, state.ELEMENTS); javaMutableLinked.addAll(javaMutable); assert areEqual(javaMutable, asList(state.ELEMENTS)) && areEqual(javaMutableLinked, javaMutable); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); javaMutableLinked.clear(); } } @Benchmark public Object java_mutable(Initialized state) { final java.util.ArrayList values = state.javaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values.remove(0); } assert values.isEmpty(); return values; } @Benchmark public Object java_linked_mutable(Initialized state) { final java.util.LinkedList values = state.javaMutableLinked; for (int i = 0; i < CONTAINER_SIZE; i++) { values.remove(0); } assert values.isEmpty(); return values; } @Benchmark @SuppressWarnings({ "unchecked", "RedundantCast" }) public Object scala_persistent() { scala.collection.immutable.List values = scalaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = (scala.collection.immutable.List) values.tail(); } assert values.isEmpty(); return values; } @Benchmark public Object clojure_persistent() { clojure.lang.IPersistentStack values = clojurePersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.pop(); } assert Objects.equals(values, clojure.lang.PersistentList.EMPTY); return values; } @Benchmark public Object fjava_persistent() { fj.data.List values = fjavaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PStack values = pcollectionsPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.minus(0); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.List values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } } public static class Get extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int java_linked_mutable() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaMutableLinked.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int scala_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= scalaPersistent.apply(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= fjavaPersistent.index(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int pcollections_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= pcollectionsPersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= vavrPersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } public static class Update extends Base { @State(Scope.Thread) public static class Initialized { final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); final java.util.LinkedList javaMutableLinked = new java.util.LinkedList<>(); final scala.collection.mutable.MutableList scalaMutable = new scala.collection.mutable.MutableList<>(); @Setup(Level.Invocation) public void initializeMutable(Base state) { java.util.Collections.addAll(javaMutable, state.ELEMENTS); java.util.Collections.addAll(javaMutableLinked, state.ELEMENTS); for (int i = state.CONTAINER_SIZE - 1; i >= 0; i--) { scalaMutable.prependElem(state.ELEMENTS[i]); } assert areEqual(javaMutable, asList(state.ELEMENTS)) && areEqual(javaMutableLinked, javaMutable) && areEqual(asJavaCollection(scalaMutable), javaMutable); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); javaMutableLinked.clear(); scalaMutable.clear(); } } @Benchmark public Object java_mutable(Initialized state) { final java.util.ArrayList values = state.javaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values.set(i, 0); } assert Array.ofAll(values).forAll(e -> e == 0); return values; } @Benchmark public Object java_linked_mutable(Initialized state) { final java.util.LinkedList values = state.javaMutableLinked; for (int i = 0; i < CONTAINER_SIZE; i++) { values.set(i, 0); } assert Array.ofAll(values).forAll(e -> e == 0); return values; } @Benchmark public Object scala_mutable(Initialized state) { final scala.collection.mutable.MutableList values = state.scalaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values.update(i, 0); } assert Array.ofAll(asJavaCollection(values)).forAll(e -> e == 0); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PStack values = pcollectionsPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.with(i, 0); } assert Array.ofAll(values).forAll(e -> e == 0); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.List values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.update(i, 0); } assert values.forAll(e -> e == 0); return values; } } @SuppressWarnings("ManualArrayToCollectionCopy") public static class Prepend extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(0, element); } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object java_linked_mutable() { final java.util.LinkedList values = new java.util.LinkedList<>(); for (Integer element : ELEMENTS) { values.addFirst(element); } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object scala_mutable() { final scala.collection.mutable.MutableList values = new scala.collection.mutable.MutableList<>(); for (Integer element : ELEMENTS) { values.prependElem(element); } assert areEqual(Array.ofAll(asJavaCollection(values)).reverse(), javaMutable); return values; } @Benchmark public Object scala_persistent() { scala.collection.immutable.List values = scala.collection.immutable.List$.MODULE$.empty(); for (Integer element : ELEMENTS) { values = values.$colon$colon(element); } assert areEqual(Array.ofAll(asJavaCollection(values)).reverse(), javaMutable); return values; } @Benchmark public Object fjava_persistent() { fj.data.List values = fj.data.List.list(); for (Integer element : ELEMENTS) { values = values.cons(element); } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PStack values = org.pcollections.ConsPStack.empty(); for (Integer element : ELEMENTS) { values = values.plus(element); } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.List values = io.vavr.collection.List.empty(); for (Integer element : ELEMENTS) { values = values.prepend(element); } assert areEqual(values.reverse(), javaMutable); return values; } } @SuppressWarnings("ManualArrayToCollectionCopy") public static class Append extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object java_linked_mutable() { final java.util.LinkedList values = new java.util.LinkedList<>(); for (Integer element : ELEMENTS) { values.addLast(element); } assert values.size() == CONTAINER_SIZE; return values; } @Benchmark public Object scala_mutable() { final scala.collection.mutable.MutableList values = new scala.collection.mutable.MutableList<>(); for (Integer element : ELEMENTS) { values.appendElem(element); } assert areEqual(asJavaCollection(values), javaMutable); return values; } @Benchmark public Object fjava_persistent() { fj.data.List values = fj.data.List.list(); for (Integer element : ELEMENTS) { values = values.snoc(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PStack values = org.pcollections.ConsPStack.empty(); for (Integer element : ELEMENTS) { values = values.plus(values.size(), element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.List values = io.vavr.collection.List.empty(); for (Integer element : ELEMENTS) { values = values.append(element); } assert areEqual(values, javaMutable); return values; } } public static class GroupBy extends Base { @Benchmark public Object java_mutable() { return javaMutable.stream().collect(Collectors.groupingBy(Integer::bitCount)); } @Benchmark public Object scala_persistent() { return scalaPersistent.groupBy(Integer::bitCount); } @Benchmark public Object fjava_persistent() { return fjavaPersistent.groupBy(Integer::bitCount); } @Benchmark public Object vavr_persistent() { return vavrPersistent.groupBy(Integer::bitCount); } } @SuppressWarnings("ForLoopReplaceableByForEach") public static class Iterate extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (final java.util.Iterator iterator = javaMutable.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int java_linked_mutable() { int aggregate = 0; for (final java.util.Iterator iterator = javaMutableLinked.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int scala_mutable() { int aggregate = 0; for (final scala.collection.Iterator iterator = scalaMutable.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int scala_persistent() { int aggregate = 0; for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = fjavaPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int pcollections_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = pcollectionsPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } public static class Fill extends Base { @Benchmark public Object scala_persistent() { final scala.collection.immutable.List values = scala.collection.immutable.List$.MODULE$.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); final Object head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent_constant_supplier() { final io.vavr.collection.List values = io.vavr.collection.List.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent_constant_object() { final io.vavr.collection.List values = io.vavr.collection.List.fill(CONTAINER_SIZE, ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/MapBenchmark.java000066400000000000000000000630651342074374400271000ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Function1; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import java.util.Arrays; import java.util.Random; import static io.vavr.JmhRunner.create; import static io.vavr.JmhRunner.getRandomValues; public class MapBenchmark { static final Array> CLASSES = Array.of( IterateKeys.class, VavrKeys.class, VavrValues.class, IterateValues.class, Get.class, Miss.class, PutOrdered.class, PutShuffled.class, ReplaceSingle.class, ReplaceAll.class, ReplaceAllOneByOne.class, Remove.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({"10", "100", "1000", "2500"}) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; Integer[] ELEMENTS; Integer[] KEYS; Integer[] REMOVAL; Map sampleTreeMap; // scala.collection.immutable.Map scalaPersistent; org.pcollections.PMap pcollectionsPersistent; io.usethesource.capsule.Map.Immutable capsulePersistent; Map vavrHash; Map vavrTreeMap; Map vavrLinkedHash; @Setup public void setup() { ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); sampleTreeMap = index(ELEMENTS); KEYS = predicableShuffle(sampleTreeMap.keySet().toJavaArray(Integer[]::new)); REMOVAL = predicableShuffle(KEYS.clone()); EXPECTED_AGGREGATE = sampleTreeMap.values().reduce(JmhRunner::aggregate); pcollectionsPersistent = create( org.pcollections.HashTreePMap::from, sampleTreeMap.toJavaMap(), sampleTreeMap.size(), v -> sampleTreeMap.forAll((e) -> v.get(e._1).equals(e._2))); capsulePersistent = create( io.usethesource.capsule.util.collection.AbstractSpecialisedImmutableMap::mapOf, sampleTreeMap.toJavaMap(), sampleTreeMap.size(), v -> sampleTreeMap.forAll((e) -> v.get(e._1).equals(e._2))); vavrTreeMap = doCreateMap(TreeMap::ofAll, sampleTreeMap); vavrHash = doCreateMap(HashMap::ofAll, sampleTreeMap); vavrLinkedHash = doCreateMap(LinkedHashMap::ofAll, sampleTreeMap); } private TreeMap index(Integer[] array) { java.util.Map javaMap = new java.util.HashMap<>(); for (int i = 0; i < array.length; i++) { javaMap.put(i, array[i]); } return TreeMap.ofAll(javaMap); } /** * Shuffle the array. Use a random number generator with a fixed seed. */ private Integer[] predicableShuffle(Integer[] array) { java.util.Collections.shuffle(Arrays.asList(array), new Random(42)); return array; } private > M doCreateMap(Function1, M> factory, M prototype) { return create(factory, prototype.toJavaMap(), prototype.size(), v -> prototype.forAll(v::contains)); } } @SuppressWarnings("Duplicates") public static class PutShuffled extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PMap values = org.pcollections.HashTreePMap.empty(); Integer[] elements = ELEMENTS; for (Integer key : KEYS) { values = values.plus(key, elements[key]); } org.pcollections.PMap result = values; assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); return result; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Map.Immutable values = io.usethesource.capsule.core.PersistentTrieMap.of(); Integer[] elements = ELEMENTS; for (Integer key : KEYS) { values = values.__put(key, elements[key]); } io.usethesource.capsule.Map.Immutable result = values; assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); return result; } @Benchmark public Object vavr_tree() { Map values = TreeMap.empty(); Integer[] elements = ELEMENTS; for (Integer key : KEYS) { values = values.put(key, elements[key]); } assert vavrTreeMap.forAll(values::contains); return values; } @Benchmark public Object vavr_hash() { Map values = HashMap.empty(); Integer[] elements = ELEMENTS; for (Integer key : KEYS) { values = values.put(key, elements[key]); } assert vavrTreeMap.forAll(values::contains); return values; } @Benchmark public Object vavr_linked_hash() { Map values = LinkedHashMap.empty(); Integer[] elements = ELEMENTS; for (Integer key : KEYS) { values = values.put(key, elements[key]); } assert vavrTreeMap.forAll(values::contains); return values; } } public static class PutOrdered extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PMap values = org.pcollections.HashTreePMap.empty(); Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.plus(i, elements[i]); } org.pcollections.PMap result = values; assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); return result; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Map.Immutable values = io.usethesource.capsule.core.PersistentTrieMap.of(); Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.__put(i, elements[i]); } io.usethesource.capsule.Map.Immutable result = values; assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); return result; } @Benchmark public Object vavr_tree() { Map values = TreeMap.empty(); Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.put(i, elements[i]); } assert vavrTreeMap.forAll(values::contains); return values; } @Benchmark public Object vavr_hash() { Map values = HashMap.empty(); Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.put(i, elements[i]); } assert vavrTreeMap.forAll(values::contains); return values; } @Benchmark public Object vavr_linked_hash() { Map values = LinkedHashMap.empty(); Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.put(i, elements[i]); } assert vavrTreeMap.forAll(values::contains); return values; } } public static class Get extends Base { @Benchmark public void pcollections_persistent(Blackhole bh) { org.pcollections.PMap values = pcollectionsPersistent; for (Integer key : KEYS) { bh.consume(values.get(key)); } } @Benchmark public void capsule_persistent(Blackhole bh) { io.usethesource.capsule.Map.Immutable values = capsulePersistent; for (Integer key : KEYS) { bh.consume(values.get(key)); } } @Benchmark public void vavr_tree(Blackhole bh) { Map values = vavrTreeMap; Integer dflt = 1; for (Integer key : KEYS) { bh.consume(values.getOrElse(key, dflt)); } } @Benchmark public void vavr_hash(Blackhole bh) { Map values = vavrHash; Integer dflt = 1; for (Integer key : KEYS) { bh.consume(values.getOrElse(key, dflt)); } } @Benchmark public void vavr_linked_hash(Blackhole bh) { Map values = vavrLinkedHash; Integer dflt = 1; for (Integer key : KEYS) { bh.consume(values.getOrElse(key, dflt)); } } } public static class Miss extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PMap values = pcollectionsPersistent; return values.get(-1); } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Map.Immutable values = capsulePersistent; return values.get(-1); } @Benchmark public Object vavr_tree() { Map values = vavrTreeMap; return values.get(-1); } @Benchmark public Object vavr_hash() { Map values = vavrHash; return values.get(-1); } @Benchmark public Object vavr_linked_hash() { Map values = vavrLinkedHash; return values.get(-1); } } public static class IterateKeys extends Base { @Benchmark public void pcollections_persistent(Blackhole bh) { org.pcollections.PMap values = pcollectionsPersistent; for (Integer integer : values.keySet()) { bh.consume(integer); } } @Benchmark public void capsule_persistent(Blackhole bh) { io.usethesource.capsule.Map.Immutable values = capsulePersistent; for (java.util.Iterator it = values.keyIterator(); it.hasNext(); ) { bh.consume(it.next()); } } @Benchmark public void vavr_tree(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.iterator((k, v) -> k)) { bh.consume(integer); } } @Benchmark public void vavr_tree_keys(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.keysIterator()) { bh.consume(integer); } } @Benchmark public void vavr_hash(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.iterator((k, v) -> k)) { bh.consume(integer); } } @Benchmark public void vavr_hash_keys(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.keysIterator()) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.iterator((k, v) -> k)) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash_keys(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.keysIterator()) { bh.consume(integer); } } } public static class VavrKeys extends Base { @Benchmark public void vavr_hash_keySet(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.keySet()) { bh.consume(integer); } } @Benchmark public void vavr_hash_iterator(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.iterator((k, v) -> k)) { bh.consume(integer); } } @Benchmark public void vavr_hash_keys(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.keysIterator()) { bh.consume(integer); } } @Benchmark public void vavr_tree_keySet(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.keySet()) { bh.consume(integer); } } @Benchmark public void vavr_tree_iterator(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.iterator((k, v) -> k)) { bh.consume(integer); } } @Benchmark public void vavr_tree_keys(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.keysIterator()) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash_keySet(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.keySet()) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash_iterator(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.iterator((k, v) -> k)) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash_keys(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.keysIterator()) { bh.consume(integer); } } } public static class VavrValues extends Base { @Benchmark public void vavr_hash_keySet(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.values()) { bh.consume(integer); } } @Benchmark public void vavr_hash_iterator(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.iterator((k, v) -> v)) { bh.consume(integer); } } @Benchmark public void vavr_hash_keys(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.valuesIterator()) { bh.consume(integer); } } @Benchmark public void vavr_tree_keySet(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.values()) { bh.consume(integer); } } @Benchmark public void vavr_tree_iterator(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.iterator((k, v) -> v)) { bh.consume(integer); } } @Benchmark public void vavr_tree_keys(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.valuesIterator()) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash_keySet(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.values()) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash_iterator(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.iterator((k, v) -> v)) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash_keys(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.valuesIterator()) { bh.consume(integer); } } } public static class IterateValues extends Base { @Benchmark public void pcollections_persistent(Blackhole bh) { org.pcollections.PMap values = pcollectionsPersistent; for (Integer integer : values.values()) { bh.consume(integer); } } @Benchmark public void capsule_persistent(Blackhole bh) { io.usethesource.capsule.Map.Immutable values = capsulePersistent; for (java.util.Iterator it = values.valueIterator(); it.hasNext(); ) { bh.consume(it.next()); } } @Benchmark public void vavr_tree(Blackhole bh) { Map values = vavrTreeMap; for (Integer integer : values.valuesIterator()) { bh.consume(integer); } } @Benchmark public void vavr_hash(Blackhole bh) { Map values = vavrHash; for (Integer integer : values.valuesIterator()) { bh.consume(integer); } } @Benchmark public void vavr_linked_hash(Blackhole bh) { Map values = vavrLinkedHash; for (Integer integer : values.valuesIterator()) { bh.consume(integer); } } } @SuppressWarnings("Duplicates") public static class Remove extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PMap values = pcollectionsPersistent; for (Integer removeMe : REMOVAL) { values = values.minus(removeMe); } assert values.isEmpty(); return values; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Map.Immutable values = capsulePersistent; for (Integer removeMe : REMOVAL) { values = values.__remove(removeMe); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_tree() { Map values = vavrTreeMap; for (Integer removeMe : REMOVAL) { values = values.remove(removeMe); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_hash() { Map values = vavrHash; for (Integer removeMe : REMOVAL) { values = values.remove(removeMe); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_linked_hash() { Map values = vavrLinkedHash; for (Integer removeMe : REMOVAL) { values = values.remove(removeMe); } assert values.isEmpty(); return values; } } @SuppressWarnings("Duplicates") public static class ReplaceSingle extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PMap values = pcollectionsPersistent; Integer key = REMOVAL[0]; Integer newValue = ELEMENTS[key] + 1; values = values.plus(key, newValue); return values; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Map.Immutable values = capsulePersistent; Integer key = REMOVAL[0]; Integer newValue = ELEMENTS[key] + 1; values = values.__put(key, newValue); return values; } @Benchmark public Object vavr_tree() { Map values = vavrTreeMap; Integer key = REMOVAL[0]; Integer newValue = ELEMENTS[key] + 1; values = values.put(key, newValue); return values; } @Benchmark public Object vavr_hash() { Map values = vavrHash; Integer key = REMOVAL[0]; Integer newValue = ELEMENTS[key] + 1; values = values.put(key, newValue); return values; } @Benchmark public Object vavr_linked_hash() { Map values = vavrLinkedHash; Integer key = REMOVAL[0]; Integer newValue = ELEMENTS[key] + 1; values = values.put(key, newValue); return values; } } @SuppressWarnings("CollectionAddedToSelf") public static class ReplaceAll extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PMap values = pcollectionsPersistent; values = values.plusAll(values); org.pcollections.PMap result = values; assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); return values; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Map.Immutable values = capsulePersistent; values = values.__putAll(values); io.usethesource.capsule.Map.Immutable result = values; assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); return values; } @Benchmark public Object vavr_tree() { Map values = vavrTreeMap; values = values.merge(values, (l, r) -> r); return values; } @Benchmark public Object vavr_hash() { Map values = vavrHash; values = values.merge(values, (l, r) -> r); return values; } @Benchmark public Object vavr_linked_hash() { Map values = vavrLinkedHash; values = values.merge(values, (l, r) -> r); return values; } } @SuppressWarnings("CollectionAddedToSelf") public static class ReplaceAllOneByOne extends Base { @Benchmark public Object pcollections_persistent() { org.pcollections.PMap values = pcollectionsPersistent; Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.plus(i, elements[i] + 1); } return values; } @Benchmark public Object capsule_persistent() { io.usethesource.capsule.Map.Immutable values = capsulePersistent; Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.__put(i, elements[i] + 1); } return values; } @Benchmark public Object vavr_tree() { Map values = vavrTreeMap; Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.put(i, elements[i] + 1); } return values; } @Benchmark public Object vavr_hash() { Map values = vavrHash; Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.put(i, elements[i] + 1); } return values; } @Benchmark public Object vavr_linked_hash() { Map values = vavrLinkedHash; Integer[] elements = ELEMENTS; for (int i = 0; i < elements.length; i++) { values = values.put(i, elements[i] + 1); } return values; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/PriorityQueueBenchmark.java000066400000000000000000000360511342074374400312040ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import fj.P; import io.vavr.JmhRunner; import io.vavr.Tuple2; import org.junit.Test; import org.openjdk.jmh.annotations.*; import scala.math.Ordering; import scala.math.Ordering$; import scalaz.Heap; import scalaz.Order; import scalaz.Order$; import java.util.Collections; import java.util.Objects; import static java.util.Arrays.asList; import static io.vavr.JmhRunner.create; import static io.vavr.JmhRunner.getRandomValues; import static scala.collection.JavaConverters.asScalaBuffer; @SuppressWarnings({ "UnnecessaryFullyQualifiedName", "UnnecessarilyQualifiedInnerClassAccess" }) public class PriorityQueueBenchmark { static final Array> CLASSES = Array.of( Enqueue.class, Dequeue.class, Sort.class , Fill.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runDebugWithAsserts(CLASSES); JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { static final Ordering SCALA_ORDERING = Ordering$.MODULE$.comparatorToOrdering(Integer::compareTo); static final Order SCALAZ_ORDER = Order$.MODULE$.fromScalaOrdering(SCALA_ORDERING); @Param({"10", "100", "1000", "2500"}) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; Integer[] ELEMENTS; scalaz.Heap scalazPersistent; io.vavr.collection.PriorityQueue vavrPersistent; fj.data.PriorityQueue fjava_persistent; @Setup public void setup() { ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate); scalazPersistent = create(v -> scalaz.Heap.Empty$.MODULE$. apply().insertAll(asScalaBuffer(v), SCALAZ_ORDER), asList(ELEMENTS), v -> v.size() == CONTAINER_SIZE); fjava_persistent = create(v -> fj.data.PriorityQueue. emptyInt().enqueue(v), List.of(ELEMENTS).map(v -> P.p(v, v)).toJavaList(), ELEMENTS.length, v -> v.toList().length() == CONTAINER_SIZE); vavrPersistent = create(io.vavr.collection.PriorityQueue::of, ELEMENTS, ELEMENTS.length, v -> v.size() == CONTAINER_SIZE); } } public static class Enqueue extends Base { @Benchmark @SuppressWarnings({ "Convert2streamapi", "ManualArrayToCollectionCopy" }) public Object java_mutable() { final java.util.PriorityQueue values = new java.util.PriorityQueue<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(element); } assert values.size() == CONTAINER_SIZE; return values; } @Benchmark @SuppressWarnings({ "Convert2streamapi", "ManualArrayToCollectionCopy" }) public Object java_blocking_mutable() { final java.util.concurrent.PriorityBlockingQueue values = new java.util.concurrent.PriorityBlockingQueue<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(element); } assert values.size() == CONTAINER_SIZE; return values; } @Benchmark public Object scala_mutable() { final scala.collection.mutable.PriorityQueue values = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING); for (Integer element : ELEMENTS) { values.$plus$eq(element); } assert values.size() == CONTAINER_SIZE; return values; } @Benchmark public Object scalaz_persistent() { scalaz.Heap values = scalaz.Heap.Empty$.MODULE$.apply(); for (Integer element : ELEMENTS) { values = values.insert(element, SCALAZ_ORDER); } assert values.size() == CONTAINER_SIZE; return values; } @Benchmark public Object fjava_persistent() { fj.data.PriorityQueue values = fj.data.PriorityQueue.emptyInt(); for (Integer element : ELEMENTS) { values = values.enqueue(element, element); } assert values.toList().length() == CONTAINER_SIZE; return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.empty(); for (Integer element : ELEMENTS) { values = values.enqueue(element); } assert values.size() == CONTAINER_SIZE; return values; } } @SuppressWarnings("Convert2MethodRef") public static class Dequeue extends Base { @State(Scope.Thread) public static class Initialized { java.util.PriorityQueue javaMutable = new java.util.PriorityQueue<>(); java.util.concurrent.PriorityBlockingQueue javaBlockingMutable = new java.util.concurrent.PriorityBlockingQueue<>(); scala.collection.mutable.PriorityQueue scalaMutable = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING); @Setup(Level.Invocation) public void initializeMutable(Base state) { Collections.addAll(javaMutable, state.ELEMENTS); Collections.addAll(javaBlockingMutable, state.ELEMENTS); for (Integer element : state.ELEMENTS) { scalaMutable.$plus$eq(element); } assert (javaMutable.size() == state.CONTAINER_SIZE) && (javaBlockingMutable.size() == state.CONTAINER_SIZE) && (scalaMutable.size() == state.CONTAINER_SIZE); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); javaBlockingMutable.clear(); scalaMutable.clear(); } } @Benchmark public Object java_mutable(Initialized state) { final java.util.PriorityQueue values = state.javaMutable; int aggregate = 0; for (; !values.isEmpty(); values.poll()) { aggregate ^= values.peek(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object java_blocking_mutable(Initialized state) { final java.util.concurrent.PriorityBlockingQueue values = state.javaBlockingMutable; int aggregate = 0; for (; !values.isEmpty(); values.poll()) { aggregate ^= values.peek(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object scala_mutable(Initialized state) { final scala.collection.mutable.PriorityQueue values = state.scalaMutable; int aggregate = 0; while (!values.isEmpty()) { aggregate ^= values.dequeue(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object scalaz_persistent() { scalaz.Heap values = scalazPersistent; int aggregate = 0; while (!values.isEmpty()) { final scala.Tuple2> uncons = values.uncons().get(); aggregate ^= uncons._1; values = uncons._2; } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object fjava_persistent() { fj.data.PriorityQueue values = fjava_persistent; int aggregate = 0; while (!values.isEmpty()) { aggregate ^= values.top().some()._1(); values = values.dequeue(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.PriorityQueue values = vavrPersistent; int aggregate = 0; while (!values.isEmpty()) { final Tuple2> dequeue = values.dequeue(); aggregate ^= dequeue._1; values = dequeue._2; } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } } @SuppressWarnings("Convert2MethodRef") public static class Sort extends Base { @Benchmark @SuppressWarnings("ManualArrayToCollectionCopy") public Object java_mutable() { final java.util.PriorityQueue values = new java.util.PriorityQueue<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(element); } assert values.size() == CONTAINER_SIZE; int aggregate = 0; for (; !values.isEmpty(); values.poll()) { aggregate ^= values.peek(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark @SuppressWarnings("ManualArrayToCollectionCopy") public Object java_blocking_mutable() { final java.util.concurrent.PriorityBlockingQueue values = new java.util.concurrent.PriorityBlockingQueue<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(element); } assert values.size() == CONTAINER_SIZE; int aggregate = 0; for (; !values.isEmpty(); values.poll()) { aggregate ^= values.peek(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark @SuppressWarnings("ManualArrayToCollectionCopy") public Object java_treeset_mutable() { io.vavr.collection.TreeMap> values = io.vavr.collection.TreeMap.empty(); for (Integer element : ELEMENTS) { final io.vavr.collection.List vs = values.get(element).getOrElse(io.vavr.collection.List.empty()).prepend(element); values = values.put(element, vs); } assert values.values().map(Traversable::size).sum().intValue() == CONTAINER_SIZE; int aggregate = 0; while (!values.isEmpty()) { final Tuple2> min = values.head(); for (Integer integer : min._2) { aggregate ^= integer; } values = values.remove(min._1); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object scala_mutable() { scala.collection.mutable.PriorityQueue values = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING); for (Integer element : ELEMENTS) { values = values.$plus$eq(element); } assert values.size() == CONTAINER_SIZE; int aggregate = 0; while (!values.isEmpty()) { aggregate ^= values.dequeue(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object scalaz_persistent() { scalaz.Heap values = scalaz.Heap.Empty$.MODULE$.apply(); for (Integer element : ELEMENTS) { values = values.insert(element, SCALAZ_ORDER); } assert values.size() == CONTAINER_SIZE; int aggregate = 0; while (!values.isEmpty()) { final scala.Tuple2> uncons = values.uncons().get(); aggregate ^= uncons._1; values = uncons._2; } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object fjava_persistent() { fj.data.PriorityQueue values = fj.data.PriorityQueue.emptyInt(); for (Integer element : ELEMENTS) { values = values.enqueue(element, element); } assert values.toList().length() == CONTAINER_SIZE; int aggregate = 0; while (!values.isEmpty()) { aggregate ^= values.top().some()._1(); values = values.dequeue(); } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.of(ELEMENTS); assert values.size() == CONTAINER_SIZE; int aggregate = 0; while (!values.isEmpty()) { final Tuple2> dequeue = values.dequeue(); aggregate ^= dequeue._1; values = dequeue._2; } assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); return values; } } public static class Fill extends Base { @Benchmark public Object vavr_persistent_constant_supplier() { final io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent_constant_object() { final io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.fill(CONTAINER_SIZE, ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/collection/VectorBenchmark.java000066400000000000000000001205141342074374400276160ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import scala.collection.generic.CanBuildFrom; import scala.math.Ordering; import scala.math.Ordering$; import java.util.Comparator; import java.util.Objects; import java.util.Random; import static java.util.Arrays.asList; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; import static io.vavr.JmhRunner.Includes.*; import static io.vavr.JmhRunner.*; import static io.vavr.collection.Collections.areEqual; import static io.vavr.collection.Vector.collector; import static scala.collection.JavaConverters.asJavaCollection; import static scala.collection.JavaConverters.asScalaBuffer; @SuppressWarnings({ "ALL", "unchecked", "rawtypes" }) public class VectorBenchmark { static final Array> CLASSES = Array.of( Create.class, Head.class, Tail.class, Get.class, Update.class, Map.class, Filter.class, Prepend.class, PrependAll.class, Append.class, AppendAll.class, Insert.class, GroupBy.class, Slice.class, Sort.class, Iterate.class , Fill.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runDebugWithAsserts(CLASSES); JmhRunner.runNormalNoAsserts(CLASSES, JAVA, FUNCTIONAL_JAVA, PCOLLECTIONS, ECOLLECTIONS, CLOJURE, SCALA, VAVR); } @State(Scope.Benchmark) public static class Base { @Param({"10", "100", "1000", "1026", "2500"}) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; Integer[] ELEMENTS; int[] INT_ELEMENTS; int[] RANDOMIZED_INDICES; /* Only use this for non-mutating operations */ java.util.ArrayList javaMutable; fj.data.Seq fjavaPersistent; org.pcollections.PVector pCollectionsPersistent; org.eclipse.collections.api.list.ImmutableList eCollectionsPersistent; clojure.lang.PersistentVector clojurePersistent; scala.collection.immutable.Vector scalaPersistent; io.vavr.collection.Vector vavrPersistent; io.vavr.collection.Vector vavrPersistentInt; io.vavr.collection.Vector vavrPersistentByte; @Setup public void setup() { final Random random = new Random(0); ELEMENTS = getRandomValues(CONTAINER_SIZE, false, random); INT_ELEMENTS = ArrayType.asPrimitives(int.class, Array.of(ELEMENTS)); RANDOMIZED_INDICES = shuffle(Array.range(0, CONTAINER_SIZE).toJavaStream().mapToInt(Integer::intValue).toArray(), random); EXPECTED_AGGREGATE = Array.of(ELEMENTS).reduce(JmhRunner::aggregate); javaMutable = create(java.util.ArrayList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); fjavaPersistent = create(fj.data.Seq::fromJavaList, javaMutable, v -> areEqual(v, javaMutable)); pCollectionsPersistent = create(org.pcollections.TreePVector::from, javaMutable, v -> areEqual(v, javaMutable)); eCollectionsPersistent = create(org.eclipse.collections.impl.factory.Lists.immutable::ofAll, javaMutable, v -> areEqual(v, javaMutable)); clojurePersistent = create(clojure.lang.PersistentVector::create, javaMutable, v -> areEqual(v, javaMutable)); scalaPersistent = create(v -> (scala.collection.immutable.Vector) scala.collection.immutable.Vector$.MODULE$.apply(asScalaBuffer(v)), javaMutable, v -> areEqual(asJavaCollection(v), javaMutable)); vavrPersistent = create(io.vavr.collection.Vector::ofAll, javaMutable, v -> areEqual(v, javaMutable)); vavrPersistentInt = create(v -> io.vavr.collection.Vector.ofAll(INT_ELEMENTS), javaMutable, v -> areEqual(v, javaMutable) && (v.trie.type.type() == int.class)); final byte[] BYTE_ELEMENTS = new byte[CONTAINER_SIZE]; random.nextBytes(BYTE_ELEMENTS); vavrPersistentByte = create(v -> io.vavr.collection.Vector.ofAll(BYTE_ELEMENTS), javaMutable, v -> areEqual(v, Array.ofAll(BYTE_ELEMENTS)) && (v.trie.type.type() == byte.class)); } } /** Bulk creation from array based, boxed source */ public static class Create extends Base { @Benchmark public Object java_mutable() { final java.util.List values = new java.util.ArrayList<>(java.util.Arrays.asList(ELEMENTS)); assert areEqual(values, javaMutable); return values; } @Benchmark public Object java_mutable_boxed() { final java.util.List values = new java.util.ArrayList<>(); for (int i = 0; i < CONTAINER_SIZE; i++) { values.add(INT_ELEMENTS[i]); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object java_mutable_boxed_stream() { final java.util.List values = java.util.Arrays.stream(INT_ELEMENTS).boxed().collect(toList()); assert areEqual(values, javaMutable); return values; } @Benchmark public Object fjava_persistent() { final fj.data.Seq values = fj.data.Seq.fromJavaList(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object pcollections_persistent() { final org.pcollections.PVector values = org.pcollections.TreePVector.from(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object ecollections_persistent() { final org.eclipse.collections.api.list.ImmutableList values = org.eclipse.collections.impl.factory.Lists.immutable.ofAll(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object clojure_persistent() { final clojure.lang.PersistentVector values = clojure.lang.PersistentVector.create(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object scala_persistent() { final scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.apply(scalaPersistent); assert Objects.equals(values, scalaPersistent); return values; } @Benchmark public Object vavr_persistent() { final io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object vavr_persistent_int() { final io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(INT_ELEMENTS); assert (values.trie.type.type() == int.class) && areEqual(values, javaMutable); return values; } } public static class Head extends Base { @Benchmark public Object java_mutable() { final Object head = javaMutable.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object fjava_persistent() { final Object head = fjavaPersistent.head(); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object pcollections_persistent() { final Object head = pCollectionsPersistent.get(0); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object ecollections_persistent() { final Object head = eCollectionsPersistent.getFirst(); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object clojure_persistent() { final Object head = clojurePersistent.nth(0); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object scala_persistent() { final Object head = scalaPersistent.head(); assert Objects.equals(head, javaMutable.get(0)); return head; } @Benchmark public Object vavr_persistent() { final Object head = vavrPersistent.head(); assert Objects.equals(head, javaMutable.get(0)); return head; } } public static class Tail extends Base { @State(Scope.Thread) public static class Initialized { final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); @Setup(Level.Invocation) public void initializeMutable(Base state) { java.util.Collections.addAll(javaMutable, state.ELEMENTS); assert areEqual(javaMutable, asList(state.ELEMENTS)); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); } } @Benchmark public Object java_mutable(Initialized state) { java.util.List values = state.javaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.subList(1, values.size()); /* remove(0) would copy everything, but this will slow access down because of nesting */ } assert values.isEmpty(); return values; } @Benchmark public Object fjava_persistent() { fj.data.Seq values = fjavaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PVector values = pCollectionsPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.minus(0); } assert values.isEmpty(); return values; } @Benchmark public Object ecollections_persistent() { org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.drop(1); } assert values.isEmpty() && (values != eCollectionsPersistent); return values; } @Benchmark public void clojure_persistent(Blackhole bh) { /* stores the whole collection underneath */ java.util.List values = clojurePersistent; while (!values.isEmpty()) { values = values.subList(1, values.size()); bh.consume(values); } } @Benchmark public Object scala_persistent() { scala.collection.immutable.Vector values = scalaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert ((scala.collection.immutable.Seq) values).isEmpty(); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Vector values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_persistent_int() { io.vavr.collection.Vector values = vavrPersistentInt; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } } /** Aggregated, randomized access to every element */ public static class Get extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (int i : RANDOMIZED_INDICES) { aggregate ^= javaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (int i : RANDOMIZED_INDICES) { aggregate ^= fjavaPersistent.index(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int pcollections_persistent() { int aggregate = 0; for (int i : RANDOMIZED_INDICES) { aggregate ^= pCollectionsPersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int ecollections_persistent() { int aggregate = 0; for (int i : RANDOMIZED_INDICES) { aggregate ^= eCollectionsPersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int clojure_persistent() { int aggregate = 0; for (int i : RANDOMIZED_INDICES) { aggregate ^= (int) clojurePersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int scala_persistent() { int aggregate = 0; for (int i : RANDOMIZED_INDICES) { aggregate ^= scalaPersistent.apply(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (int i : RANDOMIZED_INDICES) { aggregate ^= vavrPersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } /** Randomized update of every element */ public static class Update extends Base { @State(Scope.Thread) public static class Initialized { final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); @Setup(Level.Invocation) public void initializeMutable(Base state) { java.util.Collections.addAll(javaMutable, state.ELEMENTS); assert areEqual(javaMutable, asList(state.ELEMENTS)); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); } } @Benchmark public Object java_mutable(Initialized state) { final java.util.ArrayList values = state.javaMutable; for (int i : RANDOMIZED_INDICES) { values.set(i, 0); } assert Array.ofAll(values).forAll(e -> e == 0); return values; } @Benchmark public Object fjava_persistent() { fj.data.Seq values = fjavaPersistent; for (int i : RANDOMIZED_INDICES) { values = values.update(i, 0); } assert Array.ofAll(values).forAll(e -> e == 0); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PVector values = pCollectionsPersistent; for (int i : RANDOMIZED_INDICES) { values = values.with(i, 0); } assert Array.ofAll(values).forAll(e -> e == 0); return values; } @Benchmark public Object ecollections_persistent() { org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent; for (int i : RANDOMIZED_INDICES) { final org.eclipse.collections.api.list.MutableList copy = values.toList(); copy.set(i, 0); values = copy.toImmutable(); } assert Array.ofAll(values).forAll(e -> e == 0) && (values != eCollectionsPersistent); return values; } @Benchmark public Object clojure_persistent() { clojure.lang.PersistentVector values = clojurePersistent; for (int i : RANDOMIZED_INDICES) { values = values.assocN(i, 0); } assert Array.of(values.toArray()).forAll(e -> Objects.equals(e, 0)); return values; } @Benchmark public Object scala_persistent() { scala.collection.immutable.Vector values = scalaPersistent; for (int i : RANDOMIZED_INDICES) { values = values.updateAt(i, 0); } assert Array.ofAll(asJavaCollection(values)).forAll(e -> e == 0); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Vector values = vavrPersistent; for (int i : RANDOMIZED_INDICES) { values = values.update(i, 0); } assert values.forAll(e -> e == 0); return values; } @Benchmark public Object vavr_persistent_int() { io.vavr.collection.Vector values = vavrPersistentInt; for (int i : RANDOMIZED_INDICES) { values = values.update(i, 0); } assert (values.trie.type.type() == int.class) && values.forAll(e -> e == 0); return values; } } public static class Map extends Base { final CanBuildFrom canBuildFrom = scala.collection.immutable.Vector.canBuildFrom(); private static int mapper(int i) { return i + 1; } @Benchmark public Object java_mutable_loop() { final Integer[] values = ELEMENTS.clone(); for (int i = 0; i < CONTAINER_SIZE; i++) { values[i] = mapper(values[i]); } assert areEqual(Array.of(values), Array.of(ELEMENTS).map(Map::mapper)); return values; } @Benchmark public Object java_mutable() { final java.util.List values = javaMutable.stream().map(Map::mapper).collect(toList()); assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); return values; } @Benchmark public Object ecollections_persistent() { final org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent.collect(Map::mapper); assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); return values; } @Benchmark public Object scala_persistent() { final scala.collection.immutable.Vector values = (scala.collection.immutable.Vector) scalaPersistent.map(Map::mapper, canBuildFrom); assert areEqual(asJavaCollection(values), Array.of(ELEMENTS).map(Map::mapper)); return values; } @Benchmark public Object vavr_persistent() { final io.vavr.collection.Vector values = vavrPersistent.map(Map::mapper); assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); return values; } @Benchmark public Object vavr_persistent_int() { final io.vavr.collection.Vector values = vavrPersistentInt.map(Map::mapper); assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); return values; } } public static class Filter extends Base { private static boolean isOdd(int i) { return (i & 1) == 1; } @Benchmark public Object java_mutable() { final java.util.List someValues = javaMutable.stream().filter(Filter::isOdd).collect(toList()); assert areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); return someValues; } @Benchmark public Object ecollections_persistent() { final org.eclipse.collections.api.list.ImmutableList someValues = eCollectionsPersistent.select(Filter::isOdd); assert areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); return someValues; } @Benchmark public Object scala_persistent() { final scala.collection.immutable.Vector someValues = (scala.collection.immutable.Vector) ((scala.collection.Traversable) scalaPersistent).filter(Filter::isOdd); assert areEqual(asJavaCollection(someValues), Array.of(ELEMENTS).filter(Filter::isOdd)); return someValues; } @Benchmark public Object vavr_persistent() { final io.vavr.collection.Vector someValues = vavrPersistent.filter(Filter::isOdd); assert areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); return someValues; } @Benchmark public Object vavr_persistent_int() { final io.vavr.collection.Vector someValues = vavrPersistentInt.filter(Filter::isOdd); assert (someValues.trie.type.type() == int.class) && areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); return someValues; } } public static class Prepend extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList values = new java.util.ArrayList<>(); /* no initial value, as we're simulating dynamic usage */ for (Integer element : ELEMENTS) { values.add(0, element); } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object fjava_persistent() { fj.data.Seq values = fj.data.Seq.empty(); for (Integer element : ELEMENTS) { values = values.cons(element); } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PVector values = org.pcollections.TreePVector.empty(); for (Integer element : ELEMENTS) { values = values.plus(0, element); } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object ecollections_persistent() { org.eclipse.collections.api.list.ImmutableList values = org.eclipse.collections.impl.factory.Lists.immutable.empty(); for (Integer element : ELEMENTS) { final org.eclipse.collections.api.list.MutableList copy = values.toList(); copy.add(0, element); values = copy.toImmutable(); } assert areEqual(values.toReversed(), javaMutable) && (values != eCollectionsPersistent); return values; } @Benchmark public Object clojure_persistent() { clojure.lang.PersistentVector values = clojure.lang.PersistentVector.EMPTY; for (int i = 0; i < ELEMENTS.length; i++) { clojure.lang.PersistentVector prepended = clojure.lang.PersistentVector.create(ELEMENTS[i]); for (Object value : values) { prepended = prepended.cons(value); /* rebuild everything via append */ } values = prepended; } assert areEqual(Array.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object scala_persistent() { scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.empty(); for (Integer element : ELEMENTS) { values = values.appendFront(element); } assert areEqual(Array.ofAll(asJavaCollection(values)).reverse(), javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Vector values = io.vavr.collection.Vector.empty(); for (Integer element : ELEMENTS) { values = values.prepend(element); } assert areEqual(values.reverse(), javaMutable); return values; } @Benchmark public Object vavr_persistent_int() { io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(ELEMENTS[0]); for (int i = 1; i < ELEMENTS.length; i++) { values = values.prepend(ELEMENTS[i]); } assert (values.trie.type.type() == int.class) && areEqual(values.reverse(), javaMutable); return values; } } public static class PrependAll extends Base { final CanBuildFrom canBuildFrom = scala.collection.immutable.Vector.canBuildFrom(); @Benchmark public void scala_persistent(Blackhole bh) { for (int i = 0; i < CONTAINER_SIZE; i++) { final java.util.List front = javaMutable.subList(0, i); final scala.collection.immutable.Vector back = scalaPersistent.slice(i, CONTAINER_SIZE); scala.collection.immutable.Vector values = back; for (int j = front.size() - 1; j >= 0; j--) { values = values.appendFront(front.get(j)); } assert areEqual(asJavaCollection(values), javaMutable); bh.consume(values); } } @Benchmark public void vavr_persistent(Blackhole bh) { for (int i = 0; i < CONTAINER_SIZE; i++) { final java.util.List front = javaMutable.subList(0, i); final io.vavr.collection.Vector back = vavrPersistent.slice(i, CONTAINER_SIZE); final io.vavr.collection.Vector values = back.prependAll(front); assert areEqual(values, javaMutable); bh.consume(values); } } } /** Add all elements (one-by-one, as we're not testing bulk operations) */ public static class Append extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList values = new java.util.ArrayList<>(); /* no initial value as we're simulating dynamic usage */ for (Integer element : ELEMENTS) { values.add(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object fjava_persistent() { fj.data.Seq values = fj.data.Seq.empty(); for (Integer element : ELEMENTS) { values = values.snoc(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object ecollections_persistent() { org.eclipse.collections.api.list.ImmutableList values = org.eclipse.collections.impl.factory.Lists.immutable.empty(); for (Integer element : ELEMENTS) { final org.eclipse.collections.api.list.MutableList copy = values.toList(); copy.add(element); values = copy.toImmutable(); } assert areEqual(values, javaMutable) && (values != eCollectionsPersistent); return values; } @Benchmark public Object pcollections_persistent() { org.pcollections.PVector values = org.pcollections.TreePVector.empty(); for (Integer element : ELEMENTS) { values = values.plus(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object clojure_persistent() { clojure.lang.PersistentVector values = clojure.lang.PersistentVector.EMPTY; for (Integer element : ELEMENTS) { values = values.cons(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object scala_persistent() { scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.empty(); for (Integer element : ELEMENTS) { values = values.appendBack(element); } assert areEqual(asJavaCollection(values), javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Vector values = io.vavr.collection.Vector.empty(); for (Integer element : ELEMENTS) { values = values.append(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object vavr_persistent_int() { io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(INT_ELEMENTS[0]); for (int i = 1; i < INT_ELEMENTS.length; i++) { values = values.append(INT_ELEMENTS[i]); } assert (values.trie.type.type() == int.class) && areEqual(values, javaMutable); return values; } } public static class AppendAll extends Base { final CanBuildFrom canBuildFrom = scala.collection.immutable.Vector.canBuildFrom(); @Benchmark public void scala_persistent(Blackhole bh) { for (int i = 0; i < CONTAINER_SIZE; i++) { final scala.collection.immutable.Vector front = scalaPersistent.slice(0, i); final java.util.List back = javaMutable.subList(i, CONTAINER_SIZE); final scala.collection.immutable.Vector values = front.$plus$plus(asScalaBuffer(back), (CanBuildFrom, Integer, scala.collection.immutable.Vector>) canBuildFrom); assert areEqual(asJavaCollection(values), javaMutable); bh.consume(values); } } @Benchmark public void vavr_persistent(Blackhole bh) { for (int i = 0; i < CONTAINER_SIZE; i++) { final io.vavr.collection.Vector front = vavrPersistent.slice(0, i); final java.util.List back = javaMutable.subList(i, CONTAINER_SIZE); final io.vavr.collection.Vector values = front.appendAll(back); assert areEqual(values, javaMutable); bh.consume(values); } } } public static class Insert extends Base { @Benchmark public void vavr_persistent(Blackhole bh) { for (int i = 0; i < CONTAINER_SIZE; i++) { final Vector values = vavrPersistent.insert(i, 0); assert values.size() == CONTAINER_SIZE + 1; bh.consume(values); } } } public static class GroupBy extends Base { @Benchmark public Object java_mutable() { return javaMutable.stream().collect(groupingBy(Integer::bitCount)); } @Benchmark public Object scala_persistent() { return scalaPersistent.groupBy(Integer::bitCount); } @Benchmark public Object vavr_persistent() { return vavrPersistent.groupBy(Integer::bitCount); } } /** Consume the vector one-by-one, from the front and back */ public static class Slice extends Base { @Benchmark public void java_mutable(Blackhole bh) { /* stores the whole collection underneath */ java.util.List values = javaMutable; while (!values.isEmpty()) { values = values.subList(1, values.size()); values = values.subList(0, values.size() - 1); bh.consume(values); } } @Benchmark public void pcollections_persistent(Blackhole bh) { org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent; for (int i = 1; !values.isEmpty(); i++) { values = values.subList(1, values.size()); values = values.subList(0, values.size() - 1); bh.consume(values); } } @Benchmark public void clojure_persistent(Blackhole bh) { /* stores the whole collection underneath */ java.util.List values = clojurePersistent; while (!values.isEmpty()) { values = values.subList(1, values.size()); values = values.subList(0, values.size() - 1); bh.consume(values); } } @Benchmark public void scala_persistent(Blackhole bh) { scala.collection.immutable.Vector values = scalaPersistent; while (!values.isEmpty()) { values = values.slice(1, values.size()); values = values.slice(0, values.size() - 1); bh.consume(values); } } @Benchmark public void vavr_persistent(Blackhole bh) { io.vavr.collection.Vector values = vavrPersistent; for (int i = 1; !values.isEmpty(); i++) { values = values.slice(1, values.size()); values = values.slice(0, values.size() - 1); bh.consume(values); } } @Benchmark public void vavr_persistent_int(Blackhole bh) { io.vavr.collection.Vector values = this.vavrPersistentInt; while (!values.isEmpty()) { values = values.slice(1, values.size()); values = values.slice(0, values.size() - 1); bh.consume(values); } } } public static class Sort extends Base { static final Ordering SCALA_ORDERING = Ordering$.MODULE$.comparatorToOrdering(Integer::compareTo); @State(Scope.Thread) public static class Initialized { final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); @Setup(Level.Invocation) public void initializeMutable(Base state) { java.util.Collections.addAll(javaMutable, state.ELEMENTS); assert areEqual(javaMutable, asList(state.ELEMENTS)); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); } } @Benchmark public Object java_mutable(Initialized state) { state.javaMutable.sort(Comparator.naturalOrder()); assert areEqual(state.javaMutable, vavrPersistent.sorted()); return state.javaMutable; } @Benchmark public Object scala_persistent() { final scala.collection.Seq results = ((scala.collection.Seq) scalaPersistent).sorted(SCALA_ORDERING); assert areEqual(asJavaCollection(results), vavrPersistent.sorted()); return results; } @Benchmark public Object vavr_persistent() { final Vector results = vavrPersistent.sorted(); assert areEqual(results, vavrPersistent.toJavaStream().sorted().collect(collector())); return results; } } /** Sequential access for all elements */ public static class Iterate extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (final java.util.Iterator iterator = javaMutable.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = fjavaPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int ecollections_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = eCollectionsPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int pcollections_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = pCollectionsPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int clojure_persistent() { int aggregate = 0; for (final java.util.Iterator iterator = clojurePersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int scala_persistent() { int aggregate = 0; for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent_int() { final int[] aggregate = { 0 }; vavrPersistentInt.trie. visit((ordinal, leaf, start, end) -> { for (int i = start; i < end; i++) { aggregate[0] ^= leaf[i]; } return -1; }); assert aggregate[0] == EXPECTED_AGGREGATE; return aggregate[0]; } } public static class Fill extends Base { @Benchmark public Object scala_persistent() { final scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); final Object head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent_constant_supplier() { final io.vavr.collection.Vector values = io.vavr.collection.Vector.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent_constant_object() { final io.vavr.collection.Vector values = io.vavr.collection.Vector.fill(CONTAINER_SIZE, ELEMENTS[0]); final Integer head = values.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/control/000077500000000000000000000000001342074374400232205ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/control/LazyBenchmark.java000066400000000000000000000066111342074374400266210ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.control; import io.vavr.JmhRunner; import io.vavr.Lazy; import io.vavr.collection.Array; import io.vavr.collection.Iterator; import org.junit.Test; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import static io.vavr.API.Array; import static io.vavr.JmhRunner.Includes.JAVA; import static io.vavr.JmhRunner.Includes.VAVR; public class LazyBenchmark { static final Array> CLASSES = Array( Get.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runDebugWithAsserts(CLASSES, JAVA, VAVR); JmhRunner.runSlowNoAsserts(CLASSES, JAVA, VAVR); } @State(Scope.Benchmark) public static class Base { final int SIZE = 10; Integer[] EAGERS; io.vavr.Lazy[] INITED_LAZIES; @Setup @SuppressWarnings({ "unchecked", "rawtypes" }) public void setup() { EAGERS = Iterator.range(0, SIZE).toJavaArray(Integer[]::new); INITED_LAZIES = Iterator.of(EAGERS).map(i -> { final Lazy lazy = Lazy.of(() -> i); lazy.get(); return lazy; }).toJavaList().toArray(new Lazy[0]); } } @Threads(4) @SuppressWarnings({ "WeakerAccess", "rawtypes" }) public static class Get extends Base { @State(Scope.Thread) public static class Initialized { io.vavr.Lazy[] LAZIES; @Setup(Level.Invocation) @SuppressWarnings("unchecked") public void initializeMutable(Base state) { LAZIES = Iterator.of(state.EAGERS).map(i -> Lazy.of(() -> i)).toJavaList().toArray(new Lazy[0]); } } @Benchmark public void java_eager(Blackhole bh) { int size = SIZE; Integer[] eagers = EAGERS; for (int i = 0; i < size; i++) { bh.consume(eagers[i]); } } @Benchmark public void vavr_inited_lazy(Blackhole bh) { int size = SIZE; Lazy[] initedLazies = INITED_LAZIES; for (int i = 0; i < size; i++) { assert initedLazies[i].isEvaluated(); bh.consume(initedLazies[i].get()); } } @Benchmark public void vavr_lazy(Initialized state, Blackhole bh) { int size = SIZE; Lazy[] lazies = state.LAZIES; for (int i = 0; i < size; i++) { assert !lazies[i].isEvaluated(); bh.consume(lazies[i].get()); } } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/idiom/000077500000000000000000000000001342074374400226415ustar00rootroot00000000000000vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/idiom/ForBenchmark.java000066400000000000000000000057051342074374400260540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.idiom; import io.vavr.JmhRunner; import io.vavr.collection.Array; import org.junit.Test; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; import static java.util.stream.Collectors.toList; import static io.vavr.API.*; import static io.vavr.JmhRunner.getRandomValues; /** * Benchmark for nested loops vs Vavr's For().yield comprehensions. * * @see For2 */ public class ForBenchmark { static final Array> CLASSES = Array( For.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { int CONTAINER_SIZE = 1000; int AGGREGATE; io.vavr.collection.List ELEMENTS; final BiFunction AGGREGATOR = (i, j) -> i ^ j; @Setup public void setup() { ELEMENTS = io.vavr.collection.List.ofAll(Arrays.stream(getRandomValues(CONTAINER_SIZE, 0, true))); AGGREGATE = 0; for (Integer i : ELEMENTS) { for (Integer j : ELEMENTS) { AGGREGATE += AGGREGATOR.apply(i, j); } } } } public static class For extends Base { @Benchmark public Object java_for() { final List result = new ArrayList<>(CONTAINER_SIZE * CONTAINER_SIZE); for (Integer i : ELEMENTS) { for (Integer j : ELEMENTS) { result.add(AGGREGATOR.apply(i, j)); } } assert Array(result).sum().intValue() == AGGREGATE; return result; } @Benchmark public Object vavr_for() { final List result = For(ELEMENTS, ELEMENTS).yield(AGGREGATOR).collect(toList()); assert Array(result).sum().intValue() == AGGREGATE; return result; } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/idiom/PatternMatchingBenchmark.java000066400000000000000000000061761342074374400304210ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.idiom; import io.vavr.JmhRunner; import io.vavr.collection.Array; import org.junit.Test; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; import java.util.Random; import static io.vavr.API.*; /** * Benchmark for nested loops vs Vavr's For().yield comprehensions. * * @see For2 */ public class PatternMatchingBenchmark { static final Array> CLASSES = Array( MatchVsSwitchIntValues.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class MatchVsSwitchIntValues { int[] VALUES; @Setup public void setup() { final int INSTANCES = 1000; final int CASES = 5; VALUES = Array.range(0, INSTANCES).map(i -> new Random(0).nextInt(CASES)).toJavaStream().mapToInt(i -> i).toArray(); } @Benchmark public void java_switch(Blackhole bh) { for (int i : VALUES) { final String result; switch (i) { case 0: result = "0"; break; case 1: result = "1"; break; case 2: result = "2"; break; case 3: result = "3"; break; default: result = "4"; break; } assert String.valueOf(i).equals(result); bh.consume(result); } } @Benchmark public void vavr_match(Blackhole bh) { for (int i : VALUES) { final String result = Match(i).of( Case($(0), "0"), Case($(1), "1"), Case($(2), "2"), Case($(3), "3"), Case($(), "4") ); assert String.valueOf(i).equals(result); bh.consume(result); } } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/idiom/TryBenchmark.java000066400000000000000000000045441342074374400261040ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.idiom; import io.vavr.JmhRunner; import io.vavr.collection.Array; import org.junit.Test; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; import static io.vavr.API.Array; import static io.vavr.API.Try; /** * Benchmark for Try vs try/catch. */ public class TryBenchmark { static final Array> CLASSES = Array( Try.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { int inverse(int divisor) throws ArithmeticException { return 1 / divisor; } } public static class Try extends Base { @Benchmark public void java_try(Blackhole bh) { for (int i = 0; i <= 1; i++) { int result; try { result = inverse(i); } catch (ArithmeticException e) { result = 0; } assert result == i; bh.consume(result); } } @Benchmark public void vavr_try(Blackhole bh) { for (int i = 0; i <= 1; i++) { int i2 = i; final int result = Try(() -> inverse(i2)) .recover(ArithmeticException.class, 0) .get(); assert result == i; bh.consume(result); } } } } vavr-0.10.0/vavr-benchmark/src/test/java/io/vavr/idiom/TupleBenchmark.java000066400000000000000000000042241342074374400264120ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.idiom; import io.vavr.JmhRunner; import io.vavr.Tuple; import io.vavr.collection.Array; import org.junit.Test; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import static io.vavr.API.Array; /** * Benchmark for Tuple[2,4,8] vs an array. */ @State(Scope.Benchmark) public class TupleBenchmark { static final Array> CLASSES = Array( Tuple2Benchmark.class, Tuple4Benchmark.class, Tuple8Benchmark.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } public static class Tuple2Benchmark { @Benchmark public Object java_tuple() { return new Integer[] { 0, 1 }; } @Benchmark public Object vavr_tuple() { return Tuple.of(0, 1); } } public static class Tuple4Benchmark { @Benchmark public Object java_tuple() { return new Integer[] { 0, 1, 2 }; } @Benchmark public Object vavr_tuple() { return Tuple.of(0, 1, 2, 3); } } public static class Tuple8Benchmark { @Benchmark public Object java_tuple() { return new Integer[] { 0, 1, 2, 3, 4, 5, 6, 7 }; } @Benchmark public Object vavr_tuple() { return Tuple.of(0, 1, 2, 3, 4, 5, 6, 7); } } } vavr-0.10.0/vavr-match-processor/000077500000000000000000000000001342074374400166435ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/pom.xml000066400000000000000000000054171342074374400201670ustar00rootroot00000000000000 4.0.0 io.vavr vavr-parent 0.10.0 ../pom.xml vavr-match-processor jar Vavr Match Annotation Processor Processor for structural pattern matching. http://vavr.io The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo io.vavr vavr-match ${project.version} junit junit test org.assertj assertj-core test org.apache.maven.plugins maven-compiler-plugin none org.apache.maven.plugins maven-source-plugin org.apache.maven.plugins maven-jar-plugin io.vavr.match.processor org.apache.maven.plugins maven-javadoc-plugin org.apache.felix maven-bundle-plugin vavr-0.10.0/vavr-match-processor/src/000077500000000000000000000000001342074374400174325ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/000077500000000000000000000000001342074374400203565ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/java/000077500000000000000000000000001342074374400212775ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/java/io/000077500000000000000000000000001342074374400217065ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/000077500000000000000000000000001342074374400226645ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/000077500000000000000000000000001342074374400237605ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/PatternsProcessor.java000066400000000000000000000133441342074374400303300ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match; import io.vavr.match.annotation.Patterns; import io.vavr.match.annotation.Unapply; import io.vavr.match.generator.Generator; import io.vavr.match.model.ClassModel; import io.vavr.match.model.MethodModel; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import java.io.IOException; import java.io.Writer; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; /** * A code generator for Vavr structural pattern matching patterns. *

* Note: *

* If javac complains {@code [WARNING] No processor claimed any of these annotations: ...} * we need to provide the compiler arg {@code -Xlint:-processing}. *

* See JDK-6999068 bug. * * @author Daniel Dietrich */ // See Difference between Element, Type and Mirror: http://stackoverflow.com/a/2127320/1110815 public class PatternsProcessor extends AbstractProcessor { @Override public Set getSupportedAnnotationTypes() { // we do not use @SupportedAnnotationTypes in order to be type-safe return Collections.singleton(Patterns.class.getName()); } @Override public SourceVersion getSupportedSourceVersion() { // intended to be used with Java 8+ return SourceVersion.latestSupported(); } /** * Gathers annotated elements, transforms elements to a generator model and generates the model to code. * * @param annotations the annotation types requested to be processed * @param roundEnv environment for information about the current and prior round * @return whether or not the set of annotation types are claimed by this processor */ @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (!annotations.isEmpty()) { final Set typeElements = roundEnv.getElementsAnnotatedWith(Patterns.class).stream() .filter(element -> element instanceof TypeElement) .map(element -> (TypeElement) element) .collect(Collectors.toSet()); if (!typeElements.isEmpty()) { final Set classModels = transform(typeElements); if (!classModels.isEmpty()) { generate(classModels); } } } return true; } // Verify correct usage of annotations @Patterns and @Unapply private Set transform(Set typeElements) { final Set classModels = new HashSet<>(); final javax.lang.model.util.Elements elementUtils = processingEnv.getElementUtils(); final Messager messager = processingEnv.getMessager(); for (TypeElement typeElement : typeElements) { final ClassModel classModel = ClassModel.of(elementUtils, typeElement); final List methodModels = classModel.getMethods().stream() .filter(method -> method.isAnnotatedWith(Unapply.class)) .collect(toList()); if (methodModels.isEmpty()) { messager.printMessage(Diagnostic.Kind.WARNING, "No @Unapply methods found.", classModel.typeElement()); } else { final boolean methodsValid = methodModels.stream().reduce(true, (bool, method) -> bool && UnapplyChecker.isValid(method.getExecutableElement(), messager), (b1, b2) -> b1 && b2); if (methodsValid) { classModels.add(classModel); } } } return classModels; } // Expands all @Patterns classes private void generate(Set classModels) { final Filer filer = processingEnv.getFiler(); for (ClassModel classModel : classModels) { final String derivedClassName = deriveClassName(classModel); final String code = Generator.generate(derivedClassName, classModel); final String fqn = (classModel.hasDefaultPackage() ? "" : classModel.getPackageName() + ".") + derivedClassName; try (final Writer writer = filer.createSourceFile(fqn, classModel.typeElement()).openWriter()) { writer.write(code); } catch (IOException x) { throw new Error("Error writing " + fqn, x); } } } private String deriveClassName(ClassModel classModel) { final String name = classModel.getClassName(); return ("$".equals(name) ? "" : name.endsWith(".$") ? name.substring(0, name.length() - 2) : name) .replaceAll("\\.", "_") + Patterns.class.getSimpleName(); } } vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/UnapplyChecker.java000066400000000000000000000066151342074374400275500ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match; import javax.annotation.processing.Messager; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.type.TypeKind; import javax.tools.Diagnostic; import java.util.Arrays; import java.util.Set; import java.util.function.Supplier; import static javax.lang.model.element.Modifier.*; /** * Checks if an {@link javax.lang.model.element.ExecutableElement} is a valid {@code @Unapply} method. * * @author Daniel Dietrich */ class UnapplyChecker { static boolean isValid(ExecutableElement elem, Messager messager) { return ensure(elem, doesNotThrow(elem), messager, () -> "@" + "Unapply method should not throw (checked) exceptions.") && ensure(elem, !elem.isDefault(), messager, () -> "@" + "Unapply method needs to be declared in a class, not an interface.") && ensure(elem, !elem.isVarArgs(), messager, () -> "@" + "Unapply method has varargs.") && ensure(elem, elem.getParameters().size() == 1, messager, () -> "Unapply method must have exactly one parameter of the object to be deconstructed.") && ensure(elem, elem.getParameters().get(0).asType().getKind() == TypeKind.DECLARED, messager, () -> "Unapply method parameter must be a declared type.") && ensure(elem, elem.getReturnType().toString().startsWith("io.vavr.Tuple"), messager, () -> "Return type of unapply method must be a Tuple.") && ensure(elem, !elem.getReturnType().toString().endsWith("Tuple"), messager, () -> "Return type is no Tuple implementation.") && ensure(elem, hasAll(elem, STATIC), messager, () -> "Unapply method needs to be static.") && ensure(elem, hasNone(elem, PRIVATE, PROTECTED, ABSTRACT), messager, () -> "Unapply method may not be private or protected."); } private static boolean ensure(ExecutableElement elem, boolean condition, Messager messager, Supplier msg) { if (!condition) { messager.printMessage(Diagnostic.Kind.ERROR, msg.get(), elem); } return condition; } private static boolean hasAll(ExecutableElement elem, Modifier... modifiers) { return elem.getModifiers().containsAll(Arrays.asList(modifiers)); } private static boolean hasNone(ExecutableElement elem, Modifier... modifiers) { final Set set = elem.getModifiers(); for (Modifier modifier : modifiers) { if (set.contains(modifier)) { return false; } } return true; } private static boolean doesNotThrow(ExecutableElement elem) { return elem.getThrownTypes().isEmpty(); } } vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/generator/000077500000000000000000000000001342074374400257465ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/generator/Generator.java000066400000000000000000000204111342074374400305350ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.generator; import io.vavr.match.annotation.Unapply; import io.vavr.match.model.ClassModel; import io.vavr.match.model.MethodModel; import io.vavr.match.model.TypeParameterModel; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.IntStream; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; /** * Code generator for structural pattern matching patterns. * * @author Daniel Dietrich */ public class Generator { private Generator() { } // ENTRY POINT: Expands one @Patterns class public static String generate(String derivedClassName, ClassModel classModel) { final List methodModels = classModel.getMethods().stream() .filter(method -> method.isAnnotatedWith(Unapply.class)) .collect(toList()); final String _package = classModel.getPackageName(); final ImportManager im = ImportManager.forClass(classModel, "io.vavr.API.Match"); final String methods = generate(im, classModel, methodModels); return "// @formatter:off\n" + "// CHECKSTYLE:OFF\n" + (_package.isEmpty() ? "" : "package " + _package + ";\n\n") + im.getImports() + "\n\n// GENERATED BY VAVR <<>> derived from " + classModel.getFullQualifiedName() + "\n\n" + "@SuppressWarnings(\"deprecation\")\n" + "public final class " + derivedClassName + " {\n\n" + " private " + derivedClassName + "() {\n" + " }\n\n" + methods + "}\n" + "// CHECKSTYLE:ON\n" + "// @formatter:on"; } // Expands the @Unapply methods of a @Patterns class private static String generate(ImportManager im, ClassModel classModel, List methodModels) { final StringBuilder builder = new StringBuilder(); for (MethodModel methodModel : methodModels) { generate(im, classModel, methodModel, builder); builder.append("\n"); } return builder.toString(); } // Expands one @Unapply method private static void generate(ImportManager im, ClassModel classModel, MethodModel methodModel, StringBuilder builder) { final String paramTypeName = im.getType(methodModel.getParameter(0).getType()); final String definedName = methodModel.getName(); final String generatedName = "$" + definedName; final int arity = Integer.parseInt(methodModel.getReturnType().getClassName().substring("Tuple".length())); final String body; if (arity == 0) { body = pattern(im, 0) + ".of(" + paramTypeName + ".class)"; } else { final String args = IntStream.rangeClosed(1, arity).mapToObj(i -> "p" + i).collect(joining(", ")); final String unapplyRef = classModel.getFullQualifiedName() + "::" + definedName; body = String.format("%s.of(%s, %s, %s)", pattern(im, arity), paramTypeName + ".class", args, unapplyRef); } final List typeArgs = methodModel.getTypeParameters().stream() .map(typeParameterModel -> mapToName(im, typeParameterModel)) .collect(toList()); final List upperBoundArgs = deriveUpperBounds(typeArgs, methodModel.getReturnType().getTypeParameters().size()); final String returnType = genReturnType(im, methodModel, upperBoundArgs, arity); final String method; if (arity == 0 && methodModel.getTypeParameters().size() == 0) { method = String.format("final %s %s = %s;", returnType, generatedName, body); } else { final String generics = genGenerics(im, methodModel, typeArgs, upperBoundArgs); final String params = genParams(im, upperBoundArgs, arity); method = String.format("%s %s %s(%s) {\n return %s;\n }", generics, returnType, generatedName, params, body); } builder.append(" public static ").append(method).append("\n"); } // Introduces new upper generic type bounds for decomposed object parts private static List deriveUpperBounds(List typeArgs, int count) { final List result = new ArrayList<>(); final Set knownTypeArgs = new HashSet<>(typeArgs); for (int i = 0; i < count; i++) { String typeArg = "_" + (i + 1); while (knownTypeArgs.contains(typeArg)) { typeArg = "_" + typeArg; } result.add(typeArg); knownTypeArgs.add(typeArg); } return result; } // Expands the generics part of a method declaration private static String genGenerics(ImportManager im, MethodModel methodModel, List typeParameters, List upperBoundArgs) { final List returnTypeArgs = methodModel.getReturnType().getTypeParameters(); if (typeParameters.size() + returnTypeArgs.size() == 0) { return ""; } else { final List result = new ArrayList<>(typeParameters); for (int i = 0; i < returnTypeArgs.size(); i++) { final String returnTypeArg = mapToName(im, returnTypeArgs.get(i)); result.add(upperBoundArgs.get(i) + " extends " + returnTypeArg); } return result.stream().collect(joining(", ", "<", ">")); } } // Expands the return type of a method declaration private static String genReturnType(ImportManager im, MethodModel methodModel, List upperBoundArgs, int arity) { final List resultTypes = new ArrayList<>(); final String type = mapToName(im, methodModel.getParameter(0).getType()); resultTypes.add(type); resultTypes.addAll(upperBoundArgs); return pattern(im, arity) + resultTypes.stream().collect(joining(", ", "<", ">")); } // Expands the parameters of a method declaration private static String genParams(ImportManager im, List upperBoundArgs, int arity) { final String patternType = im.getType("io.vavr", "API.Match.Pattern"); return IntStream.range(0, arity) .mapToObj(i -> patternType + "<" + upperBoundArgs.get(i) + ", ?> p" + (i + 1)) .collect(joining(", ")); } // Recursively maps generic type parameters to names according to their kind private static String mapToName(ImportManager im, TypeParameterModel typeParameterModel) { if (typeParameterModel.isType()) { return mapToName(im, typeParameterModel.asType()); } else if (typeParameterModel.isTypeVar()) { return typeParameterModel.asTypeVar(); } else { throw new IllegalStateException("Unhandled type parameter: " + typeParameterModel.toString()); } } // Recursively maps class generics to names private static String mapToName(ImportManager im, ClassModel classModel) { final List typeParameters = classModel.getTypeParameters(); final String simpleName = im.getType(classModel); if (typeParameters.size() == 0) { return simpleName; } else { return simpleName + classModel.getTypeParameters().stream() .map(typeParam -> mapToName(im, typeParam)) .collect(joining(", ", "<", ">")); } } private static String pattern(ImportManager im, int arity) { return im.getType("io.vavr", "API.Match.Pattern" + arity); } } vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/generator/ImportManager.java000066400000000000000000000156161342074374400313670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.generator; import io.vavr.match.model.ClassModel; import java.util.*; import static java.util.stream.Collectors.joining; /** * A stateful ImportManager which generates an import section of a Java class file. * * @author Daniel Dietrich */ class ImportManager { // properties private final String packageNameOfClass; private List directImports; // mutable state private Map imports = new HashMap<>(); private ImportManager(String packageNameOfClass, List directImports) { this.packageNameOfClass = packageNameOfClass; this.directImports = directImports; } // directImport FQN("io.vavr", "Match.API") will import "io.vavr.Match.API.Pattern0" // otherwise "io.vavr.Match" is imported and "Match.API.Pattern0" is qualified public static ImportManager forClass(ClassModel classModel, String... directImports) { return new ImportManager(classModel.getPackageName(), reverseSort(directImports)); } // used by generator to register non-static imports public String getType(ClassModel classModel) { final FQN fqn = new FQN(classModel.getPackageName(), classModel.getClassName()); return getType(fqn, imports, packageNameOfClass, directImports); } public String getType(String packageName, String className) { final FQN fqn = new FQN(packageName, className); return getType(fqn, imports, packageNameOfClass, directImports); } // finally used by generator to get the import section public String getImports() { return optimizeImports(imports.values()); } private static String getType(FQN fqn, Map imports, String packageNameOfClass, List directImports) { if (fqn.packageName.isEmpty() && !packageNameOfClass.isEmpty()) { throw new IllegalStateException("Can't import class '" + fqn.className + "' located in default package"); } else if (fqn.packageName.equals(packageNameOfClass)) { final Import _import = createImport(fqn, directImports); if (_import.type.equals(fqn.className)) { return fqn.className; } else { imports.put(fqn, _import); return _import.type; } } else if (imports.containsKey(fqn)) { return imports.get(fqn).type; } else { final Import _import = createImport(fqn, directImports); imports.put(fqn, _import); return _import.type; } } private static Import createImport(FQN fqn, List directImports) { final String qualifiedName = fqn.qualifiedName(); final Optional directImportOption = directImports.stream() .filter(directImport -> qualifiedName.equals(directImport) || qualifiedName.startsWith(directImport + ".")) .findFirst(); if (directImportOption.isPresent()) { final String directImport = directImportOption.get(); if (qualifiedName.equals(directImport)) { final String type = directImport.substring(directImport.lastIndexOf('.') + 1); return new Import(directImport, type); } else { final String type = qualifiedName.substring(directImport.length() + 1); final int index = type.indexOf("."); final String firstSegment = (index < 0) ? type : type.substring(0, index); return new Import(directImport + "." + firstSegment, type); } } else { final int index = fqn.className.indexOf("."); final String firstSegment = (index < 0) ? fqn.className : fqn.className.substring(0, index); return new Import(fqn.packageName + "." + firstSegment, fqn.className); } } private static String optimizeImports(Collection imports) { return imports.stream() .filter(currentImport -> !currentImport.name.startsWith("java.lang.") || imports.stream() .filter(otherImport -> !otherImport.equals(currentImport)) .map(otherImport -> otherImport.type) .filter(otherType -> otherType.equals(currentImport.type)) .findFirst().isPresent()) .map(_import -> _import.name) .distinct() .sorted() .map(s -> "import " + s + ";") .collect(joining("\n")); } private static List reverseSort(String[] strings) { final String[] copy = new String[strings.length]; System.arraycopy(strings, 0, copy, 0, strings.length); Arrays.sort(copy, Comparator.reverseOrder()); return Arrays.asList(copy); } private static class FQN { private final String packageName; private final String className; FQN(String packageName, String className) { this.packageName = packageName; this.className = className; } String qualifiedName() { return packageName.isEmpty() ? className : packageName + "." + className; } @Override public boolean equals(Object o) { return (o == this) || (o instanceof FQN && qualifiedName().equals(((FQN) o).qualifiedName())); } @Override public int hashCode() { return qualifiedName().hashCode(); } @Override public String toString() { return "FQN(" + packageName + ", " + className + ")"; } } private static class Import { final String name; final String type; Import(String name, String type) { this.name = name; this.type = type; } @Override public boolean equals(Object o) { return (o == this) || (o instanceof Import && toString().equals(o.toString())); } @Override public int hashCode() { return toString().hashCode(); } @Override public String toString() { return "Import(" + name + ", " + type + ")"; } } } vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/model/000077500000000000000000000000001342074374400250605ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/model/ClassModel.java000066400000000000000000000064321342074374400277560ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.model; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.util.Elements; import java.util.List; import static java.util.stream.Collectors.toList; /** * Representation of a class. * * @author Daniel Dietrich */ public class ClassModel { private final Elements elementUtils; private final DeclaredType declaredType; public static ClassModel of(Elements elementUtils, TypeElement typeElement) { return new ClassModel(elementUtils, (DeclaredType) typeElement.asType()); } public ClassModel(Elements elementUtils, DeclaredType declaredType) { this.elementUtils = elementUtils; this.declaredType = declaredType; } public TypeElement typeElement() { return (TypeElement) declaredType.asElement(); } // returns the simple name for top level class and the combined class name for inner classes public String getClassName() { final String fqn = getFullQualifiedName(); return hasDefaultPackage() ? fqn : fqn.substring(getPackageName().length() + 1); } public String getFullQualifiedName() { return typeElement().getQualifiedName().toString(); } public List getMethods() { return typeElement().getEnclosedElements().stream() .filter(element -> { final String name = element.getSimpleName().toString(); return element instanceof ExecutableElement && !name.isEmpty() && !"".equals(name) && !"".equals(name); }) .map(element -> new MethodModel(elementUtils, (ExecutableElement) element)) .collect(toList()); } public String getPackageName() { return elementUtils.getPackageOf(typeElement()).getQualifiedName().toString(); } public List getTypeParameters() { return declaredType.getTypeArguments().stream() .map(typeMirror -> new TypeParameterModel(elementUtils, typeMirror)) .collect(toList()); } public boolean hasDefaultPackage() { return elementUtils.getPackageOf(typeElement()).isUnnamed(); } @Override public boolean equals(Object o) { return (o == this) || (o instanceof ClassModel && toString().equals(o.toString())); } @Override public int hashCode() { return toString().hashCode(); } @Override public String toString() { return declaredType.toString(); } } vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/model/MethodModel.java000066400000000000000000000055131342074374400301300ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.model; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.util.Elements; import java.lang.annotation.Annotation; import java.util.List; import static java.util.stream.Collectors.toList; /** * Representation of a method. * * @author Daniel Dietrich */ public class MethodModel { private final Elements elementUtils; private final ExecutableElement executableElement; public MethodModel(Elements elementUtils, ExecutableElement executableElement) { this.elementUtils = elementUtils; this.executableElement = executableElement; } public ExecutableElement getExecutableElement() { return executableElement; } public String getName() { return executableElement.getSimpleName().toString(); } public ParameterModel getParameter(int index) { final List parameters = executableElement.getParameters(); if (index < 0 || index > parameters.size()) { throw new ArrayIndexOutOfBoundsException(index); } return new ParameterModel(elementUtils, parameters.get(index)); } public ClassModel getReturnType() { return new ClassModel(elementUtils, (DeclaredType) executableElement.getReturnType()); } public List getTypeParameters() { return executableElement.getTypeParameters().stream() .map(typeParam -> new TypeParameterModel(elementUtils, typeParam.asType())) .collect(toList()); } public boolean isAnnotatedWith(Class annotationType) { return executableElement.getAnnotationsByType(annotationType).length > 0; } @Override public boolean equals(Object o) { return (o == this) || (o instanceof MethodModel && toString().equals(o.toString())); } @Override public int hashCode() { return toString().hashCode(); } @Override public String toString() { return executableElement.toString(); } } vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/model/ParameterModel.java000066400000000000000000000033201342074374400306220ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.model; import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.util.Elements; /** * Representation of a method parameter. * * @author Daniel Dietrich */ public class ParameterModel { private final Elements elementUtils; private final VariableElement variableElement; public ParameterModel(Elements elementUtils, VariableElement variableElement) { this.elementUtils = elementUtils; this.variableElement = variableElement; } public ClassModel getType() { return new ClassModel(elementUtils, (DeclaredType) variableElement.asType()); } @Override public boolean equals(Object o) { return (o == this) || (o instanceof ParameterModel && toString().equals(o.toString())); } @Override public int hashCode() { return toString().hashCode(); } @Override public String toString() { return variableElement.toString(); } } vavr-0.10.0/vavr-match-processor/src/main/java/io/vavr/match/model/TypeParameterModel.java000066400000000000000000000042141342074374400314670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.model; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import static javax.lang.model.type.TypeKind.DECLARED; import static javax.lang.model.type.TypeKind.TYPEVAR; /** * Representation of a generic type parameter. * * @author Daniel Dietrich */ public class TypeParameterModel { private final Elements elementUtils; private final TypeMirror typeMirror; public TypeParameterModel(Elements elementUtils, TypeMirror typeMirror) { this.elementUtils = elementUtils; this.typeMirror = typeMirror; } public ClassModel asType() { return new ClassModel(elementUtils, (DeclaredType) typeMirror); } public String asTypeVar() { return typeMirror.toString(); } public boolean isType() { return isTypeKind(DECLARED); } public boolean isTypeVar() { return isTypeKind(TYPEVAR); } private boolean isTypeKind(TypeKind typeKind) { return typeMirror.getKind() == typeKind; } @Override public boolean equals(Object o) { return (o == this) || (o instanceof TypeParameterModel && toString().equals(o.toString())); } @Override public int hashCode() { return toString().hashCode(); } @Override public String toString() { return typeMirror.toString(); } } vavr-0.10.0/vavr-match-processor/src/main/resources/000077500000000000000000000000001342074374400223705ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/resources/META-INF/000077500000000000000000000000001342074374400235305ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/resources/META-INF/services/000077500000000000000000000000001342074374400253535ustar00rootroot00000000000000javax.annotation.processing.Processor000066400000000000000000000000401342074374400346240ustar00rootroot00000000000000vavr-0.10.0/vavr-match-processor/src/main/resources/META-INF/servicesio.vavr.match.PatternsProcessor vavr-0.10.0/vavr-match/000077500000000000000000000000001342074374400146265ustar00rootroot00000000000000vavr-0.10.0/vavr-match/pom.xml000066400000000000000000000035601342074374400161470ustar00rootroot00000000000000 4.0.0 io.vavr vavr-parent 0.10.0 ../pom.xml vavr-match jar Vavr Match Annotation for structural pattern matching. http://vavr.io The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo org.apache.maven.plugins maven-jar-plugin io.vavr.match org.apache.maven.plugins maven-source-plugin org.apache.maven.plugins maven-javadoc-plugin org.apache.felix maven-bundle-plugin vavr-0.10.0/vavr-match/src/000077500000000000000000000000001342074374400154155ustar00rootroot00000000000000vavr-0.10.0/vavr-match/src/main/000077500000000000000000000000001342074374400163415ustar00rootroot00000000000000vavr-0.10.0/vavr-match/src/main/java/000077500000000000000000000000001342074374400172625ustar00rootroot00000000000000vavr-0.10.0/vavr-match/src/main/java/io/000077500000000000000000000000001342074374400176715ustar00rootroot00000000000000vavr-0.10.0/vavr-match/src/main/java/io/vavr/000077500000000000000000000000001342074374400206475ustar00rootroot00000000000000vavr-0.10.0/vavr-match/src/main/java/io/vavr/match/000077500000000000000000000000001342074374400217435ustar00rootroot00000000000000vavr-0.10.0/vavr-match/src/main/java/io/vavr/match/annotation/000077500000000000000000000000001342074374400241155ustar00rootroot00000000000000vavr-0.10.0/vavr-match/src/main/java/io/vavr/match/annotation/Patterns.java000066400000000000000000000021471342074374400265640ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Structural pattern matching annotation for pattern declarations. * * @author Daniel Dietrich */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS) public @interface Patterns { } vavr-0.10.0/vavr-match/src/main/java/io/vavr/match/annotation/Unapply.java000066400000000000000000000021431342074374400264100ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.match.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Structural pattern matching annotation for unapply methods. * * @author Daniel Dietrich */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) public @interface Unapply { } vavr-0.10.0/vavr-test/000077500000000000000000000000001342074374400145115ustar00rootroot00000000000000vavr-0.10.0/vavr-test/generator/000077500000000000000000000000001342074374400164775ustar00rootroot00000000000000vavr-0.10.0/vavr-test/generator/Generator.scala000066400000000000000000001416111342074374400214360ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // temporarily needed to circumvent https://issues.scala-lang.org/browse/SI-3772 (see case class Generics) import Generator._ import JavaGenerator._ import scala.language.implicitConversions val N = 8 val TARGET_MAIN = s"${project.getBasedir()}/src-gen/main/java" val TARGET_TEST = s"${project.getBasedir()}/src-gen/test/java" val CHARSET = java.nio.charset.StandardCharsets.UTF_8 /** * ENTRY POINT */ def run(): Unit = { generateMainClasses() generateTestClasses() } /** * Generate Vavr src-gen/main/java classes */ def generateMainClasses(): Unit = { // Workaround: Use /$** instead of /** in a StringContext when IntelliJ IDEA otherwise shows up errors in the editor val javadoc = "**" genPropertyChecks() /** * Generator of io.vavr.test.Property */ def genPropertyChecks(): Unit = { genVavrFile("io.vavr.test", "Property")(genProperty) def genProperty(im: ImportManager, packageName: String, className: String): String = xs""" /** * A property builder which provides a fluent API to build checkable properties. * * @author Daniel Dietrich */ public class $className { private final String name; private $className(String name) { this.name = name; } /** * Defines a new Property. * * @param name property name * @return a new {@code Property} * @throws NullPointerException if name is null. * @throws IllegalArgumentException if name is empty or consists of whitespace only */ public static Property def(String name) { ${im.getType("java.util.Objects")}.requireNonNull(name, "name is null"); if (name.trim().isEmpty()) { throw new IllegalArgumentException("name is empty"); } return new Property(name); } private static void logSatisfied(String name, int tries, long millis, boolean exhausted) { if (exhausted) { log(String.format("%s: Exhausted after %s tests in %s ms.", name, tries, millis)); } else { log(String.format("%s: OK, passed %s tests in %s ms.", name, tries, millis)); } } private static void logFalsified(String name, int currentTry, long millis) { log(String.format("%s: Falsified after %s passed tests in %s ms.", name, currentTry - 1, millis)); } private static void logErroneous(String name, int currentTry, long millis, String errorMessage) { log(String.format("%s: Errored after %s passed tests in %s ms with message: %s", name, Math.max(0, currentTry - 1), millis, errorMessage)); } private static void log(String msg) { System.out.println(msg); } /** * Creates a CheckError caused by an exception when obtaining a generator. * * @param position The position of the argument within the argument list of the property, starting with 1. * @param size The size hint passed to the {@linkplain Arbitrary} which caused the error. * @param cause The error which occurred when the {@linkplain Arbitrary} tried to obtain the generator {@linkplain Gen}. * @return a new CheckError instance. */ private static CheckError arbitraryError(int position, int size, Throwable cause) { return new CheckError(String.format("Arbitrary %s of size %s: %s", position, size, cause.getMessage()), cause); } /** * Creates a CheckError caused by an exception when generating a value. * * @param position The position of the argument within the argument list of the property, starting with 1. * @param size The size hint of the arbitrary which called the generator {@linkplain Gen} which caused the error. * @param cause The error which occurred when the {@linkplain Gen} tried to generate a random value. * @return a new CheckError instance. */ private static CheckError genError(int position, int size, Throwable cause) { return new CheckError(String.format("Gen %s of size %s: %s", position, size, cause.getMessage()), cause); } /** * Creates a CheckError caused by an exception when testing a Predicate. * * @param cause The error which occurred when applying the {@linkplain java.util.function.Predicate}. * @return a new CheckError instance. */ private static CheckError predicateError(Throwable cause) { return new CheckError("Applying predicate: " + cause.getMessage(), cause); } ${(1 to N).gen(i => { val generics = (1 to i).gen(j => s"T$j")(", ") val parameters = (1 to i).gen(j => s"a$j")(", ") val parametersDecl = (1 to i).gen(j => s"Arbitrary a$j")(", ") xs""" /$javadoc * Returns a logical for all quantor of $i given variables. * ${(1 to i).gen(j => s"* @param ${j.ordinal} variable type of this for all quantor")("\n")} ${(1 to i).gen(j => s"* @param a$j ${j.ordinal} variable of this for all quantor")("\n")} * @return a new {@code ForAll$i} instance of $i variables */ public <$generics> ForAll$i<$generics> forAll($parametersDecl) { return new ForAll$i<>(name, $parameters); } """ })("\n\n")} ${(1 to N).gen(i => { val generics = (1 to i).gen(j => s"T$j")(", ") val params = (name: String) => (1 to i).gen(j => s"$name$j")(", ") val parametersDecl = (1 to i).gen(j => s"Arbitrary a$j")(", ") xs""" /$javadoc * Represents a logical for all quantor. * ${(1 to i).gen(j => s"* @param ${j.ordinal} variable type of this for all quantor")("\n")} * @author Daniel Dietrich */ public static class ForAll$i<$generics> { private final String name; ${(1 to i).gen(j => xs""" private final Arbitrary a$j; """)("\n")} ForAll$i(String name, $parametersDecl) { this.name = name; ${(1 to i).gen(j => xs""" this.a$j = a$j; """)("\n")} } /$javadoc * Returns a checkable property that checks values of the $i variables of this {@code ForAll} quantor. * * @param predicate A $i-ary predicate * @return a new {@code Property$i} of $i variables. */ public Property$i<$generics> suchThat(${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate) { final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Condition> proposition = (${params("t")}) -> new Condition(true, predicate.apply(${params("t")})); return new Property$i<>(name, ${params("a")}, proposition); } } """ })("\n\n")} ${(1 to N).gen(i => { val checkedFunctionType = im.getType(s"io.vavr.CheckedFunction$i") val optionType = im.getType("io.vavr.control.Option") val randomType = im.getType("java.util.Random") val tryType = im.getType("io.vavr.control.Try") val checkException = "CheckException" val tupleType = im.getType(s"io.vavr.Tuple") val generics = (1 to i).gen(j => s"T$j")(", ") val params = (paramName: String) => (1 to i).gen(j => s"$paramName$j")(", ") val parametersDecl = (1 to i).gen(j => s"Arbitrary a$j")(", ") xs""" /$javadoc * Represents a $i-ary checkable property. * * @author Daniel Dietrich */ public static class Property$i<$generics> implements Checkable { private final String name; ${(1 to i).gen(j => xs""" private final Arbitrary a$j; """)("\n")} private final $checkedFunctionType<$generics, Condition> predicate; Property$i(String name, $parametersDecl, $checkedFunctionType<$generics, Condition> predicate) { this.name = name; ${(1 to i).gen(j => xs""" this.a$j = a$j; """)("\n")} this.predicate = predicate; } /$javadoc * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies($checkedFunctionType<$generics, Boolean> postcondition) { final $checkedFunctionType<$generics, Condition> implication = (${params("t")}) -> { final Condition precondition = predicate.apply(${params("t")}); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(${params("t")})); } }; return new Property$i<>(name, ${params("a")}, implication); } @Override public CheckResult check($randomType random, int size, int tries) { ${im.getType("java.util.Objects")}.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { ${(1 to i).gen(j => { s"""final Gen gen$j = $tryType.of(() -> a$j.apply(size)).recover(x -> { throw arbitraryError($j, size, x); }).get();""" })("\n")} boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { ${(1 to i).gen(j => { s"""final T$j val$j = $tryType.of(() -> gen$j.apply(random)).recover(x -> { throw genError($j, size, x); }).get();""" })("\n")} try { final Condition condition = $tryType.of(() -> predicate.apply(${(1 to i).gen(j => s"val$j")(", ")})).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, $tupleType.of(${(1 to i).gen(j => s"val$j")(", ")})); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, $optionType.some($tupleType.of(${(1 to i).gen(j => s"val$j")(", ")}))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, $optionType.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, $optionType.none()); } } } """ })("\n\n")} /** * Internally used to model conditions composed of pre- and post-condition. */ static class Condition { static final Condition EX_FALSO_QUODLIBET = new Condition(false, true); final boolean precondition; final boolean postcondition; Condition(boolean precondition, boolean postcondition) { this.precondition = precondition; this.postcondition = postcondition; } // ¬(p => q) ≡ ¬(¬p ∨ q) ≡ p ∧ ¬q boolean isFalse() { return precondition && !postcondition; } } /** * Internally used to provide more specific error messages. */ static class CheckError extends Error { private static final long serialVersionUID = 1L; CheckError(String message, Throwable cause) { super(message, cause); } } } """ } } /** * Generate Vavr src-gen/test/java classes */ def generateTestClasses(): Unit = { genPropertyCheckTests() /** * Generator of Property-check tests */ def genPropertyCheckTests(): Unit = { genVavrFile("io.vavr.test", "PropertyTest", baseDir = TARGET_TEST)((im: ImportManager, packageName, className) => { // main classes val list = im.getType("io.vavr.collection.List") val predicate = im.getType("io.vavr.CheckedFunction1") val random = im.getType("java.util.Random") val tuple = im.getType("io.vavr.Tuple") // test classes val test = im.getType("org.junit.Test") val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") val woops = "yay! (this is a negative test)" xs""" public class $className { static $predicate tautology() { return any -> true; } static $predicate falsum() { return any -> false; } static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @$test(expected = NullPointerException.class) public void shouldThrowWhenPropertyNameIsNull() { Property.def(null); } @$test(expected = IllegalArgumentException.class) public void shouldThrowWhenPropertyNameIsEmpty() { Property.def(""); } // -- Property.check methods @$test public void shouldCheckUsingDefaultConfiguration() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isFalse(); } @$test public void shouldCheckGivenSizeAndTries() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, 0); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isTrue(); } @$test(expected = IllegalArgumentException.class) public void shouldThrowOnCheckGivenNegativeTries() { Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, -1); } @$test public void shouldCheckGivenRandomAndSizeAndTries() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(new $random(), 0, 0); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isTrue(); } // -- satisfaction @$test public void shouldCheckPythagoras() { final Arbitrary real = n -> Gen.choose(0, (double) n).filter(d -> d > .0d); // (∀a,b ∈ ℝ+ ∃c ∈ ℝ+ : a²+b²=c²) ≡ (∀a,b ∈ ℝ+ : √(a²+b²) ∈ ℝ+) final Checkable property = Property.def("test").forAll(real, real).suchThat((a, b) -> Math.sqrt(a * a + b * b) > .0d); final CheckResult result = property.check(); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isFalse(); } @$test public void shouldCheckZipAndThenUnzipIsIdempotentForListsOfSameLength() { // ∀is,ss: length(is) = length(ss) → unzip(zip(is, ss)) = (is, ss) final Arbitrary<$list> ints = Arbitrary.list(size -> Gen.choose(0, size)); final Arbitrary<$list> strings = Arbitrary.list( Arbitrary.string( Gen.frequency( Tuple.of(1, Gen.choose('A', 'Z')), Tuple.of(1, Gen.choose('a', 'z')), Tuple.of(1, Gen.choose('0', '9')) ))); final CheckResult result = Property.def("test") .forAll(ints, strings) .suchThat((is, ss) -> is.length() == ss.length()) .implies((is, ss) -> is.zip(ss).unzip(t -> t).equals($tuple.of(is, ss))) .check(); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isFalse(); } // -- exhausting @$test public void shouldRecognizeExhaustedParameters() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(falsum()).implies(tautology()).check(); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isTrue(); } // -- falsification @$test public void shouldFalsifyFalseProperty() { final Arbitrary ones = n -> random -> 1; final CheckResult result = Property.def("test").forAll(ones).suchThat(one -> one == 2).check(); $assertThat(result.isFalsified()).isTrue(); $assertThat(result.isExhausted()).isFalse(); $assertThat(result.count()).isEqualTo(1); } // -- error detection @$test public void shouldRecognizeArbitraryError() { final Arbitrary arbitrary = n -> { throw new RuntimeException("$woops"); }; final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); $assertThat(result.isErroneous()).isTrue(); $assertThat(result.isExhausted()).isFalse(); $assertThat(result.count()).isEqualTo(0); $assertThat(result.sample().isEmpty()).isTrue(); } @$test public void shouldRecognizeGenError() { final Arbitrary arbitrary = Gen.fail("$woops").arbitrary(); final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); $assertThat(result.isErroneous()).isTrue(); $assertThat(result.isExhausted()).isFalse(); $assertThat(result.count()).isEqualTo(1); $assertThat(result.sample().isEmpty()).isTrue(); } @$test public void shouldRecognizePropertyError() { final Arbitrary a1 = n -> random -> 1; final Arbitrary a2 = n -> random -> 2; final CheckResult result = Property.def("test").forAll(a1, a2).suchThat((a, b) -> { throw new RuntimeException("$woops"); }).check(); $assertThat(result.isErroneous()).isTrue(); $assertThat(result.isExhausted()).isFalse(); $assertThat(result.count()).isEqualTo(1); $assertThat(result.sample().isDefined()).isTrue(); $assertThat(result.sample().get()).isEqualTo(Tuple.of(1, 2)); } // -- Property.and tests @$test public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.and(p2).check(); $assertThat(result.isSatisfied()).isTrue(); } @$test public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.and(p2).check(); $assertThat(result.isSatisfied()).isFalse(); } @$test public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.and(p2).check(); $assertThat(result.isSatisfied()).isFalse(); } @$test public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.and(p2).check(); $assertThat(result.isSatisfied()).isFalse(); } // -- Property.or tests @$test public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.or(p2).check(); $assertThat(result.isSatisfied()).isTrue(); } @$test public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.or(p2).check(); $assertThat(result.isSatisfied()).isTrue(); } @$test public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.or(p2).check(); $assertThat(result.isSatisfied()).isTrue(); } @$test public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.or(p2).check(); $assertThat(result.isSatisfied()).isFalse(); } } """ }) for (i <- 1 to N) { genVavrFile("io.vavr.test", s"PropertyCheck${i}Test", baseDir = TARGET_TEST)((im: ImportManager, packageName, className) => { val generics = (1 to i).gen(j => "Object")(", ") val arbitraries = (1 to i).gen(j => "OBJECTS")(", ") val arbitrariesMinus1 = (1 until i).gen(j => "OBJECTS")(", ") val args = (1 to i).gen(j => s"o$j")(", ") // test classes val test = im.getType("org.junit.Test") val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") val woops = "yay! (this is a negative test)" xs""" public class $className { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @$test public void shouldApplyForAllOfArity$i() { final Property.ForAll$i<${(1 to i).gen(j => "Object")(", ")}> forAll = Property.def("test").forAll(${(1 to i).gen(j => "null")(", ")}); $assertThat(forAll).isNotNull(); } @$test public void shouldApplySuchThatOfArity$i() { final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> true; final Property.Property$i<$generics> suchThat = forAll.suchThat(predicate); $assertThat(suchThat).isNotNull(); } @$test public void shouldCheckTrueProperty$i() { final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> true; final CheckResult result = forAll.suchThat(predicate).check(); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isFalse(); } @$test public void shouldCheckFalseProperty$i() { final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> false; final CheckResult result = forAll.suchThat(predicate).check(); $assertThat(result.isFalsified()).isTrue(); } @$test public void shouldCheckErroneousProperty$i() { final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> { throw new RuntimeException("$woops"); }; final CheckResult result = forAll.suchThat(predicate).check(); $assertThat(result.isErroneous()).isTrue(); } @$test public void shouldCheckProperty${i}ImplicationWithTruePrecondition() { final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p1 = ($args) -> true; final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p2 = ($args) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isFalse(); } @$test public void shouldCheckProperty${i}ImplicationWithFalsePrecondition() { final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p1 = ($args) -> false; final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p2 = ($args) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); $assertThat(result.isSatisfied()).isTrue(); $assertThat(result.isExhausted()).isTrue(); } @$test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty${i}CheckGivenNegativeTries() { Property.def("test") .forAll($arbitraries) .suchThat(($args) -> true) .check(Checkable.RNG.get(), 0, -1); } @$test public void shouldReturnErroneousProperty${i}CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("$woops").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen${(i > 1).gen(s", $arbitrariesMinus1")}) .suchThat(($args) -> true) .check(); $assertThat(result.isErroneous()).isTrue(); } @$test public void shouldReturnErroneousProperty${i}CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("$woops"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary${(i > 1).gen(s", $arbitrariesMinus1")}) .suchThat(($args) -> true) .check(); $assertThat(result.isErroneous()).isTrue(); } } """ }) } } } /** * Adds the Vavr header to generated classes. * @param packageName Java package name * @param className Simple java class name * @param gen A generator which produces a String. */ def genVavrFile(packageName: String, className: String, baseDir: String = TARGET_MAIN)(gen: (ImportManager, String, String) => String, knownSimpleClassNames: List[String] = List()) = genJavaFile(baseDir, packageName, className)(xraw""" /* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ """)(gen)(CHARSET) /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ J A V A G E N E R A T O R F R A M E W O R K \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ object JavaGenerator { import java.nio.charset.{Charset, StandardCharsets} import Generator._ /** * Generates a Java file. * @param packageName Java package name * @param className Simple java class name * @param classHeader A class file header * @param gen A generator which produces a String. */ def genJavaFile(baseDir: String, packageName: String, className: String)(classHeader: String)(gen: (ImportManager, String, String) => String, knownSimpleClassNames: List[String] = List())(implicit charset: Charset = StandardCharsets.UTF_8): Unit = { // DEV-NOTE: using File.separator instead of "/" does *not* work on windows! val dirName = packageName.replaceAll("[.]", "/") val fileName = className + ".java" val importManager = new ImportManager(packageName, knownSimpleClassNames) val classBody = gen.apply(importManager, packageName, className) genFile(baseDir, dirName, fileName)(xraw""" $classHeader package $packageName; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ ${importManager.getImports} $classBody """) } /** * A stateful ImportManager which generates an import section of a Java class file. * @param packageNameOfClass package name of the generated class * @param knownSimpleClassNames a list of class names which may not be imported from other packages */ class ImportManager(packageNameOfClass: String, knownSimpleClassNames: List[String], wildcardThreshold: Int = 5) { import scala.collection.mutable val nonStaticImports = new mutable.HashMap[String, String] val staticImports = new mutable.HashMap[String, String] def getType(fullQualifiedName: String): String = simplify(fullQualifiedName, nonStaticImports) def getStatic(fullQualifiedName: String): String = simplify(fullQualifiedName, staticImports) def getImports: String = { def optimizeImports(imports: Seq[String], static: Boolean): String = { val counts = imports.map(getPackageName).groupBy(s => s).map { case (s, list) => s -> list.length } val directImports = imports.filter(s => counts(getPackageName(s)) <= wildcardThreshold) val wildcardImports = counts.filter { case (_, count) => count > wildcardThreshold }.keySet.toIndexedSeq.map(s => s"$s.*") (directImports ++ wildcardImports).sorted.map(fqn => s"import ${static.gen("static ")}$fqn;").mkString("\n") } val staticImportSection = optimizeImports(staticImports.keySet.toIndexedSeq, static = true) val nonStaticImportSection = optimizeImports(nonStaticImports.keySet.toIndexedSeq, static = false) Seq(staticImportSection, nonStaticImportSection).mkString("\n\n") } private def simplify(fullQualifiedName: String, imports: mutable.HashMap[String, String]): String = { val simpleName = getSimpleName(fullQualifiedName) val packageName = getPackageName(fullQualifiedName) if (packageName.isEmpty && !packageNameOfClass.isEmpty) { throw new IllegalStateException(s"Can't import class '$simpleName' located in default package") } else if (packageName == packageNameOfClass) { simpleName } else if (imports.contains(fullQualifiedName)) { imports(fullQualifiedName) } else if (simpleName != "*" && (knownSimpleClassNames.contains(simpleName) || imports.values.exists(simpleName.equals(_)))) { fullQualifiedName } else { imports += fullQualifiedName -> simpleName simpleName } } private def getPackageName(fqn: String): String = fqn.substring(0, Math.max(fqn.lastIndexOf("."), 0)) private def getSimpleName(fqn: String): String = fqn.substring(fqn.lastIndexOf(".") + 1) } } /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ C O R E G E N E R A T O R F R A M E W O R K \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /** * Core generator API */ object Generator { import java.nio.charset.{Charset, StandardCharsets} import java.nio.file.{Files, Paths, StandardOpenOption} /** * Generates a file by writing string contents to the file system. * * @param baseDir The base directory, e.g. src-gen * @param dirName The directory relative to baseDir, e.g. main/java * @param fileName The file name within baseDir/dirName * @param createOption One of java.nio.file.{StandardOpenOption.CREATE_NEW, StandardOpenOption.CREATE}, default: CREATE_NEW * @param contents The string contents of the file * @param charset The charset, by default UTF-8 */ def genFile(baseDir: String, dirName: String, fileName: String, createOption: StandardOpenOption = StandardOpenOption.CREATE_NEW)(contents: => String)(implicit charset: Charset = StandardCharsets.UTF_8): Unit = { // println(s"Generating $dirName${File.separator}$fileName") Files.write( Files.createDirectories(Paths.get(baseDir, dirName)).resolve(fileName), contents.getBytes(charset), createOption, StandardOpenOption.WRITE) } implicit class IntExtensions(i: Int) { // returns i as ordinal, i.e. 1st, 2nd, 3rd, 4th, ... def ordinal: String = s"$i" + (if (i >= 4 && i <= 20) { "th" } else { i % 10 match { case 1 => "st" case 2 => "nd" case 3 => "rd" case _ => "th" } }) // returns the grammatical number of a string, i.e. `i.numerus("name")` is // 0: "no name", 1: "one name", 2: "two names", 3: "three names", 4: "4 names", ... def numerus(noun: String): String = Math.abs(i) match { case 0 => s"no ${noun}s" case 1 => s"one $noun" case 2 => s"two ${noun}s" case 3 => s"three ${noun}s" case _ => s"$i ${noun}s" } } implicit class StringExtensions(s: String) { // gets first char of s as string. throws if string is empty def first: String = s.substring(0, 1) // converts first char of s to upper case. throws if string is empty def firstUpper: String = s(0).toUpper + s.substring(1) // converts first char of s to lower case. throws if string is empty def firstLower: String = s(0).toLower + s.substring(1) } implicit class BooleanExtensions(condition: Boolean) { def gen(s: => String): String = if (condition) s else "" } implicit class OptionExtensions(option: Option[Any]) { def gen(f: String => String): String = option.map(any => f.apply(any.toString)).getOrElse("") def gen: String = option.map(any => any.toString).getOrElse("") } /** * Generates a String based on ints within a specific range. * {{{ * (1 to 3).gen(i => s"x$i")(", ") // x1, x2, x3 * (1 to 3).reverse.gen(i -> s"x$i")(", ") // x3, x2, x1 * }}} * @param range A Range */ implicit class RangeExtensions(range: Range) { def gen(f: Int => String = String.valueOf)(implicit delimiter: String = ""): String = range map f mkString delimiter } /** * Generates a String based on an Iterable of objects. Objects are converted to Strings via toString. * {{{ * // val a = "A" * // val b = "B" * // val c = "C" * Seq("a", "b", "c").gen(s => raw"""val $s = "${s.toUpperCase}"""")("\n") * }}} * * @param iterable An Interable */ implicit class IterableExtensions(iterable: Iterable[Any]) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = iterable.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple1Extensions(tuple: Tuple1[Any]) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = f.apply(tuple._1.toString) mkString delimiter } implicit class Tuple2Extensions(tuple: (Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } /** * Generates a String based on a tuple of objects. Objects are converted to Strings via toString. * {{{ * // val seq = Seq("a", "1", "true") * s"val seq = Seq(${("a", 1, true).gen(s => s""""$s"""")(", ")})" * }}} * @param tuple A Tuple */ implicit class Tuple3Extensions(tuple: (Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple4Extensions(tuple: (Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple5Extensions(tuple: (Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple6Extensions(tuple: (Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple7Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple8Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple9Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple10Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple11Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple12Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple13Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple14Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple15Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple16Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple17Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple18Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple19Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple20Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple21Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple22Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } /** * Provides StringContext extensions, e.g. indentation of cascaded rich strings. * @param sc Current StringContext * @see this gist */ implicit class StringContextExtensions(sc: StringContext) { import scala.util.Properties.lineSeparator /** * Formats escaped strings. * @param args StringContext parts * @return An aligned String */ def xs(args: Any*): String = align(sc.s, args) /** * Formats raw/unescaped strings. * @param args StringContext parts * @return An aligned String */ def xraw(args: Any*): String = align(sc.raw, args) /** * Indenting a rich string, removing first and last newline. * A rich string consists of arguments surrounded by text parts. */ private def align(interpolator: Seq[Any] => String, args: Seq[Any]): String = { // indent embedded strings, invariant: parts.length = args.length + 1 val indentedArgs = for { (part, arg) <- sc.parts zip args.map(s => if (s == null) "" else s.toString) } yield { // get the leading space of last line of current part val space = """([ \t]*)[^\s]*$""".r.findFirstMatchIn(part).map(_.group(1)).getOrElse("") // add this leading space to each line (except the first) of current arg arg.split("\r?\n") match { case lines: Array[String] if lines.nonEmpty => lines reduce (_ + lineSeparator + space + _) case whitespace => whitespace mkString "" } } // remove first and last newline and split string into separate lines // adding termination symbol \u0000 in order to preserve empty strings between last newlines when splitting val split = (interpolator(indentedArgs).replaceAll( """(^[ \t]*\r?\n)|(\r?\n[ \t]*$)""", "") + '\u0000').split("\r?\n") // find smallest indentation val prefix = split filter (!_.trim().isEmpty) map { s => """^\s+""".r.findFirstIn(s).getOrElse("") } match { case prefixes: Array[String] if prefixes.length > 0 => prefixes reduce { (s1, s2) => if (s1.length <= s2.length) s1 else s2 } case _ => "" } // align all lines val aligned = split map { s => if (s.startsWith(prefix)) s.substring(prefix.length) else s } mkString lineSeparator dropRight 1 // dropping termination character \u0000 // combine multiple newlines to two aligned.replaceAll("""[ \t]*\r?\n ([ \t]*\r?\n)+""", lineSeparator * 2) } } } vavr-0.10.0/vavr-test/pom.xml000066400000000000000000000060211342074374400160250ustar00rootroot00000000000000 4.0.0 io.vavr vavr-parent 0.10.0 ../pom.xml vavr-test jar Vavr Test A property check framework for Vavr. http://vavr.io The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo ${project.groupId} vavr ${project.version} junit junit test org.assertj assertj-core test org.apache.maven.plugins maven-source-plugin org.apache.maven.plugins maven-clean-plugin net.alchim31.maven scala-maven-plugin org.codehaus.mojo build-helper-maven-plugin org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-jar-plugin io.vavr.test org.apache.maven.plugins maven-javadoc-plugin org.apache.felix maven-bundle-plugin vavr-0.10.0/vavr-test/src-gen/000077500000000000000000000000001342074374400160475ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/main/000077500000000000000000000000001342074374400167735ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/main/java/000077500000000000000000000000001342074374400177145ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/main/java/io/000077500000000000000000000000001342074374400203235ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/main/java/io/vavr/000077500000000000000000000000001342074374400213015ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/main/java/io/vavr/test/000077500000000000000000000000001342074374400222605ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/main/java/io/vavr/test/Property.java000066400000000000000000001747661342074374400247740ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.*; import io.vavr.control.Option; import io.vavr.control.Try; import java.util.Objects; import java.util.Random; /** * A property builder which provides a fluent API to build checkable properties. * * @author Daniel Dietrich */ public class Property { private final String name; private Property(String name) { this.name = name; } /** * Defines a new Property. * * @param name property name * @return a new {@code Property} * @throws NullPointerException if name is null. * @throws IllegalArgumentException if name is empty or consists of whitespace only */ public static Property def(String name) { Objects.requireNonNull(name, "name is null"); if (name.trim().isEmpty()) { throw new IllegalArgumentException("name is empty"); } return new Property(name); } private static void logSatisfied(String name, int tries, long millis, boolean exhausted) { if (exhausted) { log(String.format("%s: Exhausted after %s tests in %s ms.", name, tries, millis)); } else { log(String.format("%s: OK, passed %s tests in %s ms.", name, tries, millis)); } } private static void logFalsified(String name, int currentTry, long millis) { log(String.format("%s: Falsified after %s passed tests in %s ms.", name, currentTry - 1, millis)); } private static void logErroneous(String name, int currentTry, long millis, String errorMessage) { log(String.format("%s: Errored after %s passed tests in %s ms with message: %s", name, Math.max(0, currentTry - 1), millis, errorMessage)); } private static void log(String msg) { System.out.println(msg); } /** * Creates a CheckError caused by an exception when obtaining a generator. * * @param position The position of the argument within the argument list of the property, starting with 1. * @param size The size hint passed to the {@linkplain Arbitrary} which caused the error. * @param cause The error which occurred when the {@linkplain Arbitrary} tried to obtain the generator {@linkplain Gen}. * @return a new CheckError instance. */ private static CheckError arbitraryError(int position, int size, Throwable cause) { return new CheckError(String.format("Arbitrary %s of size %s: %s", position, size, cause.getMessage()), cause); } /** * Creates a CheckError caused by an exception when generating a value. * * @param position The position of the argument within the argument list of the property, starting with 1. * @param size The size hint of the arbitrary which called the generator {@linkplain Gen} which caused the error. * @param cause The error which occurred when the {@linkplain Gen} tried to generate a random value. * @return a new CheckError instance. */ private static CheckError genError(int position, int size, Throwable cause) { return new CheckError(String.format("Gen %s of size %s: %s", position, size, cause.getMessage()), cause); } /** * Creates a CheckError caused by an exception when testing a Predicate. * * @param cause The error which occurred when applying the {@linkplain java.util.function.Predicate}. * @return a new CheckError instance. */ private static CheckError predicateError(Throwable cause) { return new CheckError("Applying predicate: " + cause.getMessage(), cause); } /** * Returns a logical for all quantor of 1 given variables. * * @param 1st variable type of this for all quantor * @param a1 1st variable of this for all quantor * @return a new {@code ForAll1} instance of 1 variables */ public ForAll1 forAll(Arbitrary a1) { return new ForAll1<>(name, a1); } /** * Returns a logical for all quantor of 2 given variables. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param a1 1st variable of this for all quantor * @param a2 2nd variable of this for all quantor * @return a new {@code ForAll2} instance of 2 variables */ public ForAll2 forAll(Arbitrary a1, Arbitrary a2) { return new ForAll2<>(name, a1, a2); } /** * Returns a logical for all quantor of 3 given variables. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param a1 1st variable of this for all quantor * @param a2 2nd variable of this for all quantor * @param a3 3rd variable of this for all quantor * @return a new {@code ForAll3} instance of 3 variables */ public ForAll3 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3) { return new ForAll3<>(name, a1, a2, a3); } /** * Returns a logical for all quantor of 4 given variables. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param a1 1st variable of this for all quantor * @param a2 2nd variable of this for all quantor * @param a3 3rd variable of this for all quantor * @param a4 4th variable of this for all quantor * @return a new {@code ForAll4} instance of 4 variables */ public ForAll4 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4) { return new ForAll4<>(name, a1, a2, a3, a4); } /** * Returns a logical for all quantor of 5 given variables. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @param a1 1st variable of this for all quantor * @param a2 2nd variable of this for all quantor * @param a3 3rd variable of this for all quantor * @param a4 4th variable of this for all quantor * @param a5 5th variable of this for all quantor * @return a new {@code ForAll5} instance of 5 variables */ public ForAll5 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5) { return new ForAll5<>(name, a1, a2, a3, a4, a5); } /** * Returns a logical for all quantor of 6 given variables. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @param 6th variable type of this for all quantor * @param a1 1st variable of this for all quantor * @param a2 2nd variable of this for all quantor * @param a3 3rd variable of this for all quantor * @param a4 4th variable of this for all quantor * @param a5 5th variable of this for all quantor * @param a6 6th variable of this for all quantor * @return a new {@code ForAll6} instance of 6 variables */ public ForAll6 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6) { return new ForAll6<>(name, a1, a2, a3, a4, a5, a6); } /** * Returns a logical for all quantor of 7 given variables. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @param 6th variable type of this for all quantor * @param 7th variable type of this for all quantor * @param a1 1st variable of this for all quantor * @param a2 2nd variable of this for all quantor * @param a3 3rd variable of this for all quantor * @param a4 4th variable of this for all quantor * @param a5 5th variable of this for all quantor * @param a6 6th variable of this for all quantor * @param a7 7th variable of this for all quantor * @return a new {@code ForAll7} instance of 7 variables */ public ForAll7 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7) { return new ForAll7<>(name, a1, a2, a3, a4, a5, a6, a7); } /** * Returns a logical for all quantor of 8 given variables. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @param 6th variable type of this for all quantor * @param 7th variable type of this for all quantor * @param 8th variable type of this for all quantor * @param a1 1st variable of this for all quantor * @param a2 2nd variable of this for all quantor * @param a3 3rd variable of this for all quantor * @param a4 4th variable of this for all quantor * @param a5 5th variable of this for all quantor * @param a6 6th variable of this for all quantor * @param a7 7th variable of this for all quantor * @param a8 8th variable of this for all quantor * @return a new {@code ForAll8} instance of 8 variables */ public ForAll8 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, Arbitrary a8) { return new ForAll8<>(name, a1, a2, a3, a4, a5, a6, a7, a8); } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll1 { private final String name; private final Arbitrary a1; ForAll1(String name, Arbitrary a1) { this.name = name; this.a1 = a1; } /** * Returns a checkable property that checks values of the 1 variables of this {@code ForAll} quantor. * * @param predicate A 1-ary predicate * @return a new {@code Property1} of 1 variables. */ public Property1 suchThat(CheckedFunction1 predicate) { final CheckedFunction1 proposition = (t1) -> new Condition(true, predicate.apply(t1)); return new Property1<>(name, a1, proposition); } } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll2 { private final String name; private final Arbitrary a1; private final Arbitrary a2; ForAll2(String name, Arbitrary a1, Arbitrary a2) { this.name = name; this.a1 = a1; this.a2 = a2; } /** * Returns a checkable property that checks values of the 2 variables of this {@code ForAll} quantor. * * @param predicate A 2-ary predicate * @return a new {@code Property2} of 2 variables. */ public Property2 suchThat(CheckedFunction2 predicate) { final CheckedFunction2 proposition = (t1, t2) -> new Condition(true, predicate.apply(t1, t2)); return new Property2<>(name, a1, a2, proposition); } } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll3 { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; ForAll3(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; } /** * Returns a checkable property that checks values of the 3 variables of this {@code ForAll} quantor. * * @param predicate A 3-ary predicate * @return a new {@code Property3} of 3 variables. */ public Property3 suchThat(CheckedFunction3 predicate) { final CheckedFunction3 proposition = (t1, t2, t3) -> new Condition(true, predicate.apply(t1, t2, t3)); return new Property3<>(name, a1, a2, a3, proposition); } } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll4 { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; ForAll4(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; } /** * Returns a checkable property that checks values of the 4 variables of this {@code ForAll} quantor. * * @param predicate A 4-ary predicate * @return a new {@code Property4} of 4 variables. */ public Property4 suchThat(CheckedFunction4 predicate) { final CheckedFunction4 proposition = (t1, t2, t3, t4) -> new Condition(true, predicate.apply(t1, t2, t3, t4)); return new Property4<>(name, a1, a2, a3, a4, proposition); } } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll5 { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; ForAll5(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; } /** * Returns a checkable property that checks values of the 5 variables of this {@code ForAll} quantor. * * @param predicate A 5-ary predicate * @return a new {@code Property5} of 5 variables. */ public Property5 suchThat(CheckedFunction5 predicate) { final CheckedFunction5 proposition = (t1, t2, t3, t4, t5) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5)); return new Property5<>(name, a1, a2, a3, a4, a5, proposition); } } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @param 6th variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll6 { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; private final Arbitrary a6; ForAll6(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; this.a6 = a6; } /** * Returns a checkable property that checks values of the 6 variables of this {@code ForAll} quantor. * * @param predicate A 6-ary predicate * @return a new {@code Property6} of 6 variables. */ public Property6 suchThat(CheckedFunction6 predicate) { final CheckedFunction6 proposition = (t1, t2, t3, t4, t5, t6) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5, t6)); return new Property6<>(name, a1, a2, a3, a4, a5, a6, proposition); } } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @param 6th variable type of this for all quantor * @param 7th variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll7 { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; private final Arbitrary a6; private final Arbitrary a7; ForAll7(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; this.a6 = a6; this.a7 = a7; } /** * Returns a checkable property that checks values of the 7 variables of this {@code ForAll} quantor. * * @param predicate A 7-ary predicate * @return a new {@code Property7} of 7 variables. */ public Property7 suchThat(CheckedFunction7 predicate) { final CheckedFunction7 proposition = (t1, t2, t3, t4, t5, t6, t7) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5, t6, t7)); return new Property7<>(name, a1, a2, a3, a4, a5, a6, a7, proposition); } } /** * Represents a logical for all quantor. * * @param 1st variable type of this for all quantor * @param 2nd variable type of this for all quantor * @param 3rd variable type of this for all quantor * @param 4th variable type of this for all quantor * @param 5th variable type of this for all quantor * @param 6th variable type of this for all quantor * @param 7th variable type of this for all quantor * @param 8th variable type of this for all quantor * @author Daniel Dietrich */ public static class ForAll8 { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; private final Arbitrary a6; private final Arbitrary a7; private final Arbitrary a8; ForAll8(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, Arbitrary a8) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; this.a6 = a6; this.a7 = a7; this.a8 = a8; } /** * Returns a checkable property that checks values of the 8 variables of this {@code ForAll} quantor. * * @param predicate A 8-ary predicate * @return a new {@code Property8} of 8 variables. */ public Property8 suchThat(CheckedFunction8 predicate) { final CheckedFunction8 proposition = (t1, t2, t3, t4, t5, t6, t7, t8) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5, t6, t7, t8)); return new Property8<>(name, a1, a2, a3, a4, a5, a6, a7, a8, proposition); } } /** * Represents a 1-ary checkable property. * * @author Daniel Dietrich */ public static class Property1 implements Checkable { private final String name; private final Arbitrary a1; private final CheckedFunction1 predicate; Property1(String name, Arbitrary a1, CheckedFunction1 predicate) { this.name = name; this.a1 = a1; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction1 postcondition) { final CheckedFunction1 implication = (t1) -> { final Condition precondition = predicate.apply(t1); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1)); } }; return new Property1<>(name, a1, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Represents a 2-ary checkable property. * * @author Daniel Dietrich */ public static class Property2 implements Checkable { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final CheckedFunction2 predicate; Property2(String name, Arbitrary a1, Arbitrary a2, CheckedFunction2 predicate) { this.name = name; this.a1 = a1; this.a2 = a2; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction2 postcondition) { final CheckedFunction2 implication = (t1, t2) -> { final Condition precondition = predicate.apply(t1, t2); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1, t2)); } }; return new Property2<>(name, a1, a2, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1, val2)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1, val2)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Represents a 3-ary checkable property. * * @author Daniel Dietrich */ public static class Property3 implements Checkable { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final CheckedFunction3 predicate; Property3(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, CheckedFunction3 predicate) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction3 postcondition) { final CheckedFunction3 implication = (t1, t2, t3) -> { final Condition precondition = predicate.apply(t1, t2, t3); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1, t2, t3)); } }; return new Property3<>(name, a1, a2, a3, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Represents a 4-ary checkable property. * * @author Daniel Dietrich */ public static class Property4 implements Checkable { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final CheckedFunction4 predicate; Property4(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, CheckedFunction4 predicate) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction4 postcondition) { final CheckedFunction4 implication = (t1, t2, t3, t4) -> { final Condition precondition = predicate.apply(t1, t2, t3, t4); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1, t2, t3, t4)); } }; return new Property4<>(name, a1, a2, a3, a4, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Represents a 5-ary checkable property. * * @author Daniel Dietrich */ public static class Property5 implements Checkable { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; private final CheckedFunction5 predicate; Property5(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, CheckedFunction5 predicate) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction5 postcondition) { final CheckedFunction5 implication = (t1, t2, t3, t4, t5) -> { final Condition precondition = predicate.apply(t1, t2, t3, t4, t5); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5)); } }; return new Property5<>(name, a1, a2, a3, a4, a5, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Represents a 6-ary checkable property. * * @author Daniel Dietrich */ public static class Property6 implements Checkable { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; private final Arbitrary a6; private final CheckedFunction6 predicate; Property6(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, CheckedFunction6 predicate) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; this.a6 = a6; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction6 postcondition) { final CheckedFunction6 implication = (t1, t2, t3, t4, t5, t6) -> { final Condition precondition = predicate.apply(t1, t2, t3, t4, t5, t6); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5, t6)); } }; return new Property6<>(name, a1, a2, a3, a4, a5, a6, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); final Gen gen6 = Try.of(() -> a6.apply(size)).recover(x -> { throw arbitraryError(6, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); final T6 val6 = Try.of(() -> gen6.apply(random)).recover(x -> { throw genError(6, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5, val6)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5, val6)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5, val6))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Represents a 7-ary checkable property. * * @author Daniel Dietrich */ public static class Property7 implements Checkable { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; private final Arbitrary a6; private final Arbitrary a7; private final CheckedFunction7 predicate; Property7(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, CheckedFunction7 predicate) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; this.a6 = a6; this.a7 = a7; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction7 postcondition) { final CheckedFunction7 implication = (t1, t2, t3, t4, t5, t6, t7) -> { final Condition precondition = predicate.apply(t1, t2, t3, t4, t5, t6, t7); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5, t6, t7)); } }; return new Property7<>(name, a1, a2, a3, a4, a5, a6, a7, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); final Gen gen6 = Try.of(() -> a6.apply(size)).recover(x -> { throw arbitraryError(6, size, x); }).get(); final Gen gen7 = Try.of(() -> a7.apply(size)).recover(x -> { throw arbitraryError(7, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); final T6 val6 = Try.of(() -> gen6.apply(random)).recover(x -> { throw genError(6, size, x); }).get(); final T7 val7 = Try.of(() -> gen7.apply(random)).recover(x -> { throw genError(7, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5, val6, val7)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5, val6, val7)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5, val6, val7))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Represents a 8-ary checkable property. * * @author Daniel Dietrich */ public static class Property8 implements Checkable { private final String name; private final Arbitrary a1; private final Arbitrary a2; private final Arbitrary a3; private final Arbitrary a4; private final Arbitrary a5; private final Arbitrary a6; private final Arbitrary a7; private final Arbitrary a8; private final CheckedFunction8 predicate; Property8(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, Arbitrary a8, CheckedFunction8 predicate) { this.name = name; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; this.a5 = a5; this.a6 = a6; this.a7 = a7; this.a8 = a8; this.predicate = predicate; } /** * Returns an implication which composes this Property as pre-condition and a given post-condition. * * @param postcondition The postcondition of this implication * @return A new Checkable implication */ public Checkable implies(CheckedFunction8 postcondition) { final CheckedFunction8 implication = (t1, t2, t3, t4, t5, t6, t7, t8) -> { final Condition precondition = predicate.apply(t1, t2, t3, t4, t5, t6, t7, t8); if (precondition.isFalse()) { return Condition.EX_FALSO_QUODLIBET; } else { return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5, t6, t7, t8)); } }; return new Property8<>(name, a1, a2, a3, a4, a5, a6, a7, a8, implication); } @Override public CheckResult check(Random random, int size, int tries) { Objects.requireNonNull(random, "random is null"); if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } final long startTime = System.currentTimeMillis(); try { final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); final Gen gen6 = Try.of(() -> a6.apply(size)).recover(x -> { throw arbitraryError(6, size, x); }).get(); final Gen gen7 = Try.of(() -> a7.apply(size)).recover(x -> { throw arbitraryError(7, size, x); }).get(); final Gen gen8 = Try.of(() -> a8.apply(size)).recover(x -> { throw arbitraryError(8, size, x); }).get(); boolean exhausted = true; for (int i = 1; i <= tries; i++) { try { final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); final T6 val6 = Try.of(() -> gen6.apply(random)).recover(x -> { throw genError(6, size, x); }).get(); final T7 val7 = Try.of(() -> gen7.apply(random)).recover(x -> { throw genError(7, size, x); }).get(); final T8 val8 = Try.of(() -> gen8.apply(random)).recover(x -> { throw genError(8, size, x); }).get(); try { final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5, val6, val7, val8)).recover(x -> { throw predicateError(x); }).get(); if (condition.precondition) { exhausted = false; if (!condition.postcondition) { logFalsified(name, i, System.currentTimeMillis() - startTime); return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5, val6, val7, val8)); } } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5, val6, val7, val8))); } } catch(CheckError err) { logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, i, err, Option.none()); } } logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); return new CheckResult.Satisfied(name, tries, exhausted); } catch(CheckError err) { logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); return new CheckResult.Erroneous(name, 0, err, Option.none()); } } } /** * Internally used to model conditions composed of pre- and post-condition. */ static class Condition { static final Condition EX_FALSO_QUODLIBET = new Condition(false, true); final boolean precondition; final boolean postcondition; Condition(boolean precondition, boolean postcondition) { this.precondition = precondition; this.postcondition = postcondition; } // ¬(p => q) ≡ ¬(¬p ∨ q) ≡ p ∧ ¬q boolean isFalse() { return precondition && !postcondition; } } /** * Internally used to provide more specific error messages. */ static class CheckError extends Error { private static final long serialVersionUID = 1L; CheckError(String message, Throwable cause) { super(message, cause); } } }vavr-0.10.0/vavr-test/src-gen/test/000077500000000000000000000000001342074374400170265ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/test/java/000077500000000000000000000000001342074374400177475ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/test/java/io/000077500000000000000000000000001342074374400203565ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/000077500000000000000000000000001342074374400213345ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/000077500000000000000000000000001342074374400223135ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck1Test.java000066400000000000000000000113461342074374400266660ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction1; import org.junit.Test; public class PropertyCheck1Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity1() { final Property.ForAll1 forAll = Property.def("test").forAll(null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity1() { final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); final CheckedFunction1 predicate = (o1) -> true; final Property.Property1 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty1() { final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); final CheckedFunction1 predicate = (o1) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty1() { final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); final CheckedFunction1 predicate = (o1) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty1() { final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); final CheckedFunction1 predicate = (o1) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty1ImplicationWithTruePrecondition() { final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); final CheckedFunction1 p1 = (o1) -> true; final CheckedFunction1 p2 = (o1) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty1ImplicationWithFalsePrecondition() { final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); final CheckedFunction1 p1 = (o1) -> false; final CheckedFunction1 p2 = (o1) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty1CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS) .suchThat((o1) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty1CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen) .suchThat((o1) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty1CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary) .suchThat((o1) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck2Test.java000066400000000000000000000117511342074374400266670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction2; import org.junit.Test; public class PropertyCheck2Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity2() { final Property.ForAll2 forAll = Property.def("test").forAll(null, null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity2() { final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); final CheckedFunction2 predicate = (o1, o2) -> true; final Property.Property2 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty2() { final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); final CheckedFunction2 predicate = (o1, o2) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty2() { final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); final CheckedFunction2 predicate = (o1, o2) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty2() { final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); final CheckedFunction2 predicate = (o1, o2) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty2ImplicationWithTruePrecondition() { final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); final CheckedFunction2 p1 = (o1, o2) -> true; final CheckedFunction2 p2 = (o1, o2) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty2ImplicationWithFalsePrecondition() { final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); final CheckedFunction2 p1 = (o1, o2) -> false; final CheckedFunction2 p2 = (o1, o2) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty2CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS, OBJECTS) .suchThat((o1, o2) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty2CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen, OBJECTS) .suchThat((o1, o2) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty2CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary, OBJECTS) .suchThat((o1, o2) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck3Test.java000066400000000000000000000123541342074374400266700ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction3; import org.junit.Test; public class PropertyCheck3Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity3() { final Property.ForAll3 forAll = Property.def("test").forAll(null, null, null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity3() { final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); final CheckedFunction3 predicate = (o1, o2, o3) -> true; final Property.Property3 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty3() { final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); final CheckedFunction3 predicate = (o1, o2, o3) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty3() { final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); final CheckedFunction3 predicate = (o1, o2, o3) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty3() { final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); final CheckedFunction3 predicate = (o1, o2, o3) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty3ImplicationWithTruePrecondition() { final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); final CheckedFunction3 p1 = (o1, o2, o3) -> true; final CheckedFunction3 p2 = (o1, o2, o3) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty3ImplicationWithFalsePrecondition() { final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); final CheckedFunction3 p1 = (o1, o2, o3) -> false; final CheckedFunction3 p2 = (o1, o2, o3) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty3CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty3CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen, OBJECTS, OBJECTS) .suchThat((o1, o2, o3) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty3CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary, OBJECTS, OBJECTS) .suchThat((o1, o2, o3) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck4Test.java000066400000000000000000000127571342074374400267000ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction4; import org.junit.Test; public class PropertyCheck4Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity4() { final Property.ForAll4 forAll = Property.def("test").forAll(null, null, null, null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity4() { final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction4 predicate = (o1, o2, o3, o4) -> true; final Property.Property4 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty4() { final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction4 predicate = (o1, o2, o3, o4) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty4() { final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction4 predicate = (o1, o2, o3, o4) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty4() { final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction4 predicate = (o1, o2, o3, o4) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty4ImplicationWithTruePrecondition() { final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction4 p1 = (o1, o2, o3, o4) -> true; final CheckedFunction4 p2 = (o1, o2, o3, o4) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty4ImplicationWithFalsePrecondition() { final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction4 p1 = (o1, o2, o3, o4) -> false; final CheckedFunction4 p2 = (o1, o2, o3, o4) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty4CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty4CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty4CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck5Test.java000066400000000000000000000133621342074374400266720ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction5; import org.junit.Test; public class PropertyCheck5Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity5() { final Property.ForAll5 forAll = Property.def("test").forAll(null, null, null, null, null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity5() { final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> true; final Property.Property5 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty5() { final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty5() { final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty5() { final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty5ImplicationWithTruePrecondition() { final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction5 p1 = (o1, o2, o3, o4, o5) -> true; final CheckedFunction5 p2 = (o1, o2, o3, o4, o5) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty5ImplicationWithFalsePrecondition() { final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction5 p1 = (o1, o2, o3, o4, o5) -> false; final CheckedFunction5 p2 = (o1, o2, o3, o4, o5) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty5CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty5CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty5CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck6Test.java000066400000000000000000000137651342074374400267020ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction6; import org.junit.Test; public class PropertyCheck6Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity6() { final Property.ForAll6 forAll = Property.def("test").forAll(null, null, null, null, null, null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity6() { final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> true; final Property.Property6 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty6() { final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty6() { final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty6() { final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty6ImplicationWithTruePrecondition() { final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction6 p1 = (o1, o2, o3, o4, o5, o6) -> true; final CheckedFunction6 p2 = (o1, o2, o3, o4, o5, o6) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty6ImplicationWithFalsePrecondition() { final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction6 p1 = (o1, o2, o3, o4, o5, o6) -> false; final CheckedFunction6 p2 = (o1, o2, o3, o4, o5, o6) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty6CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty6CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty6CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck7Test.java000066400000000000000000000143701342074374400266740ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction7; import org.junit.Test; public class PropertyCheck7Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity7() { final Property.ForAll7 forAll = Property.def("test").forAll(null, null, null, null, null, null, null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity7() { final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> true; final Property.Property7 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty7() { final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty7() { final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty7() { final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty7ImplicationWithTruePrecondition() { final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction7 p1 = (o1, o2, o3, o4, o5, o6, o7) -> true; final CheckedFunction7 p2 = (o1, o2, o3, o4, o5, o6, o7) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty7ImplicationWithFalsePrecondition() { final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction7 p1 = (o1, o2, o3, o4, o5, o6, o7) -> false; final CheckedFunction7 p2 = (o1, o2, o3, o4, o5, o6, o7) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty7CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6, o7) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty7CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6, o7) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty7CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6, o7) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck8Test.java000066400000000000000000000147731342074374400267040ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction8; import org.junit.Test; public class PropertyCheck8Test { static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test public void shouldApplyForAllOfArity8() { final Property.ForAll8 forAll = Property.def("test").forAll(null, null, null, null, null, null, null, null); assertThat(forAll).isNotNull(); } @Test public void shouldApplySuchThatOfArity8() { final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; final Property.Property8 suchThat = forAll.suchThat(predicate); assertThat(suchThat).isNotNull(); } @Test public void shouldCheckTrueProperty8() { final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckFalseProperty8() { final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> false; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isFalsified()).isTrue(); } @Test public void shouldCheckErroneousProperty8() { final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = forAll.suchThat(predicate).check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldCheckProperty8ImplicationWithTruePrecondition() { final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction8 p1 = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; final CheckedFunction8 p2 = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckProperty8ImplicationWithFalsePrecondition() { final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); final CheckedFunction8 p1 = (o1, o2, o3, o4, o5, o6, o7, o8) -> false; final CheckedFunction8 p2 = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; final CheckResult result = forAll.suchThat(p1).implies(p2).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnProperty8CheckGivenNegativeTries() { Property.def("test") .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6, o7, o8) -> true) .check(Checkable.RNG.get(), 0, -1); } @Test public void shouldReturnErroneousProperty8CheckResultIfGenFails() { final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test") .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6, o7, o8) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } @Test public void shouldReturnErroneousProperty8CheckResultIfArbitraryFails() { final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test") .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) .suchThat((o1, o2, o3, o4, o5, o6, o7, o8) -> true) .check(); assertThat(result.isErroneous()).isTrue(); } }vavr-0.10.0/vavr-test/src-gen/test/java/io/vavr/test/PropertyTest.java000066400000000000000000000231111342074374400256400ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.CheckedFunction1; import io.vavr.Tuple; import io.vavr.collection.List; import java.util.Random; import org.junit.Test; public class PropertyTest { static CheckedFunction1 tautology() { return any -> true; } static CheckedFunction1 falsum() { return any -> false; } static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); @Test(expected = NullPointerException.class) public void shouldThrowWhenPropertyNameIsNull() { Property.def(null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenPropertyNameIsEmpty() { Property.def(""); } // -- Property.check methods @Test public void shouldCheckUsingDefaultConfiguration() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckGivenSizeAndTries() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, 0); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnCheckGivenNegativeTries() { Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, -1); } @Test public void shouldCheckGivenRandomAndSizeAndTries() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(new Random(), 0, 0); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } // -- satisfaction @Test public void shouldCheckPythagoras() { final Arbitrary real = n -> Gen.choose(0, (double) n).filter(d -> d > .0d); // (∀a,b ∈ ℝ+ ∃c ∈ ℝ+ : a²+b²=c²) ≡ (∀a,b ∈ ℝ+ : √(a²+b²) ∈ ℝ+) final Checkable property = Property.def("test").forAll(real, real).suchThat((a, b) -> Math.sqrt(a * a + b * b) > .0d); final CheckResult result = property.check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } @Test public void shouldCheckZipAndThenUnzipIsIdempotentForListsOfSameLength() { // ∀is,ss: length(is) = length(ss) → unzip(zip(is, ss)) = (is, ss) final Arbitrary> ints = Arbitrary.list(size -> Gen.choose(0, size)); final Arbitrary> strings = Arbitrary.list( Arbitrary.string( Gen.frequency( Tuple.of(1, Gen.choose('A', 'Z')), Tuple.of(1, Gen.choose('a', 'z')), Tuple.of(1, Gen.choose('0', '9')) ))); final CheckResult result = Property.def("test") .forAll(ints, strings) .suchThat((is, ss) -> is.length() == ss.length()) .implies((is, ss) -> is.zip(ss).unzip(t -> t).equals(Tuple.of(is, ss))) .check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isFalse(); } // -- exhausting @Test public void shouldRecognizeExhaustedParameters() { final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(falsum()).implies(tautology()).check(); assertThat(result.isSatisfied()).isTrue(); assertThat(result.isExhausted()).isTrue(); } // -- falsification @Test public void shouldFalsifyFalseProperty() { final Arbitrary ones = n -> random -> 1; final CheckResult result = Property.def("test").forAll(ones).suchThat(one -> one == 2).check(); assertThat(result.isFalsified()).isTrue(); assertThat(result.isExhausted()).isFalse(); assertThat(result.count()).isEqualTo(1); } // -- error detection @Test public void shouldRecognizeArbitraryError() { final Arbitrary arbitrary = n -> { throw new RuntimeException("yay! (this is a negative test)"); }; final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); assertThat(result.isErroneous()).isTrue(); assertThat(result.isExhausted()).isFalse(); assertThat(result.count()).isEqualTo(0); assertThat(result.sample().isEmpty()).isTrue(); } @Test public void shouldRecognizeGenError() { final Arbitrary arbitrary = Gen.fail("yay! (this is a negative test)").arbitrary(); final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); assertThat(result.isErroneous()).isTrue(); assertThat(result.isExhausted()).isFalse(); assertThat(result.count()).isEqualTo(1); assertThat(result.sample().isEmpty()).isTrue(); } @Test public void shouldRecognizePropertyError() { final Arbitrary a1 = n -> random -> 1; final Arbitrary a2 = n -> random -> 2; final CheckResult result = Property.def("test").forAll(a1, a2).suchThat((a, b) -> { throw new RuntimeException("yay! (this is a negative test)"); }).check(); assertThat(result.isErroneous()).isTrue(); assertThat(result.isExhausted()).isFalse(); assertThat(result.count()).isEqualTo(1); assertThat(result.sample().isDefined()).isTrue(); assertThat(result.sample().get()).isEqualTo(Tuple.of(1, 2)); } // -- Property.and tests @Test public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.and(p2).check(); assertThat(result.isSatisfied()).isTrue(); } @Test public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.and(p2).check(); assertThat(result.isSatisfied()).isFalse(); } @Test public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.and(p2).check(); assertThat(result.isSatisfied()).isFalse(); } @Test public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.and(p2).check(); assertThat(result.isSatisfied()).isFalse(); } // -- Property.or tests @Test public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.or(p2).check(); assertThat(result.isSatisfied()).isTrue(); } @Test public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.or(p2).check(); assertThat(result.isSatisfied()).isTrue(); } @Test public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); final CheckResult result = p1.or(p2).check(); assertThat(result.isSatisfied()).isTrue(); } @Test public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); final CheckResult result = p1.or(p2).check(); assertThat(result.isSatisfied()).isFalse(); } }vavr-0.10.0/vavr-test/src/000077500000000000000000000000001342074374400153005ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/main/000077500000000000000000000000001342074374400162245ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/main/java/000077500000000000000000000000001342074374400171455ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/main/java/io/000077500000000000000000000000001342074374400175545ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/main/java/io/vavr/000077500000000000000000000000001342074374400205325ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/main/java/io/vavr/test/000077500000000000000000000000001342074374400215115ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/main/java/io/vavr/test/Arbitrary.java000066400000000000000000000264201342074374400243170ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import io.vavr.collection.List; import io.vavr.collection.Stream; import java.time.Duration; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.Comparator; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; /** * Represents an arbitrary object of type T. * * @param The type of the arbitrary object. * @author Daniel Dietrich */ @FunctionalInterface public interface Arbitrary { /** * Returns a generator for objects of type T. * Use {@link Gen#map(Function)} and {@link Gen#flatMap(Function)} to * combine object generators. *

* Example: *

     * 
     * // represents arbitrary binary trees of a certain depth n
     * final class ArbitraryTree implements Arbitrary<BinaryTree<Integer>> {
     *     @Override
     *     public Gen<BinaryTree<Integer>> apply(int n) {
     *         return Gen.choose(-1000, 1000).flatMap(value -> {
     *                  if (n == 0) {
     *                      return Gen.of(BinaryTree.leaf(value));
     *                  } else {
     *                      return Gen.frequency(
     *                              Tuple.of(1, Gen.of(BinaryTree.leaf(value))),
     *                              Tuple.of(4, Gen.of(BinaryTree.branch(apply(n / 2).get(), value, apply(n / 2).get())))
     *                      );
     *                  }
     *         });
     *     }
     * }
     *
     * // tree generator with a size hint of 10
     * final Gen<BinaryTree<Integer>> treeGen = new ArbitraryTree().apply(10);
     *
     * // stream sum of tree node values to console for 100 arbitrary trees
     * Stream.of(() -> treeGen.apply(RNG.get())).map(Tree::sum).take(100).stdout();
     * 
     * 
* * @param size A (not necessarily positive) size parameter which may be interpreted individually and is constant for all arbitrary objects regarding one property check. * @return A generator for objects of type T. */ Gen apply(int size); /** * Returns an Arbitrary based on this Arbitrary which produces unique values. * * @return A new generator */ default Arbitrary distinct() { return distinctBy(Function.identity()); } /** * Returns an Arbitrary based on this Arbitrary which produces unique values based on the given comparator. * * @param comparator A comparator * @return A new generator */ default Arbitrary distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final java.util.Set seen = new java.util.TreeSet<>(comparator); return filter(seen::add); } /** * Returns an Arbitrary based on this Arbitrary which produces unique values based on the given function. * * @param key type * @param keyExtractor A function * @return A new generator */ default Arbitrary distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); final java.util.Set seen = new java.util.HashSet<>(); return filter(t -> seen.add(keyExtractor.apply(t))); } /** * Returns an Arbitrary based on this Arbitrary which produces values that fulfill the given predicate. * * @param predicate A predicate * @return A new generator */ default Arbitrary filter(Predicate predicate) { return size -> apply(size).filter(predicate); } /** * Maps arbitrary objects T to arbitrary object U. * * @param mapper A function that maps arbitrary Ts to arbitrary Us given a mapper. * @param New type of arbitrary objects * @return A new Arbitrary */ default Arbitrary flatMap(Function> mapper) { return size -> { final Gen gen = apply(size); return random -> mapper.apply(gen.apply(random)).apply(size).apply(random); }; } /** * Intersperses values from this arbitrary instance with those of another. * * @param other another T arbitrary to accept values from. * @return A new T arbitrary */ default Arbitrary intersperse(Arbitrary other) { Objects.requireNonNull(other, "other is null"); return size -> this.apply(size).intersperse(other.apply(size)); } /** * Maps arbitrary objects T to arbitrary object U. * * @param mapper A function that maps an arbitrary T to an object of type U. * @param Type of the mapped object * @return A new generator */ default Arbitrary map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return n -> { final Gen generator = apply(n); return random -> mapper.apply(generator.apply(random)); }; } default Arbitrary peek(Consumer action) { return size -> apply(size).peek(action); } /** * Transforms this {@code Arbitrary}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } /** * Generates an arbitrary value from a fixed set of values * * @param values A fixed set of values * @param Type of generator value * @return A new generator */ @SafeVarargs @SuppressWarnings("varargs") static Arbitrary of(U... values) { return ofAll(Gen.choose(values)); } /** * Generates an arbitrary value from a given generator * * @param generator A generator to produce arbitrary values * @param Type of generator value * @return A new generator */ static Arbitrary ofAll(Gen generator) { return size -> generator; } /** * Generates arbitrary integer values. * * @return A new Arbitrary of Integer */ static Arbitrary integer() { return size -> Gen.choose(-size, size); } /** * Generates arbitrary {@link LocalDateTime}s with {@link LocalDateTime#now()} as {@code median} and * {@link ChronoUnit#DAYS} as chronological unit. * * @return A new Arbitrary of LocalDateTime * @see #localDateTime(LocalDateTime, ChronoUnit) */ static Arbitrary localDateTime() { return localDateTime(ChronoUnit.DAYS); } /** * Generates arbitrary {@link LocalDateTime}s with {@link LocalDateTime#now()} as {@code median}. * * @param unit Chronological unit of {@code size} * @return A new Arbitrary of LocalDateTime * @see #localDateTime(LocalDateTime, ChronoUnit) */ static Arbitrary localDateTime(ChronoUnit unit) { return localDateTime(LocalDateTime.now(), unit); } /** * Generates arbitrary {@link LocalDateTime}s. All generated values are drawn from a range with {@code median} * as center and {@code median +/- size} as included boundaries. {@code unit} defines the chronological unit * of {@code size}. * *

* Example: *

     * 
     * Arbitrary.localDateTime(LocalDateTime.now(), ChronoUnit.YEARS);
     * 
     * 
* * @param median Center of the LocalDateTime range * @param unit Chronological unit of {@code size} * @return A new Arbitrary of LocalDateTime */ static Arbitrary localDateTime(LocalDateTime median, ChronoUnit unit) { Objects.requireNonNull(median, "median is null"); Objects.requireNonNull(unit, "unit is null"); return size -> { if(size == 0) { return Gen.of(median); } final LocalDateTime start = median.minus(size, unit); final LocalDateTime end = median.plus(size, unit); final long duration = Duration.between(start, end).toMillis(); final Gen from = Gen.choose(0, duration); return random -> start.plus(from.apply(random), ChronoUnit.MILLIS); }; } /** * Generates arbitrary strings based on a given alphabet represented by gen. *

* Example: *

     * 
     * Arbitrary.string(
     *     Gen.frequency(
     *         Tuple.of(1, Gen.choose('A', 'Z')),
     *         Tuple.of(1, Gen.choose('a', 'z')),
     *         Tuple.of(1, Gen.choose('0', '9'))));
     * 
     * 
* * @param gen A character generator * @return a new Arbitrary of String */ static Arbitrary string(Gen gen) { return size -> random -> Gen.choose(0, size).map(i -> { final char[] chars = new char[i]; for (int j = 0; j < i; j++) { chars[j] = gen.apply(random); } return new String(chars); }).apply(random); } /** * Generates arbitrary lists based on a given element generator arbitraryT. *

* Example: *

     * 
     * Arbitrary.list(Arbitrary.integer());
     * 
     * 
* * @param arbitraryT Arbitrary elements of type T * @param Component type of the List * @return a new Arbitrary of List<T> */ static Arbitrary> list(Arbitrary arbitraryT) { return size -> { final Gen genT = arbitraryT.apply(size); return random -> List.fill(Gen.choose(0, size).apply(random), () -> genT.apply(random)); }; } /** * Generates arbitrary streams based on a given element generator arbitraryT. *

* Example: *

     * 
     * Arbitrary.stream(Arbitrary.integer());
     * 
     * 
* * @param arbitraryT Arbitrary elements of type T * @param Component type of the Stream * @return a new Arbitrary of Stream<T> */ static Arbitrary> stream(Arbitrary arbitraryT) { return size -> { final Gen genT = arbitraryT.apply(size); return random -> Stream.continually(() -> genT.apply(random)) .take(Gen.choose(0, size).apply(random)); }; } } vavr-0.10.0/vavr-test/src/main/java/io/vavr/test/CheckResult.java000066400000000000000000000265171342074374400246030ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import io.vavr.Tuple; import io.vavr.control.Option; import java.io.Serializable; import java.util.Objects; /** * Represents the result of a property check which is * *
    *
  • {@code Satisfied}, if all tests satisfied the given property
  • *
  • {@code Falsified}, if a counter-example could be discovered that falsified the given property
  • *
  • {@code Erroneous}, if an exception occurred executing the property check
  • *
* * Please note that a {@code Satisfied} property check may be {@code Exhausted}, if the property is an implication * and no sample could be found that satisfied the pre-condition. In this case the post-condition is satisfied by * definition (see ex falso quodlibet). * * @author Daniel Dietrich */ public interface CheckResult { /** * If this check result is satisfied as specified above. * * @return true, if this check result is satisfied, false otherwise */ boolean isSatisfied(); /** * If this check result is falsified as specified above. * * @return true, if this check result is falsified, false otherwise */ boolean isFalsified(); /** * If this check result is erroneous as specified above. * * @return true, if this check result is erroneous, false otherwise */ boolean isErroneous(); /** * If this check result is exhausted as specified above. * * @return true, if this check result is exhausted, false otherwise */ boolean isExhausted(); /** * The name of the checked property this result refers to. * * @return a property name */ String propertyName(); /** * The number of checks performed using random generated input data. * * @return the number of checks performed */ int count(); /** * An optional sample which falsified the property or which lead to an error. * * @return an optional sample */ Option sample(); /** * An optional error. * * @return an optional error */ Option error(); /** * Asserts that this CheckResult is satisfied. * * @throws AssertionError if this CheckResult is not satisfied. */ default void assertIsSatisfied() { if (!isSatisfied()) { throw new AssertionError("Expected satisfied check result but was " + this); } } /** * Asserts that this CheckResult is satisfied with a given exhausted state. * * @param exhausted The exhausted state to be checked in the case of a satisfied CheckResult. * @throws AssertionError if this CheckResult is not satisfied or the exhausted state does not match. */ default void assertIsSatisfiedWithExhaustion(boolean exhausted) { if (!isSatisfied()) { throw new AssertionError("Expected satisfied check result but was " + this); } else if (isExhausted() != exhausted) { throw new AssertionError("Expected satisfied check result to be " + (exhausted ? "" : "not ") + "exhausted but was: " + this); } } /** * Asserts that this CheckResult is falsified. * * @throws AssertionError if this CheckResult is not falsified. */ default void assertIsFalsified() { if (!isFalsified()) { throw new AssertionError("Expected falsified check result but was " + this); } } /** * Asserts that this CheckResult is erroneous. * * @throws AssertionError if this CheckResult is not erroneous. */ default void assertIsErroneous() { if (!isErroneous()) { throw new AssertionError("Expected erroneous check result but was " + this); } } /** * Represents a satisfied property check. */ class Satisfied implements CheckResult, Serializable { private static final long serialVersionUID = 1L; private final String propertyName; private final int count; private final boolean exhausted; Satisfied(String propertyName, int count, boolean exhausted) { this.propertyName = propertyName; this.count = count; this.exhausted = exhausted; } @Override public boolean isSatisfied() { return true; } @Override public boolean isFalsified() { return false; } @Override public boolean isErroneous() { return false; } @Override public boolean isExhausted() { return exhausted; } @Override public String propertyName() { return propertyName; } @Override public int count() { return count; } @Override public Option sample() { return Option.none(); } @Override public Option error() { return Option.none(); } @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof Satisfied) { final Satisfied that = (Satisfied) o; return Objects.equals(this.propertyName, that.propertyName) && this.count == that.count && this.exhausted == that.exhausted; } else { return false; } } @Override public int hashCode() { return Objects.hash(propertyName, count, exhausted); } @Override public String toString() { return String.format("%s(propertyName = %s, count = %s, exhausted = %s)", getClass().getSimpleName(), propertyName, count, exhausted); } } /** * Represents a falsified property check. */ class Falsified implements CheckResult, Serializable { private static final long serialVersionUID = 1L; private final String propertyName; private final int count; private final Tuple sample; Falsified(String propertyName, int count, Tuple sample) { this.propertyName = propertyName; this.count = count; this.sample = sample; } @Override public boolean isSatisfied() { return false; } @Override public boolean isFalsified() { return true; } @Override public boolean isErroneous() { return false; } @Override public boolean isExhausted() { return false; } @Override public String propertyName() { return propertyName; } @Override public int count() { return count; } @Override public Option sample() { return Option.some(sample); } @Override public Option error() { return Option.none(); } @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof Falsified) { final Falsified that = (Falsified) o; return Objects.equals(this.propertyName, that.propertyName) && this.count == that.count && Objects.equals(this.sample, that.sample); } else { return false; } } @Override public int hashCode() { return Objects.hash(propertyName, count, sample); } @Override public String toString() { return String.format("%s(propertyName = %s, count = %s, sample = %s)", getClass().getSimpleName(), propertyName, count, sample); } } /** * Represents an erroneous property check. */ class Erroneous implements CheckResult, Serializable { private static final long serialVersionUID = 1L; private final String propertyName; private final int count; private final Error error; private final Option sample; Erroneous(String propertyName, int count, Error error, Option sample) { this.propertyName = propertyName; this.count = count; this.error = error; this.sample = sample; } @Override public boolean isSatisfied() { return false; } @Override public boolean isFalsified() { return false; } @Override public boolean isErroneous() { return true; } @Override public boolean isExhausted() { return false; } @Override public String propertyName() { return propertyName; } @Override public int count() { return count; } @Override public Option sample() { return sample; } @Override public Option error() { return Option.some(error); } @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof Erroneous) { final Erroneous that = (Erroneous) o; return Objects.equals(this.propertyName, that.propertyName) && this.count == that.count && deepEquals(this.error, that.error) && Objects.equals(this.sample, that.sample); } else { return false; } } boolean deepEquals(Throwable t1, Throwable t2) { return (t1 == null && t2 == null) || ( t1 != null && t2 != null && Objects.equals(t1.getMessage(), t2.getMessage()) && deepEquals(t1.getCause(), t2.getCause()) ); } @Override public int hashCode() { return Objects.hash(propertyName, count, deepHashCode(error), sample); } int deepHashCode(Throwable t) { if (t == null) { return 0; } else { return Objects.hash(t.getMessage(), deepHashCode(t.getCause())); } } @Override public String toString() { return String.format("%s(propertyName = %s, count = %s, error = %s, sample = %s)", getClass().getSimpleName(), propertyName, count, error.getMessage(), sample); } } } vavr-0.10.0/vavr-test/src/main/java/io/vavr/test/Checkable.java000066400000000000000000000074371342074374400242300ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Supplier; /** * Interface for checkable properties, allowing composition via {@linkplain #and(Checkable)} and {@linkplain #or(Checkable)}. * * @author Daniel Dietrich */ @FunctionalInterface public interface Checkable { /** * A thread-safe, equally distributed random number generator. */ Supplier RNG = ThreadLocalRandom::current; /** * Default size hint for generators: 100 */ int DEFAULT_SIZE = 100; /** * Default tries to check a property: 1000 */ int DEFAULT_TRIES = 1000; /** * Checks this property. * * @param randomNumberGenerator An implementation of {@link java.util.Random}. * @param size A (not necessarily positive) size hint. * @param tries A non-negative number of tries to falsify the given property. * @return A {@linkplain CheckResult} */ CheckResult check(Random randomNumberGenerator, int size, int tries); /** * Checks this property using the default random number generator {@link #RNG}. * * @param size A (not necessarily positive) size hint. * @param tries A non-negative number of tries to falsify the given property. * @return A {@linkplain CheckResult} */ default CheckResult check(int size, int tries) { if (tries < 0) { throw new IllegalArgumentException("tries < 0"); } return check(RNG.get(), size, tries); } /** * Checks this property using the default random number generator {@link #RNG} by calling {@link #check(int, int)}, * where size is {@link #DEFAULT_SIZE} and tries is {@link #DEFAULT_TRIES}. * * @return A {@linkplain CheckResult} */ default CheckResult check() { return check(RNG.get(), DEFAULT_SIZE, DEFAULT_TRIES); } /** * Returns a new Checkable which is satisfied if this Checkable and the given checkable are satisfied. *

* First this Checkable is checked. * * @param checkable A Checkable * @return A new Checkable */ default Checkable and(Checkable checkable) { return (rng, size, tries) -> { final CheckResult result = check(rng, size, tries); if (result.isSatisfied()) { return checkable.check(rng, size, tries); } else { return result; } }; } /** * Returns a new Checkable which is satisfied if this Checkable or the given checkable are satisfied. *

* First this Checkable is checked. * * @param checkable A Checkable * @return A new Checkable */ default Checkable or(Checkable checkable) { return (rng, size, tries) -> { final CheckResult result = check(rng, size, tries); if (result.isSatisfied()) { return result; } else { return checkable.check(rng, size, tries); } }; } } vavr-0.10.0/vavr-test/src/main/java/io/vavr/test/Gen.java000066400000000000000000000365611342074374400231000ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import io.vavr.Tuple2; import io.vavr.collection.Iterator; import io.vavr.collection.List; import io.vavr.collection.Stream; import io.vavr.collection.Vector; import java.util.Objects; import java.util.Random; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; /** * Generators are the building blocks for providing arbitrary objects. *

* To ease the creation of Arbitraries, Gen is a FunctionalInterface which extends {@code Function}. *

* Gen objects are obtained via one of the methods {@code choose}, {@code fail}, {@code frequency}, {@code of} and * {@code oneOf}. *

* Given Gen objects may be transformed using one of the methods {@code filter}, {@code map} and {@code flatMap}. *

* A simple way to obtain an Arbitrary of a Gen is to call {@linkplain Gen#arbitrary()}. * This will ignore the size hint of Arbitrary. * * @param type of generated objects * @author Daniel Dietrich * @see Arbitrary */ @FunctionalInterface public interface Gen { /** * Functional interface of this generator. * * @param random a random number generator * @return A generated value of type T. */ T apply(Random random); /** * A generator which constantly returns t. * * @param t A value. * @param Type of t. * @return A new T generator */ static Gen of(T t) { return ignored -> t; } static Gen of(T seed, Function next) { Objects.requireNonNull(next, "next is null"); final Iterator iterator = Iterator.iterate(seed, next); return ignored -> iterator.next(); } /** * Chooses an int between min and max, bounds inclusive and numbers distributed according to the distribution of * the underlying random number generator. *

* Note: min and max are internally swapped if min > max. * * @param min lower bound * @param max upper bound * @return A new int generator */ static Gen choose(int min, int max) { if (min == max) { return ignored -> min; } else { final int _min = Math.min(min, max); final int _max = Math.max(min, max); return rng -> rng.nextInt(Math.abs(_max - _min) + 1) + _min; } } /** * Chooses a long between min and max, bounds inclusive and numbers distributed according to the distribution of * the underlying random number generator. *

* Note: min and max are internally swapped if min > max. * * @param min lower bound * @param max upper bound * @return A new long generator */ static Gen choose(long min, long max) { if (min == max) { return ignored -> min; } else { return random -> { final double d = random.nextDouble(); final long _min = Math.min(min, max); final long _max = Math.max(min, max); return (long) ((d * _max) + ((1.0 - d) * _min) + d); }; } } /** * Chooses a double between min and max, bounds inclusive and numbers distributed according to the distribution * of the underlying random number generator. *

* Note: min and max are internally swapped if min > max. * * @param min lower bound * @param max upper bound * @return A new double generator * @throws IllegalArgumentException if min or max is infinite, min or max is not a number (NaN) */ static Gen choose(double min, double max) { if (Double.isInfinite(min)) { throw new IllegalArgumentException("min is infinite"); } if (Double.isInfinite(max)) { throw new IllegalArgumentException("max is infinite"); } if (Double.isNaN(min)) { throw new IllegalArgumentException("min is not a number (NaN)"); } if (Double.isNaN(max)) { throw new IllegalArgumentException("max is not a number (NaN)"); } if (min == max) { return ignored -> min; } else { return random -> { final double d = random.nextDouble(); final double _min = Math.min(min, max); final double _max = Math.max(min, max); return d * _max + (1.0 - d) * _min; }; } } /** * Chooses a char between min and max, bounds inclusive and chars distributed according to the underlying random * number generator. *

* Note: min and max are internally swapped if min > max. * * @param min lower bound * @param max upper bound * @return A new char generator */ static Gen choose(char min, char max) { if (min == max) { return ignored -> min; } else { return Gen.choose((int) min, (int) max).map(i -> (char) (int) i); } } /** * Chooses a char from all chars in the array * * @param characters array with the characters to choose from * @return A new array generator */ static Gen choose(char... characters) { Objects.requireNonNull(characters, "characters is null"); final Character[] validCharacters = List.ofAll(characters).toJavaArray(Character[]::new); return choose(validCharacters); } /** * Chooses an enum value from all the enum constants defined in the enumerated type. * * @param clazz Enum class * @param type of enum constants * @return A new enum generator */ static > Gen choose(Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return Gen.choose(clazz.getEnumConstants()); } /** * Chooses a value from all values in the array. * * @param values array with the values to choose from * @param value type * @return A new array generator */ @SafeVarargs @SuppressWarnings("varargs") static Gen choose(T... values) { Objects.requireNonNull(values, "values is null"); if (values.length == 0) { return Gen.fail("Empty array"); } else { return Gen.choose(0, values.length - 1).map(i -> values[i]); } } /** * Chooses a value from all values in the iterable * * @param values iterable with the values to choose from. * @param value type * @return A new iterable generator */ static Gen choose(Iterable values) { Objects.requireNonNull(values, "values is null"); final Iterator iterator = Iterator.ofAll(values); if (!iterator.hasNext()) { throw new IllegalArgumentException("Empty iterable"); } @SuppressWarnings("unchecked") final T[] array = (T[]) iterator.toJavaArray(); return choose(array); } /** * A failing generator which throws a RuntimeException("failed"). * * @param Type of values theoretically generated. * @return A new generator which always fails with the message "failed" */ static Gen fail() { return fail("failed"); } /** * A failing generator which throws a RuntimeException. * * @param message Message thrown. * @param Type of values theoretically generated. * @return A new generator which always fails with the given message */ static Gen fail(String message) { return ignored -> { throw new RuntimeException(message); }; } /** * Chooses one of the given generators according to their frequency. * Only generators with positive frequencies are used in returned * generator. * * @param generators A non-empty array of Tuples (frequency, generator) * @param Type to be generated * @return A new T generator * @throws java.lang.NullPointerException if generators is null * @throws java.lang.IllegalArgumentException if generators doesn't contain any generator with positive frequency */ @SuppressWarnings("varargs") @SafeVarargs static Gen frequency(Tuple2>... generators) { Objects.requireNonNull(generators, "generators is null"); if (generators.length == 0) { throw new IllegalArgumentException("generators is empty"); } final Iterable>> iterable = Stream.of(generators); return frequency(iterable); } /** * Chooses one of the given generators according to their frequency. * Only generators with positive frequencies ares used in returned * generator. * * @param generators A non-empty traversable of Tuples (frequency, generator) * @param Type to be generated * @return A new T generator * @throws java.lang.NullPointerException if generators is null * @throws java.lang.IllegalArgumentException if generators doesn't contain any generator with positive frequency */ static Gen frequency(Iterable>> generators) { Objects.requireNonNull(generators, "generators is null"); final Vector>> filtered = Iterator.ofAll(generators) .filter(t -> t._1() > 0).toVector(); if (filtered.isEmpty()) { throw new IllegalArgumentException("no generator with positive weight"); } final int size = filtered.map(t -> t._1).sum().intValue(); return choose(1, size).flatMap(n -> GenModule.frequency(n, filtered.iterator())); } /** * Intersperse values from this generator instance with those of another. * * @param other another T generator to accept values from. * @return A new T generator */ default Gen intersperse(Gen other) { final Iterator> iter = Iterator.continually(this).intersperse(other); return random -> iter.get().apply(random); } /** * Randomly chooses one of the given generators. * * @param generators A non-empty array of generators * @param Type to be generated * @return A new T generator * @throws java.lang.NullPointerException if generators is null * @throws java.lang.IllegalArgumentException if generators is empty */ @SafeVarargs static Gen oneOf(Gen... generators) { Objects.requireNonNull(generators, "generators is null"); if (generators.length == 0) { throw new IllegalArgumentException("generators is empty"); } return choose(0, generators.length - 1).flatMap(i -> generators[i]); } /** * Randomly chooses one of the given generators. * * @param generators A non-empty Iterable of generators * @param Type to be generated * @return A new T generator * @throws java.lang.NullPointerException if generators is null * @throws java.lang.IllegalArgumentException if generators is empty */ static Gen oneOf(Iterable> generators) { Objects.requireNonNull(generators, "generators is null"); final Stream> stream = Stream.ofAll(generators); if (stream.isEmpty()) { throw new IllegalArgumentException("generators is empty"); } @SuppressWarnings("unchecked") final Gen[] array = stream.toJavaArray(Gen[]::new); return oneOf(array); } /** * Converts this Gen to an Arbitrary * * @return An arbitrary which returns this generator regardless of the provided size hint n */ default Arbitrary arbitrary() { return n -> this; } /** * Returns a generator based on this generator which produces values that fulfill the given predicate. * * @param predicate A predicate * @return A new generator */ default Gen filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return random -> { int count = 0; final int filterThreshold = Integer.MAX_VALUE; T t; while (!predicate.test(t = apply(random))) { // it may take a looooooong time to hit this condition! if (++count == filterThreshold) { throw new IllegalStateException("empty filter"); } } return t; }; } /** * Maps generated Ts to Us. * * @param mapper A function that maps a generated T to a new generator which generates objects of type U. * @param Type of generated objects of the new generator * @return A new generator */ default Gen flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return random -> mapper.apply(apply(random)).apply(random); } /** * Maps generated Ts to Us. * * @param mapper A function that maps a generated T to an object of type U. * @param Type of the mapped object * @return A new generator */ default Gen map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return random -> mapper.apply(apply(random)); } default Gen peek(Consumer action) { return random -> { final T t = apply(random); action.accept(t); return t; }; } /** * Transforms this {@code Gen}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } } interface GenModule { /** * Chooses a Gen according to the given frequencies. * * @param n a random value between 0 and sum(frequencies) - 1 * @param iter a non-empty Iterator of (frequency, Gen) pairs * @param type of generated values * @return A value generator, choosen according to the given frequencies and the underlying n */ static Gen frequency(int n, java.util.Iterator>> iter) { do { final Tuple2> freqGen = iter.next(); final int k = freqGen._1; if (n <= k) { return freqGen._2; } else { n = n - k; } } while (true); } } vavr-0.10.0/vavr-test/src/main/java/io/vavr/test/package-info.java000066400000000000000000000002501342074374400246750ustar00rootroot00000000000000/** * A property check framework built around {@linkplain io.vavr.test.Property} which integrates well with unit test frameworks like junit. */ package io.vavr.test; vavr-0.10.0/vavr-test/src/test/000077500000000000000000000000001342074374400162575ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/test/java/000077500000000000000000000000001342074374400172005ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/test/java/io/000077500000000000000000000000001342074374400176075ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/test/java/io/vavr/000077500000000000000000000000001342074374400205655ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/test/java/io/vavr/test/000077500000000000000000000000001342074374400215445ustar00rootroot00000000000000vavr-0.10.0/vavr-test/src/test/java/io/vavr/test/ArbitraryTest.java000066400000000000000000000300701342074374400252060ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import io.vavr.Function1; import io.vavr.Tuple; import io.vavr.collection.Iterator; import io.vavr.collection.List; import io.vavr.collection.Stream; import org.junit.Test; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.Comparator; import java.util.Random; import static org.assertj.core.api.Assertions.assertThat; public class ArbitraryTest { // equally distributed random number generator private static final Random RANDOM = new Random(); // predictable random number generator (seed = 1) private Random predictableRandom = new Random(1L); // -- apply @Test public void shouldApplyIntegerObject() { final Gen> gen = new ArbitraryBinaryTree(0, 0).apply(0); assertThat(gen).isNotNull(); } // -- flatMap @Test public void shouldFlatMapArbitrary() { final Arbitrary arbitraryInt = size -> Gen.choose(-size, size); final Arbitrary> arbitraryTree = arbitraryInt.flatMap(i -> new ArbitraryBinaryTree(-i, i)); assertThat(arbitraryTree.apply(0).apply(RANDOM)).isNotNull(); } // -- map @Test public void shouldMapArbitrary() { final Arbitrary arbitraryInt = size -> Gen.choose(-size, size); final Arbitrary> arbitraryTree = arbitraryInt.map(BinaryTree::leaf); assertThat(arbitraryTree.apply(0).apply(RANDOM)).isNotNull(); } // -- filter @Test public void shouldFilterArbitrary() { final Arbitrary ints = Arbitrary.integer(); final Arbitrary evenInts = ints.filter(i -> i % 2 == 0); assertThat(evenInts.apply(10).apply(RANDOM)).isNotNull(); } // -- peek @Test public void shouldPeekArbitrary() { final int[] actual = new int[] { Integer.MIN_VALUE }; final int expected = Arbitrary.integer().peek(i -> actual[0] = i).apply(10).apply(RANDOM); assertThat(actual[0]).isEqualTo(expected); } // factory methods @Test public void shouldCreateArbitraryInteger() { final Arbitrary arbitrary = Arbitrary.integer(); final Integer actual = arbitrary.apply(10).apply(RANDOM); assertThat(actual).isNotNull(); } @Test public void shouldCreateArbitraryString() { final Arbitrary arbitrary = Arbitrary.string(Gen.choose('a', 'z')); final String actual = arbitrary.apply(10).apply(RANDOM); assertThat(actual).isNotNull(); } @Test public void shouldCreateArbitraryList() { final Arbitrary> arbitrary = Arbitrary.list(Arbitrary.integer()); final List actual = arbitrary.apply(10).apply(RANDOM); assertThat(actual).isNotNull(); } @Test public void shouldCreateArbitraryStream() { final Arbitrary> arbitrary = Arbitrary.stream(Arbitrary.integer()); final Stream actual = arbitrary.apply(10).apply(RANDOM); assertThat(actual).isNotNull(); } @Test public void shouldCreateFixedContentArbitrary() { final Gen arbitrary = Arbitrary.of("test", "content").apply(10); for (int i = 0; i < 100; i++) { assertThat(arbitrary.apply(RANDOM)).isIn("test", "content"); } } @Test public void shouldCreateNonDistinctArbitrary() { final Gen arbitrary = Arbitrary.string(Gen.choose('a', 'b')).apply(2); List.range(0, 1000) .map(i -> arbitrary.apply(RANDOM)) .groupBy(Function1.identity()) .forEach((key, value) -> assertThat(value.length()) .describedAs(key) .isGreaterThan(1)); } @Test public void shouldCreateDistinctArbitrary() { final Gen distinctArbitrary = Arbitrary.string(Gen.choose('a', 'b')).distinct().apply(100); List.range(0, 1000) .map(i -> distinctArbitrary.apply(RANDOM)) .groupBy(Function1.identity()) .forEach((key, value) -> assertThat(value.length()) .describedAs(key) .isEqualTo(1)); } @Test public void shouldCreateDistinctByArbitrary() { final Gen distinctByArbitrary = Arbitrary.string(Gen.choose('a', 'b')) .distinctBy(Comparator.naturalOrder()).apply(100); List.range(0, 10000) .map(i -> distinctByArbitrary.apply(RANDOM)) .groupBy(Function1.identity()) .forEach((key, value) -> assertThat(value.length()) .describedAs(key) .isEqualTo(1)); } @Test public void shouldCreateInterspersedFixedContentArbitrary() { final Gen arbitrary = Arbitrary.of("test") .intersperse(Arbitrary.of("content")) .apply(10); for (int i = 0; i < 100; i++) { assertThat(arbitrary.apply(RANDOM)).isIn("test", "content"); } } @Test public void shouldCreateInterspersedFixedContentArbitraryWithConstantOrder() { final Gen arbitrary = Arbitrary.of("test") .intersperse(Arbitrary.of("content")) .apply(10); final Iterator> generatedStringPairs = Stream.range(0, 10) .map(i -> arbitrary.apply(RANDOM)) .grouped(2); for (Stream stringPairs : generatedStringPairs) { assertThat(stringPairs.mkString(",")).isEqualTo("test,content"); } } @Test public void shouldCreateCharArrayArbitrary() { final Gen arbitrary = Arbitrary.string(Gen.choose("test".toCharArray())) .filter(s -> !"".equals(s)) .apply(1); for (int i = 0; i < 100; i++) { assertThat(arbitrary.apply(RANDOM)).isIn("t", "e", "s"); } } @Test public void shouldCreateArbitraryStreamAndEvaluateAllElements() { final Arbitrary> arbitrary = Arbitrary.stream(Arbitrary.integer()); final Stream actual = arbitrary.apply(10).apply(new Random() { private static final long serialVersionUID = 1L; @Override public int nextInt(int bound) { return bound - 1; } }); assertThat(actual.length()).isEqualTo(10); } @Test public void shouldCreateArbitraryLocalDateTime(){ final Arbitrary date = Arbitrary.localDateTime(); assertThat(date).isNotNull(); } @Test(expected = NullPointerException.class) public void shouldNotAcceptNullMedianLocalDateTime(){ Arbitrary.localDateTime(null, ChronoUnit.DAYS); } @Test(expected = NullPointerException.class) public void shouldNotAcceptNullChronoUnit(){ Arbitrary.localDateTime(LocalDateTime.now(), null); } @Test public void shouldCreateArbitraryLocalDateTimeAdjustedWithGivenChronoUnit(){ final LocalDateTime median = LocalDateTime.of(2017, 2, 17, 3, 40); final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.YEARS); final LocalDateTime date = arbitrary.apply(100).apply(predictableRandom); assertThat(date).isEqualTo("2063-04-22T01:46:10.312"); } @Test public void shouldCreateMedianLocalDateTimeIfSizeIsZero(){ final LocalDateTime median = LocalDateTime.now(); final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.DAYS); final LocalDateTime date = arbitrary.apply(0).apply(RANDOM); assertThat(date).isEqualTo(median); } @Test public void shouldCreateDatesInInRangeOfSize(){ final LocalDateTime median = LocalDateTime.now(); final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.DAYS); Property.def("With size of 100 days, dates should be in range of +/- 100 days") .forAll(arbitrary) .suchThat(d -> d.isAfter(median.minusDays(100)) && d.isBefore(median.plusDays(100))) .check(100, 1000); } @Test public void shouldIgnoreNegativeSignInRangeOfDates(){ final LocalDateTime median = LocalDateTime.now(); final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.DAYS); Property.def("With negative size of -100 days, dates should be in range of +/- 100 days") .forAll(arbitrary) .suchThat(d -> d.isAfter(median.minusDays(100)) && d.isBefore(median.plusDays(100))) .check(-100, 1000); } @Test public void shouldGenerateTwoDifferentSuccessiveDates(){ final Arbitrary dates = Arbitrary.localDateTime(); final LocalDateTime firstDate = dates.apply(100).apply(RANDOM); final LocalDateTime secondDate = dates.apply(100).apply(RANDOM); assertThat(firstDate).isNotEqualTo(secondDate); } // -- transform @Test public void shouldTransformArbitrary() { final Arbitrary arbitrary = ignored -> Gen.of(1); final String s = arbitrary.transform(a -> a.apply(0).apply(RANDOM).toString()); assertThat(s).isEqualTo("1"); } // helpers /** * Represents arbitrary binary trees of a certain depth n with values of type int. */ static class ArbitraryBinaryTree implements Arbitrary> { final int minValue; final int maxValue; ArbitraryBinaryTree(int minValue, int maxValue) { this.minValue = Math.min(minValue, maxValue); this.maxValue = Math.max(minValue, maxValue); } @Override public Gen> apply(int n) { return random -> Gen.choose(minValue, maxValue).flatMap(value -> { if (n == 0) { return Gen.of(BinaryTree.leaf(value)); } else { return Gen.frequency( Tuple.of(1, Gen.of(BinaryTree.leaf(value))), Tuple.of(4, Gen.of(BinaryTree.branch(apply(n / 2).apply(random), value, apply(n / 2).apply(random)))) ); } } ).apply(random); } } interface BinaryTree { static Branch branch(BinaryTree left, T value, BinaryTree right) { return new Branch<>(left, value, right); } static Branch leaf(T value) { return new Branch<>(empty(), value, empty()); } static Empty empty() { return Empty.instance(); } class Branch implements BinaryTree { final BinaryTree left; final T value; final BinaryTree right; Branch(BinaryTree left, T value, BinaryTree right) { this.left = left; this.value = value; this.right = right; } } class Empty implements BinaryTree { private static final Empty INSTANCE = new Empty<>(); @SuppressWarnings("unchecked") static Empty instance() { return (Empty) INSTANCE; } } } } vavr-0.10.0/vavr-test/src/test/java/io/vavr/test/CheckResultTest.java000066400000000000000000000337641342074374400255000ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import io.vavr.Tuple; import io.vavr.control.Option; import org.assertj.core.api.Assertions; import org.junit.Test; import java.util.Objects; import static org.assertj.core.api.Assertions.assertThat; public class CheckResultTest { static final CheckResult.Satisfied SATISFIED = new CheckResult.Satisfied("test", 0, false); static final CheckResult.Falsified FALSIFIED = new CheckResult.Falsified("test", 0, Tuple.of(1)); static final CheckResult.Erroneous ERRONEOUS = new CheckResult.Erroneous("test", 0, new Error("test"), Option.none()); // -- Satisfied @Test public void shouldBeSatisfiedWhenIsSatisfied() { assertThat(SATISFIED.isSatisfied()).isTrue(); } @Test public void shouldNotBeFalsifiedWhenIsSatisfied() { assertThat(SATISFIED.isFalsified()).isFalse(); } @Test public void shouldNotBeErroneousWhenIsSatisfied() { assertThat(SATISFIED.isErroneous()).isFalse(); } @Test public void shouldBeExhaustedWhenIsSatisfiedAndExhausted() { Assertions.assertThat(new CheckResult.Satisfied("test", 0, true).isExhausted()).isTrue(); } @Test public void shouldNotBeExhaustedWhenIsSatisfiedAndNotExhausted() { assertThat(SATISFIED.isExhausted()).isFalse(); } @Test public void shouldGetPropertyNameOfSatisfied() { assertThat(SATISFIED.propertyName()).isEqualTo("test"); } @Test public void shouldGetCountOfSatisfied() { assertThat(SATISFIED.count()).isEqualTo(0); } @Test public void shouldHaveNoSampleWhenIsSatisfied() { assertThat(SATISFIED.sample()).isEqualTo(Option.none()); } @Test public void shouldHaveNoErrorWhenIsSatisfied() { assertThat(SATISFIED.error()).isEqualTo(Option.none()); } @Test public void shouldIdentififyEqualSatisfiedObjectsWhenObjectsAreIdentical() { final CheckResult.Satisfied satisfied = SATISFIED; //noinspection EqualsWithItself assertThat(satisfied.equals(satisfied)).isTrue(); } @Test public void shouldIdentififyEqualSatisfiedObjectsWhenObjectsHaveSameTypeAndEqualValues() { final CheckResult.Satisfied satisfied1 = SATISFIED; final CheckResult.Satisfied satisfied2 = new CheckResult.Satisfied("test", 0, false); assertThat(satisfied1.equals(satisfied2)).isTrue(); } @Test public void shouldIdentififyUnequalSatisfiedObjectsWhenTypesAreUnequal() { final CheckResult.Satisfied satisfied = SATISFIED; assertThat(satisfied.equals(new Object())).isFalse(); } @Test public void shouldIdentififyUnequalSatisfiedObjectsWhenValuesAreUnequal() { final CheckResult.Satisfied satisfied = new CheckResult.Satisfied("test", 1, true); assertThat(satisfied.equals(new CheckResult.Satisfied("x", 1, true))).isFalse(); assertThat(satisfied.equals(new CheckResult.Satisfied("test", -1, true))).isFalse(); assertThat(satisfied.equals(new CheckResult.Satisfied("test", 1, false))).isFalse(); } @Test public void shouldComputeHashCodeOfSatisfied() { assertThat(SATISFIED.hashCode()).isEqualTo(Objects.hash("test", 0, false)); } @Test public void shouldComputeToStringOfSatisfied() { assertThat(SATISFIED.toString()).isEqualTo("Satisfied(propertyName = test, count = 0, exhausted = false)"); } // -- Falsified @Test public void shouldNotBeSatisfiedWhenIsFalsified() { assertThat(FALSIFIED.isSatisfied()).isFalse(); } @Test public void shouldBeFalsifiedWhenIsFalsified() { assertThat(FALSIFIED.isFalsified()).isTrue(); } @Test public void shouldNotBeErroneousWhenIsFalsified() { assertThat(FALSIFIED.isErroneous()).isFalse(); } @Test public void shouldNotBeExhaustedWhenIsFalsified() { assertThat(FALSIFIED.isExhausted()).isFalse(); } @Test public void shouldGetPropertyNameOfFalsified() { assertThat(FALSIFIED.propertyName()).isEqualTo("test"); } @Test public void shouldGetCountOfFalsified() { assertThat(FALSIFIED.count()).isEqualTo(0); } @Test public void shouldHaveASampleWhenIsFalsified() { assertThat(FALSIFIED.sample().get()).isEqualTo(Tuple.of(1)); } @Test public void shouldHaveNoErrorWhenIsFalsified() { assertThat(FALSIFIED.error()).isEqualTo(Option.none()); } @Test public void shouldIdentififyEqualFalsifiedObjectsWhenObjectsAreIdentical() { final CheckResult.Falsified falsified = FALSIFIED; //noinspection EqualsWithItself assertThat(falsified.equals(falsified)).isTrue(); } @Test public void shouldIdentififyEqualFalsifiedObjectsWhenObjectsHaveSameTypeAndEqualValues() { final CheckResult.Falsified falsified1 = FALSIFIED; final CheckResult.Falsified falsified2 = new CheckResult.Falsified("test", 0, Tuple.of(1)); assertThat(falsified1.equals(falsified2)).isTrue(); } @Test public void shouldIdentififyUnequalFalsifiedObjectsWhenTypesAreUnequal() { final CheckResult.Falsified falsified = FALSIFIED; assertThat(falsified.equals(new Object())).isFalse(); } @Test public void shouldIdentififyUnequalFalsifiedObjectsWhenValuesAreUnequal() { final CheckResult.Falsified falsified = new CheckResult.Falsified("test", 1, Tuple.of(2)); assertThat(falsified.equals(new CheckResult.Falsified("x", 1, Tuple.of(2)))).isFalse(); assertThat(falsified.equals(new CheckResult.Falsified("test", -1, Tuple.of(2)))).isFalse(); assertThat(falsified.equals(new CheckResult.Falsified("test", 1, Tuple.of(-1)))).isFalse(); } @Test public void shouldComputeHashCodeOfFalsified() { assertThat(FALSIFIED.hashCode()).isEqualTo(Objects.hash("test", 0, Tuple.of(1))); } @Test public void shouldComputeToStringOfFalsified() { assertThat(FALSIFIED.toString()).isEqualTo("Falsified(propertyName = test, count = 0, sample = (1))"); } // -- Erroneous @Test public void shouldNotBeSatisfiedWhenIsErroneous() { assertThat(ERRONEOUS.isSatisfied()).isFalse(); } @Test public void shouldNotBeFalsifiedWhenIsErroneous() { assertThat(ERRONEOUS.isFalsified()).isFalse(); } @Test public void shouldBeErroneousWhenIsErroneous() { assertThat(ERRONEOUS.isErroneous()).isTrue(); } @Test public void shouldNotBeExhaustedWhenIsErroneous() { assertThat(ERRONEOUS.isExhausted()).isFalse(); } @Test public void shouldGetPropertyNameOfErroneous() { assertThat(ERRONEOUS.propertyName()).isEqualTo("test"); } @Test public void shouldGetCountOfErroneous() { assertThat(ERRONEOUS.count()).isEqualTo(0); } @Test public void shouldHaveNoSampleWhenIsErroneousWithoutSample() { assertThat(ERRONEOUS.sample()).isEqualTo(Option.none()); } @Test public void shouldHaveSampleWhenIsErroneousWithSample() { final CheckResult.Erroneous erroneous = new CheckResult.Erroneous("test", 1, new Error("test"), Option.of(Tuple.of(1))); assertThat(erroneous.sample().get()).isEqualTo(Tuple.of(1)); } @Test public void shouldHaveAnErrorWhenIsErroneous() { assertThat(ERRONEOUS.error().get().getMessage()).isEqualTo("test"); } @Test public void shouldIdentififyEqualErroneousObjectsWhenObjectsAreIdentical() { final CheckResult.Erroneous erroneous = ERRONEOUS; //noinspection EqualsWithItself assertThat(erroneous.equals(erroneous)).isTrue(); } @Test public void shouldIdentififyEqualErroneousObjectsWhenObjectsHaveSameTypeAndEqualValues() { final CheckResult.Erroneous erroneous1 = ERRONEOUS; final CheckResult.Erroneous erroneous2 = new CheckResult.Erroneous("test", 0, new Error("test"), Option.none()); assertThat(erroneous1.equals(erroneous2)).isTrue(); } @Test public void shouldIdentififyUnequalErroneousObjectsWhenTypesAreUnequal() { final CheckResult.Erroneous erroneous = ERRONEOUS; assertThat(erroneous.equals(new Object())).isFalse(); } @Test public void shouldIdentififyUnequalErroneousObjectsWhenValuesAreUnequal() { final CheckResult.Erroneous erroneous = new CheckResult.Erroneous("test", 1, new Error("error"), Option.none()); assertThat(erroneous.equals(new CheckResult.Erroneous("x", 1, new Error("error"), Option.none()))).isFalse(); assertThat(erroneous.equals(new CheckResult.Erroneous("test", -1, new Error("error"), Option.none()))).isFalse(); assertThat(erroneous.equals(new CheckResult.Erroneous("test", 1, new Error("x"), Option.none()))).isFalse(); assertThat(erroneous.equals(new CheckResult.Erroneous("test", 1, new Error("error"), Option.some(Tuple.of(1))))).isFalse(); } @Test public void shouldCheckDeepEqualityOfErroneousErrors() { Assertions.assertThat(new CheckResult.Erroneous("test", 1, null, Option.none())).isEqualTo(new CheckResult.Erroneous("test", 1, null, Option.none())); Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, null, Option.none())); Assertions.assertThat(new CheckResult.Erroneous("test", 1, null, Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())); Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())).isEqualTo(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())); Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("x"), Option.none())); Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())).isEqualTo(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())); Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())); Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("test", new Error("x")), Option.none())); } @Test public void shouldComputeHashCodeOfErroneous() { assertThat(ERRONEOUS.hashCode()).isEqualTo(Objects.hash("test", 0, ERRONEOUS.deepHashCode(new Error("test")), Option.none())); } @Test public void shouldComputeToStringOfErroneous() { assertThat(ERRONEOUS.toString()).isEqualTo("Erroneous(propertyName = test, count = 0, error = test, sample = None)"); } // Assertions // -- satisfied @Test public void shouldAssertThatCheckResultIsSatisfied() { new CheckResult.Satisfied("test", 0, false).assertIsSatisfied(); } @Test(expected = AssertionError.class) public void shouldThrowWhenAssertThatNonSatisfiedCheckResultIsSatisfied() { new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsSatisfied(); } // -- satisfiedWithExhaustion @Test public void shouldAssertThatCheckResultIsSatisfiedWithExhaustionTrue() { new CheckResult.Satisfied("test", 0, true).assertIsSatisfiedWithExhaustion(true); } @Test public void shouldAssertThatCheckResultIsSatisfiedWithExhaustionFalse() { new CheckResult.Satisfied("test", 0, false).assertIsSatisfiedWithExhaustion(false); } @Test(expected = AssertionError.class) public void shouldThrowWhenAssertThatNonSatisfiedCheckResultIsSatisfiedWithExhaustionTrue() { new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsSatisfiedWithExhaustion(true); } @Test(expected = AssertionError.class) public void shouldThrowWhenAssertThatNonSatisfiedCheckResultIsSatisfiedWithExhaustionFalse() { new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsSatisfiedWithExhaustion(false); } @Test(expected = AssertionError.class) public void shouldThrowWhenAssertThatSatisfiedNonExhaustedCheckResultIsSatisfiedWithExhaustionTrue() { new CheckResult.Satisfied("test", 0, false).assertIsSatisfiedWithExhaustion(true); } @Test(expected = AssertionError.class) public void shouldThrowWhenAssertThatSatisfiedExhaustedCheckResultIsSatisfiedWithExhaustionFalse() { new CheckResult.Satisfied("test", 0, true).assertIsSatisfiedWithExhaustion(false); } // -- falsified @Test public void shouldAssertThatCheckResultIsFalsified() { new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsFalsified(); } @Test(expected = AssertionError.class) public void shouldThrowWhenAssertThatNonFalsifiedCheckResultIsFalsified() { new CheckResult.Satisfied("test", 0, false).assertIsFalsified(); } // -- erroneous @Test public void shouldAssertThatCheckResultIsErroneous() { new CheckResult.Erroneous("test", 0, new Error(), Option.none()).assertIsErroneous(); } @Test(expected = AssertionError.class) public void shouldThrowWhenAssertThatNonErroneousCheckResultIsErroneous() { new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsErroneous(); } } vavr-0.10.0/vavr-test/src/test/java/io/vavr/test/ConditionTest.java000066400000000000000000000026661342074374400252070ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2018 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import io.vavr.test.Property.Condition; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; public class ConditionTest { /** * Def: A 'Condition' is the result of {@code p => q} where {@code p} is a pre-condition and {@code q} is a post-condition. *

* The following holds: {@code p => q ≡ ¬p ∨ q} */ @Test public void should() { assertThat(cond(false, false)).isTrue(); assertThat(cond(false, true)).isTrue(); assertThat(cond(true, false)).isFalse(); assertThat(cond(true, true)).isTrue(); } private boolean cond(boolean p, boolean q) { return !new Condition(p, q).isFalse(); } } vavr-0.10.0/vavr-test/src/test/java/io/vavr/test/GenTest.java000066400000000000000000000277541342074374400237770ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.test; import io.vavr.Tuple; import io.vavr.collection.Stream; import io.vavr.Tuple2; import io.vavr.collection.List; import org.junit.Test; import java.util.Arrays; import java.util.Random; import java.util.function.Predicate; import java.util.function.Supplier; import static org.assertj.core.api.Assertions.assertThat; public class GenTest { // equally distributed random number generator static final Random RANDOM = new Random(); // number of tries to assert a property static final int TRIES = 1000; // -- of @Test public void shouldIntersperseMultipleGeneratos() throws Exception { Gen gen = Gen.of(0).intersperse(Gen.of(1)); assertThat(gen.apply(RANDOM)).isEqualTo(0); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(0); assertThat(gen.apply(RANDOM)).isEqualTo(1); } @Test public void shouldCreateConstantGenOfElement() { final Gen gen = Gen.of(1); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(1); } @Test public void shouldCreateGenOfSeedAndFunction() { final Gen gen = Gen.of(1, i -> i + 1); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(2); assertThat(gen.apply(RANDOM)).isEqualTo(3); } // -- random number generator (rng) @Test public void shouldUseCustomRandomNumberGenerator() { final Random rng = new Random() { private static final long serialVersionUID = 1L; @Override public int nextInt(int bound) { return 0; } }; final Gen gen = Gen.choose(1, 2); final Number actual = Stream.continually(() -> gen.apply(rng)).take(10).sum(); assertThat(actual).isEqualTo(10L); } // -- choose(int, int) @Test public void shouldChooseIntBetweenMinMax() { assertForAll(() -> Gen.choose(-1, 1).apply(RANDOM), i -> i >= -1 && i <= 1); } @Test public void shouldChooseIntWhenMinEqualsMax() { assertForAll(() -> Gen.choose(0, 0).apply(RANDOM), i -> i == 0); } // -- choose(long, long) @Test public void shouldChooseLongBetweenMinMax() { assertForAll(() -> Gen.choose(-1L, 1L).apply(RANDOM), l -> l >= -1L && l <= 1L); } @Test public void shouldChooseLongWhenMinEqualsMax() { assertForAll(() -> Gen.choose(0L, 0L).apply(RANDOM), l -> l == 0L); } // -- choose(double, double) @Test public void shouldChooseDoubleBetweenMinMax() { assertForAll(() -> Gen.choose(-1.0d, 1.0d).apply(RANDOM), d -> d >= -1.0d && d <= 1.0d); } @Test public void shouldChooseDoubleWhenMinEqualsMax() { assertForAll(() -> Gen.choose(0.0d, 0.0d).apply(RANDOM), d -> d == 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMinIsNegativeInfinite() { Gen.choose(Double.NEGATIVE_INFINITY, 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMinIsPositiveInfinite() { Gen.choose(Double.POSITIVE_INFINITY, 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMinIsNotANumber() { Gen.choose(Double.NaN, 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMaxIsNegativeInfinite() { Gen.choose(0.0d, Double.NEGATIVE_INFINITY); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMaxIsPositiveInfinite() { Gen.choose(0.0d, Double.POSITIVE_INFINITY); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMaxIsNotANumber() { Gen.choose(0.0d, Double.NaN); } // -- choose(char, char) @Test public void shouldChooseCharBetweenMinMax() { assertForAll(() -> Gen.choose('A', 'Z').apply(RANDOM), c -> c >= 'A' && c <= 'Z'); } @Test public void shouldChooseCharWhenMinEqualsMax() { assertForAll(() -> Gen.choose('a', 'a').apply(RANDOM), c -> c == 'a'); } // -- choose(array) @Test public void shouldChooseFromASingleArray() throws Exception { Integer[] i = { 1 }; assertForAll(() -> Gen.choose(i).apply(RANDOM), c -> c == 1); } @Test(expected = RuntimeException.class) public void shouldFailOnEmptyArray() throws Exception { Integer[] i = {}; Gen.choose(i).apply(RANDOM); } // -- Choose(enum) enum testEnum { value1 } @Test public void shouldChooseFromEnum() throws Exception { assertForAll(() -> Gen.choose(testEnum.class).apply(RANDOM), e -> Arrays.asList(testEnum.values()).contains(e)); } // -- Choose(iterable) @Test public void shouldChooseFromIterable() throws Exception { List i = List.of(1); assertForAll(() -> Gen.choose(i).apply(RANDOM), c -> c == 1); } @Test public void shouldChooseFromIterableWithInstancesOfGenericInterface() { List> i = List.of(() -> "test", () -> "test"); Supplier supplier = Gen.choose(i).apply(RANDOM); assertThat(supplier.get()).isEqualTo("test"); } @Test(expected = RuntimeException.class) public void shouldFailOnEmptyIterable() throws Exception { List i = List.empty(); Gen.choose(i).apply(RANDOM); } // -- fail @Test(expected = RuntimeException.class) public void shouldFailAlwaysWhenCallingFailingGen() { Gen.fail().apply(RANDOM); } // -- frequency(VarArgs) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFrequencyOfVarArgsAndArgIsNull() { Gen.frequency((Tuple2>) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfVarArgsAndArgIsEmpty() { @SuppressWarnings("unchecked") final Tuple2>[] empty = (Tuple2>[]) new Tuple2[0]; Gen.frequency(empty); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfVarArgsAndAllFrequenciesAreNonPositive() { final Gen gen = Gen.frequency(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0))); gen.apply(RANDOM); } @Test public void shouldIgnoreGeneratorsWithNonPositiveFrequency() { final Gen gen = Gen.frequency(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0)), Tuple.of(1, Gen.of(1))); assertForAll(() -> gen.apply(RANDOM), i -> i == 1); } @Test public void shouldGenerateElementsAccordingToFrequencyGivenVarArgs() { final Gen gen = Gen.frequency(Tuple.of(0, Gen.of(-1)), Tuple.of(1, Gen.of(1))); assertForAll(() -> gen.apply(RANDOM), i -> i != -1); } // -- frequency(Iterable) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFrequencyOfIterableAndArgIsNull() { Gen.frequency((Iterable>>) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfIterableAndArgIsEmpty() { Gen.frequency(List.empty()); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfIterableAndAllFrequenciesAreNonPositive() { final Gen gen = Gen.frequency(List.of(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0)))); gen.apply(RANDOM); } @Test public void shouldGenerateElementsAccordingToFrequencyGivenAnIterable() { final Gen gen = Gen.frequency(List.of(Tuple.of(0, Gen.of(-1)), Tuple.of(1, Gen.of(1)))); assertForAll(() -> gen.apply(RANDOM), i -> i != -1); } // -- oneOf(VarArgs) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingOneOfAndVarArgsIsNull() { Gen.oneOf((Gen[]) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingOneOfAndVarArgsIsEmpty() { @SuppressWarnings("unchecked") final Gen[] empty = (Gen[]) new Gen[0]; Gen.oneOf(empty); } @Test public void shouldReturnOneOfGivenVarArgs() { final Gen gen = Gen.oneOf(Gen.of(1), Gen.of(2)); assertForAll(() -> gen.apply(RANDOM), i -> i == 1 || i == 2); } // -- oneOf(Iterable) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingOneOfAndIterableIsNull() { Gen.oneOf((Iterable>) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingOneOfAndIterableIsEmpty() { Gen.oneOf(List.empty()); } @Test public void shouldReturnOneOfGivenIterable() { final Gen gen = Gen.oneOf(List.of(Gen.of(1), Gen.of(2))); assertForAll(() -> gen.apply(RANDOM), i -> i == 1 || i == 2); } // -- arbitrary @Test public void shouldConvertGenToArbitrary() { assertThat(Gen.of(1).arbitrary()).isInstanceOf(Arbitrary.class); } // -- map @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingMapWithNullArg() { Gen.of(1).map(null); } @Test public void shouldMapGen() { final Gen gen = Gen.of(1).map(i -> i * 2); assertForAll(() -> gen.apply(RANDOM), i -> i % 2 == 0); } // -- flatMap @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFlatMapWithNullArg() { Gen.of(1).flatMap(null); } @Test public void shouldFlatMapGen() { final Gen gen = Gen.of(1).flatMap(i -> Gen.of(i * 2)); assertForAll(() -> gen.apply(RANDOM), i -> i % 2 == 0); } // -- filter @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFilterWithNullArg() { Gen.of(1).filter(null); } @Test public void shouldFilterGenerator() { final Gen gen = Gen.choose(1, 2).filter(i -> i % 2 == 0); assertForAll(() -> gen.apply(RANDOM), i -> i == 2); } @Test(expected = IllegalStateException.class) public void shouldDetectEmptyFilter() { Gen.of(1).filter(ignored -> false).apply(RANDOM); } // -- peek @Test public void shouldPeekArbitrary() { final int[] actual = new int[] { -1 }; final int expected = Gen.of(1).peek(i -> actual[0] = i).apply(new Random()); assertThat(actual[0]).isEqualTo(expected); } // -- transform @Test public void shouldTransformGen() { final String s = Gen.of(1).transform(gen -> gen.apply(RANDOM).toString()); assertThat(s).isEqualTo("1"); } // helpers void assertForAll(Supplier supplier, Predicate property) { for (int i = 0; i < TRIES; i++) { final T element = supplier.get(); if (!property.test(element)) { throw new AssertionError("predicate did not hold for " + element); } } } } vavr-0.10.0/vavr/000077500000000000000000000000001342074374400135345ustar00rootroot00000000000000vavr-0.10.0/vavr/generator/000077500000000000000000000000001342074374400155225ustar00rootroot00000000000000vavr-0.10.0/vavr/generator/Generator.scala000066400000000000000000005276661342074374400205030ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // temporarily needed to circumvent https://issues.scala-lang.org/browse/SI-3772 (see case class Generics) import Generator._ import JavaGenerator._ import collection.immutable.ListMap import scala.language.implicitConversions val N = 8 val VARARGS = 10 val TARGET_MAIN = s"${project.getBasedir()}/src-gen/main/java" val TARGET_TEST = s"${project.getBasedir()}/src-gen/test/java" val CHARSET = java.nio.charset.StandardCharsets.UTF_8 /** * ENTRY POINT */ def run(): Unit = { generateMainClasses() generateTestClasses() } /** * Generate Vavr src-gen/main/java classes */ def generateMainClasses(): Unit = { // Workaround: Use /$javadoc instead of /** in a StringContext when IntelliJ IDEA otherwise shows up errors in the editor val javadoc = "**" genAPI() genFunctions() genTuples() genArrayTypes() /** * Generator of Match */ def genAPI(): Unit = { genVavrFile("io.vavr", "API")(genAPI) def genAPI(im: ImportManager, packageName: String, className: String): String = { val OptionType = im.getType("io.vavr.control.Option") val IteratorType = im.getType("io.vavr.collection.Iterator") val EitherType = im.getType("io.vavr.control.Either") val FutureType = im.getType("io.vavr.concurrent.Future") val CheckedFunction0Type = im.getType("io.vavr.CheckedFunction0") val PartialFunctionType = im.getType("io.vavr.PartialFunction") val TryType = im.getType("io.vavr.control.Try") val ValidationType = im.getType("io.vavr.control.Validation") val CharSeqType = im.getType("io.vavr.collection.CharSeq") val ArrayType = im.getType("io.vavr.collection.Array") val VectorType = im.getType("io.vavr.collection.Vector") val ListType = im.getType("io.vavr.collection.List") val StreamType = im.getType("io.vavr.collection.Stream") val QueueType = im.getType("io.vavr.collection.Queue") val LinkedHashSetType = im.getType("io.vavr.collection.LinkedHashSet") val HashSetType = im.getType("io.vavr.collection.HashSet") val TreeSetType = im.getType("io.vavr.collection.TreeSet") val PriorityQueueType = im.getType("io.vavr.collection.PriorityQueue") val LinkedHashMapType = im.getType("io.vavr.collection.LinkedHashMap") val HashMapType = im.getType("io.vavr.collection.HashMap") val TreeMapType = im.getType("io.vavr.collection.TreeMap") val IndexedSeqType = im.getType("io.vavr.collection.IndexedSeq") val MapType = im.getType("io.vavr.collection.Map") val SeqType = im.getType("io.vavr.collection.Seq") val SetType = im.getType("io.vavr.collection.Set") val SortedMapType = im.getType("io.vavr.collection.SortedMap") val SortedSetType = im.getType("io.vavr.collection.SortedSet") // Note: import the Java stuff last in order to force full qualified names on import clashes val Objects = im.getType("java.util.Objects") val JavaComparatorType = im.getType("java.util.Comparator") val JavaMapType = im.getType("java.util.Map") val ExecutorType = im.getType("java.util.concurrent.Executor") val FunctionType = im.getType("java.util.function.Function") val BiFunctionType = im.getType("java.util.function.BiFunction") val PredicateType = im.getType("java.util.function.Predicate") val SupplierType = im.getType("java.util.function.Supplier") val monadicTypesFor = List("Iterable", OptionType, FutureType, TryType, ListType) def genTraversableAliases(traversableType: String, returnType: String, name: String) = xs""" // -- $name /$javadoc * Alias for {@link $traversableType#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link $traversableType} */ public static $returnType $name() { return $traversableType.empty(); } /$javadoc * Alias for {@link $traversableType#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link $traversableType} instance containing the given element */ public static $returnType $name(T element) { return $traversableType.of(element); } /$javadoc * Alias for {@link $traversableType#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link $traversableType} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static $returnType $name(T... elements) { return $traversableType.of(elements); } """ def genSortedTraversableAliases(traversableType: String, returnType: String, name: String) = xs""" // -- $name /$javadoc * Alias for {@link $traversableType#empty()} * * @param Component type of element. * @return A new {@link $traversableType} empty instance */ public static > $returnType $name() { return $traversableType.empty(); } /$javadoc * Alias for {@link $traversableType#empty($JavaComparatorType)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @return A new {@link $traversableType} empty instance */ public static > $returnType $name($JavaComparatorType comparator) { return $traversableType.empty(comparator); } /$javadoc * Alias for {@link $traversableType#of(Comparable)} * * @param Component type of element. * @param element An element. * @return A new {@link $traversableType} instance containing the given element */ public static > $returnType $name(T element) { return $traversableType.of(element); } /$javadoc * Alias for {@link $traversableType#of($JavaComparatorType, Object)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @param element An element. * @return A new {@link $traversableType} instance containing the given element */ public static $returnType $name($JavaComparatorType comparator, T element) { return $traversableType.of(comparator, element); } /$javadoc * Alias for {@link $traversableType#of(Comparable...)} * * @param Component type of element. * @param elements Zero or more elements. * @return A new {@link $traversableType} instance containing the given elements */ @SuppressWarnings("varargs") @SafeVarargs public static > $returnType $name(T... elements) { return $traversableType.of(elements); } /$javadoc * Alias for {@link $traversableType#of($JavaComparatorType, Object...)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @param elements Zero or more elements. * @return A new {@link $traversableType} instance containing the given elements */ @SuppressWarnings("varargs") @SafeVarargs public static $returnType $name($JavaComparatorType comparator, T... elements) { return $traversableType.of(comparator, elements); } """ def genMapAliases(mapType: String, returnType: String, name: String) = xs""" // -- $name /$javadoc * Alias for {@link $mapType#empty()} * * @param The key type. * @param The value type. * @return A singleton instance of empty {@link $mapType} */ public static $returnType $name() { return $mapType.empty(); } /$javadoc * Alias for {@link $mapType#ofEntries(Tuple2...)} * * @param The key type. * @param The value type. * @param entries Map entries. * @return A new {@link $mapType} instance containing the given entries * @deprecated Will be removed in a future version. */ @Deprecated @SuppressWarnings("varargs") @SafeVarargs public static $returnType $name(Tuple2... entries) { return $mapType.ofEntries(entries); } ${(1 to VARARGS).gen(i => { xs""" /$javadoc * Alias for {@link $mapType#of(${(1 to i).gen(j => "Object, Object")(", ")})} * * @param The key type. * @param The value type. ${(1 to i).gen(j => s"* @param k$j The key${ if (i > 1) s" of the ${j.ordinal} pair" else ""}\n* @param v$j The value${ if (i > 1) s" of the ${j.ordinal} pair" else ""}\n")} * @return A new {@link $mapType} instance containing the given entries */ public static $returnType $name(${(1 to i).gen(j => xs"K k$j, V v$j")(", ")}) { return $mapType.of(${(1 to i).gen(j => xs"k$j, v$j")(", ")}); } """ })("\n\n")} """ def genSortedMapAliases(mapType: String, returnType: String, name: String) = xs""" /$javadoc * Alias for {@link $mapType#empty()} * * @param The key type. * @param The value type. * @return A new empty {@link $mapType} instance */ public static , V> $returnType $name() { return $mapType.empty(); } /$javadoc * Alias for {@link $mapType#empty($JavaComparatorType)} * * @param The key type. * @param The value type. * @param keyComparator The comparator used to sort the entries by their key * @return A new empty {@link $mapType} instance */ public static $returnType $name($JavaComparatorType keyComparator) { return $mapType.empty(keyComparator); } /$javadoc * Alias for {@link $mapType#of(Comparator, Object, Object)} * * @param The key type. * @param The value type. * @param keyComparator The comparator used to sort the entries by their key * @param key A singleton map key. * @param value A singleton map value. * @return A new {@link $mapType} instance containing the given entry */ public static $returnType $name(Comparator keyComparator, K key, V value) { return $mapType.of(keyComparator, key, value); } /$javadoc * Alias for {@link $mapType#ofEntries(Tuple2...)} * * @param The key type. * @param The value type. * @param entries Map entries. * @return A new {@link $mapType} instance containing the given entries * @deprecated Will be removed in a future version. */ @Deprecated @SuppressWarnings("varargs") @SafeVarargs public static , V> $returnType $name(Tuple2... entries) { return $mapType.ofEntries(entries); } /$javadoc * Alias for {@link $mapType#ofEntries($JavaComparatorType, Tuple2...)} * * @param The key type. * @param The value type. * @param keyComparator The comparator used to sort the entries by their key * @param entries Map entries. * @return A new {@link $mapType} instance containing the given entry * @deprecated Will be removed in a future version. */ @Deprecated @SuppressWarnings("varargs") @SafeVarargs public static $returnType $name($JavaComparatorType keyComparator, Tuple2... entries) { return $mapType.ofEntries(keyComparator, entries); } /$javadoc * Alias for {@link $mapType#ofAll($JavaMapType)} * * @param The key type. * @param The value type. * @param map A map entry. * @return A new {@link $mapType} instance containing the given map * @deprecated Will be removed in a future version. */ @Deprecated public static , V> $returnType $name($JavaMapType map) { return $mapType.ofAll(map); } ${(1 to VARARGS).gen(i => xs""" /$javadoc * Alias for {@link $mapType#of(${(1 to i).gen(j => s"${if (mapType.equals("TreeMap")) s"Comparable" else s"Object"}, Object")(", ")})} * * @param The key type. * @param The value type. ${(1 to i).gen(j => s"* @param k$j The key${if (i > 1) s" of the ${j.ordinal} pair" else ""}\n* @param v$j The value${if (i > 1) s" of the ${j.ordinal} pair" else ""}\n")} * @return A new {@link $mapType} instance containing the given entries */ public static , V> $returnType $name(${(1 to i).gen(j => xs"K k$j, V v$j")(", ")}) { return $mapType.of(${(1 to i).gen(j => xs"k$j, v$j")(", ")}); } """)("\n\n")} """ def genAliases(im: ImportManager, packageName: String, className: String): String = { xs""" // // Aliases for static factories // // -- Function ${(0 to N).gen(i => { val generics = (1 to i).gen(j => s"T$j")(", ") val fullGenerics = s"<${(i > 0).gen(s"$generics, ")}R>" xs""" /$javadoc * Alias for {@link Function$i#of(Function$i)} * ${(0 to i).gen(j => if (j == 0) "* @param return type" else s"* @param ${if (j < 10) " " else ""} type of the ${j.ordinal} argument")("\n")} * @param methodReference A method reference * @return A {@link Function$i} */ public static $fullGenerics Function$i$fullGenerics Function(Function$i$fullGenerics methodReference) { return Function$i.of(methodReference); } """ })("\n\n")} // -- CheckedFunction ${(0 to N).gen(i => { val generics = (1 to i).gen(j => s"T$j")(", ") val fullGenerics = s"<${(i > 0).gen(s"$generics, ")}R>" xs""" /$javadoc * Alias for {@link CheckedFunction$i#of(CheckedFunction$i)} * ${(0 to i).gen(j => if (j == 0) "* @param return type" else s"* @param type of the ${j.ordinal} argument")("\n")} * @param methodReference A method reference * @return A {@link CheckedFunction$i} */ public static $fullGenerics CheckedFunction$i$fullGenerics CheckedFunction(CheckedFunction$i$fullGenerics methodReference) { return CheckedFunction$i.of(methodReference); } """ })("\n\n")} // -- unchecked ${(0 to N).gen(i => { val generics = (1 to i).gen(j => s"T$j")(", ") val fullGenerics = s"<${(i > 0).gen(s"$generics, ")}R>" xs""" /$javadoc * Alias for {@link CheckedFunction$i#unchecked} * ${(0 to i).gen(j => if (j == 0) "* @param return type" else s"* @param type of the ${j.ordinal} argument")("\n")} * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction$i} */ public static $fullGenerics Function$i$fullGenerics unchecked(CheckedFunction$i$fullGenerics f) { return f.unchecked(); } """ })("\n\n")} // -- Tuple /$javadoc * Alias for {@link Tuple#empty()} * * @return the empty tuple. */ public static Tuple0 Tuple() { return Tuple.empty(); } ${(1 to N).gen(i => { val generics = (1 to i).gen(j => s"T$j")(", ") val links = (1 to i).gen(j => s"Object")(", ") val params = (1 to i).gen(j => s"T$j t$j")(", ") val args = (1 to i).gen(j => s"t$j")(", ") xs""" /$javadoc * Alias for {@link Tuple#of($links)} * * Creates a tuple of ${i.numerus("element")}. * ${(1 to i).gen(j => s"* @param type of the ${j.ordinal} element")("\n")} ${(1 to i).gen(j => s"* @param t$j the ${j.ordinal} element")("\n")} * @return a tuple of ${i.numerus("element")}. */ public static <$generics> Tuple$i<$generics> Tuple($params) { return Tuple.of($args); } """ })("\n\n")} // -- Either /$javadoc * Alias for {@link $EitherType#right(Object)} * * @param Type of left value. * @param Type of right value. * @param right The value. * @return A new {@link $EitherType.Right} instance. */ @SuppressWarnings("unchecked") public static $EitherType.Right Right(R right) { return ($EitherType.Right) $EitherType.right(right); } /$javadoc * Alias for {@link $EitherType#left(Object)} * * @param Type of left value. * @param Type of right value. * @param left The value. * @return A new {@link $EitherType.Left} instance. */ @SuppressWarnings("unchecked") public static $EitherType.Left Left(L left) { return ($EitherType.Left) $EitherType.left(left); } // -- Future /$javadoc * Alias for {@link $FutureType#of($CheckedFunction0Type)} * * @param Type of the computation result. * @param computation A computation. * @return A new {@link $FutureType} instance. * @throws NullPointerException if computation is null. */ public static $FutureType Future($CheckedFunction0Type computation) { return $FutureType.of(computation); } /$javadoc * Alias for {@link $FutureType#of($ExecutorType, $CheckedFunction0Type)} * * @param Type of the computation result. * @param executorService An executor service. * @param computation A computation. * @return A new {@link $FutureType} instance. * @throws NullPointerException if one of executorService or computation is null. */ public static $FutureType Future($ExecutorType executorService, $CheckedFunction0Type computation) { return $FutureType.of(executorService, computation); } /$javadoc * Alias for {@link $FutureType#successful(Object)} * * @param The value type of a successful result. * @param result The result. * @return A succeeded {@link $FutureType}. */ public static $FutureType Future(T result) { return $FutureType.successful(result); } /$javadoc * Alias for {@link $FutureType#successful($ExecutorType, Object)} * * @param The value type of a successful result. * @param executorService An {@code ExecutorService}. * @param result The result. * @return A succeeded {@link $FutureType}. * @throws NullPointerException if executorService is null */ public static $FutureType Future($ExecutorType executorService, T result) { return $FutureType.successful(executorService, result); } // -- Lazy /$javadoc * Alias for {@link Lazy#of($SupplierType)} * * @param type of the lazy value * @param supplier A supplier * @return A new instance of {@link Lazy} */ public static Lazy Lazy($SupplierType supplier) { return Lazy.of(supplier); } // -- Option /$javadoc * Alias for {@link $OptionType#of(Object)} * * @param type of the value * @param value A value * @return {@link $OptionType.Some} if value is not {@code null}, {@link $OptionType.None} otherwise */ public static $OptionType Option(T value) { return $OptionType.of(value); } /$javadoc * Alias for {@link $OptionType#some(Object)} * * @param type of the value * @param value A value * @return {@link $OptionType.Some} */ @SuppressWarnings("unchecked") public static $OptionType.Some Some(T value) { return ($OptionType.Some) $OptionType.some(value); } /$javadoc * Alias for {@link $OptionType#none()} * * @param component type * @return the singleton instance of {@link $OptionType.None} */ @SuppressWarnings("unchecked") public static $OptionType.None None() { return ($OptionType.None) $OptionType.none(); } // -- Try /$javadoc * Alias for {@link $TryType#of($CheckedFunction0Type)} * * @param Component type * @param supplier A checked supplier * @return {@link $TryType.Success} if no exception occurs, otherwise {@link $TryType.Failure} if an * exception occurs calling {@code supplier.get()}. */ public static $TryType Try($CheckedFunction0Type supplier) { return $TryType.of(supplier); } /$javadoc * Alias for {@link $TryType#success(Object)} * * @param Type of the given {@code value}. * @param value A value. * @return A new {@link $TryType.Success}. */ @SuppressWarnings("unchecked") public static $TryType.Success Success(T value) { return ($TryType.Success) $TryType.success(value); } /$javadoc * Alias for {@link $TryType#failure(Throwable)} * * @param Component type of the {@code Try}. * @param exception An exception. * @return A new {@link $TryType.Failure}. */ @SuppressWarnings("unchecked") public static $TryType.Failure Failure(Throwable exception) { return ($TryType.Failure) $TryType.failure(exception); } // -- Validation /$javadoc * Alias for {@link $ValidationType#valid(Object)} * * @param type of the error * @param type of the given {@code value} * @param value A value * @return {@link $ValidationType.Valid} * @throws NullPointerException if value is null */ @SuppressWarnings("unchecked") public static $ValidationType.Valid Valid(T value) { return ($ValidationType.Valid) $ValidationType.valid(value); } /$javadoc * Alias for {@link $ValidationType#invalid(Object)} * * @param type of the given {@code error} * @param type of the value * @param error An error * @return {@link $ValidationType.Invalid} * @throws NullPointerException if error is null */ @SuppressWarnings("unchecked") public static $ValidationType.Invalid Invalid(E error) { return ($ValidationType.Invalid) $ValidationType.invalid(error); } // -- CharSeq /$javadoc * Alias for {@link $CharSeqType#of(char)} * * @param character A character. * @return A new {@link $CharSeqType} instance containing the given element */ public static $CharSeqType CharSeq(char character) { return $CharSeqType.of(character); } /$javadoc * Alias for {@link $CharSeqType#of(char...)} * * @param characters Zero or more characters. * @return A new {@link $CharSeqType} instance containing the given characters in the same order. * @throws NullPointerException if {@code elements} is null */ public static $CharSeqType CharSeq(char... characters) { return $CharSeqType.of(characters); } /$javadoc * Alias for {@link $CharSeqType#of(CharSequence)} * * @param sequence {@code CharSequence} instance. * @return A new {@link $CharSeqType} instance */ public static $CharSeqType CharSeq(CharSequence sequence) { return $CharSeqType.of(sequence); } // -- TRAVERSABLES ${genSortedTraversableAliases(PriorityQueueType, PriorityQueueType, "PriorityQueue")} // -- SEQUENCES ${genTraversableAliases(ListType, SeqType, "Seq")} ${genTraversableAliases(VectorType, IndexedSeqType, "IndexedSeq")} ${genTraversableAliases(ArrayType, ArrayType, "Array")} ${genTraversableAliases(ListType, ListType, "List")} ${genTraversableAliases(QueueType, QueueType, "Queue")} ${genTraversableAliases(StreamType, StreamType, "Stream")} ${genTraversableAliases(VectorType, VectorType, "Vector")} // -- SETS ${genTraversableAliases(HashSetType, SetType, "Set")} ${genTraversableAliases(LinkedHashSetType, SetType, "LinkedSet")} ${genSortedTraversableAliases(TreeSetType, SortedSetType, "SortedSet")} // -- MAPS ${genMapAliases(HashMapType, MapType, "Map")} ${genMapAliases(LinkedHashMapType, MapType, "LinkedMap")} ${genSortedMapAliases(TreeMapType, SortedMapType, "SortedMap")} """ } im.getStatic("io.vavr.API.Match.*") def genJavaTypeTweaks(im: ImportManager, packageName: String, className: String): String = { xs""" // // Java type tweaks // /** * Runs a {@code unit} of work and returns {@code Void}. This is helpful when a return value is expected, * e.g. by {@code Match}: * *
Match(i).of(
           *     Case($$(is(0)), i -> run(() -> System.out.println("zero"))),
           *     Case($$(is(1)), i -> run(() -> System.out.println("one"))),
           *     Case($$(), o -> run(() -> System.out.println("many")))
           * )
* * @param unit A block of code to be run. * @return the single instance of {@code Void}, namely {@code null} */ public static Void run(Runnable unit) { unit.run(); return null; } """ } def genFor(im: ImportManager, packageName: String, className: String): String = { xs""" // // For-Comprehension // /** * A shortcut for {@code Iterator.ofAll(ts).flatMap(f)} which allows us to write real for-comprehensions using * {@code For(...).yield(...)}. *

* Example: *


           * For(getPersons(), person ->
           *     For(person.getTweets(), tweet ->
           *         For(tweet.getReplies())
           *             .yield(reply -> person + ", " + tweet + ", " + reply)));
           * 
* * @param ts An iterable * @param f A function {@code T -> Iterable} * @param element type of {@code ts} * @param component type of the resulting {@code Iterator} * @return A new Iterator */ public static $IteratorType For(Iterable ts, Function> f) { return $IteratorType.ofAll(ts).flatMap(f); } ${monadicTypesFor.gen(mtype => (1 to N).gen(i => { val forClassName = if (mtype == "Iterable") { s"For$i" } else { s"For$i$mtype" } val generics = (1 to i).gen(j => s"T$j")(", ") val params = (1 to i).gen(j => s"$mtype ts$j")(", ") xs""" /$javadoc * Creates a {@code For}-comprehension of ${i.numerus(mtype)}. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param ts$j the ${j.ordinal} $mtype")("\n")} ${(1 to i).gen(j => s"* @param component type of the ${j.ordinal} $mtype")("\n")} * @return a new {@code For}-comprehension of arity $i */ public static <$generics> $forClassName<$generics> For($params) { ${(1 to i).gen(j => xs"""$Objects.requireNonNull(ts$j, "ts$j is null");""")("\n")} return new $forClassName<>(${(1 to i).gen(j => s"ts$j")(", ")}); } """ })("\n\n"))("\n\n")} ${monadicTypesFor.gen(mtype => (1 to N).gen(i => { val rtype = if (mtype == "Iterable") { IteratorType } else { mtype } val cons: String => String = if (mtype == "Iterable") { m => s"$IteratorType.ofAll($m)" } else { m => m } val forClassName = if (mtype == "Iterable") { s"For$i" } else { s"For$i$mtype" } val generics = (1 to i).gen(j => s"T$j")(", ") val functionType = i match { case 1 => FunctionType case 2 => BiFunctionType case _ => s"Function$i" } val args = (1 to i).gen(j => s"? super T$j")(", ") xs""" /$javadoc * For-comprehension with ${i.numerus(mtype)}. */ public static class $forClassName<$generics> { ${(1 to i).gen(j => xs"""private final $mtype ts$j;""")("\n")} private $forClassName(${(1 to i).gen(j => s"$mtype ts$j")(", ")}) { ${(1 to i).gen(j => xs"""this.ts$j = ts$j;""")("\n")} } /$javadoc * Yields a result for elements of the cross product of the underlying ${i.plural(mtype)}. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code $rtype} elements * @return an {@code $rtype} of mapped results */ public $rtype yield($functionType<$args, ? extends R> f) { $Objects.requireNonNull(f, "f is null"); ${if (i == 1) xs""" return ${cons("ts1")}.map(f); """ else xs""" return ${(1 until i).gen(j => s"${cons(s"ts$j")}.flatMap(t$j ->")("\n")} ${cons(s"ts$i")}.map(t$i -> f.apply(${(1 to i).gen(j => s"t$j")(", ")}))${")" * (i - 1)}; """} } ${(i == 1).gen(xs""" /$javadoc * A shortcut for {@code yield(Function.identity())}. * * @return an {@code Iterator} of mapped results */ public $rtype yield() { return yield(Function.identity()); } """)} } """ })("\n\n"))("\n\n")} """ } def genMatch(im: ImportManager, packageName: String, className: String): String = xs""" // // Structural Pattern Matching // // -- static Match API /** * Entry point of the match API. * * @param value a value to be matched * @param type of the value * @return a new {@code Match} instance */ @GwtIncompatible public static Match Match(T value) { return new Match<>(value); } // -- static Case API // - Pattern0 @GwtIncompatible public static Case Case(Pattern0 pattern, $FunctionType f) { $Objects.requireNonNull(pattern, "pattern is null"); $Objects.requireNonNull(f, "f is null"); return new Case0<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern0 pattern, $SupplierType supplier) { $Objects.requireNonNull(pattern, "pattern is null"); $Objects.requireNonNull(supplier, "supplier is null"); return new Case0<>(pattern, ignored -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern0 pattern, R retVal) { $Objects.requireNonNull(pattern, "pattern is null"); return new Case0<>(pattern, ignored -> retVal); } ${(1 to N).gen(i => { val argTypes = (1 to i).gen(j => s"? super T$j")(", ") val generics = (1 to i).gen(j => s"T$j")(", ") val params = (i > 1).gen("(") + (1 to i).gen(j => s"_$j")(", ") + (i > 1).gen(")") val functionType = i match { case 1 => FunctionType case 2 => BiFunctionType case _ => s"Function$i" } xs""" // - Pattern$i @GwtIncompatible public static Case Case(Pattern$i pattern, $functionType<$argTypes, ? extends R> f) { $Objects.requireNonNull(pattern, "pattern is null"); $Objects.requireNonNull(f, "f is null"); return new Case$i<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern$i pattern, $SupplierType supplier) { $Objects.requireNonNull(pattern, "pattern is null"); $Objects.requireNonNull(supplier, "supplier is null"); return new Case$i<>(pattern, $params -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern$i pattern, R retVal) { $Objects.requireNonNull(pattern, "pattern is null"); return new Case$i<>(pattern, $params -> retVal); } """ })("\n\n")} // PRE-DEFINED PATTERNS // 1) Atomic patterns $$(), $$(value), $$(predicate) /** * Wildcard pattern, matches any value. * * @param injected type of the underlying value * @return a new {@code Pattern0} instance */ @GwtIncompatible public static Pattern0 $$() { return Pattern0.any(); } /** * Value pattern, checks for equality. * * @param type of the prototype * @param prototype the value that should be equal to the underlying object * @return a new {@code Pattern0} instance */ @GwtIncompatible public static Pattern0 $$(T prototype) { return new Pattern0() { private static final long serialVersionUID = 1L; @Override public T apply(T obj) { return obj; } @Override public boolean isDefinedAt(T obj) { return $Objects.equals(obj, prototype); } }; } /** * Guard pattern, checks if a predicate is satisfied. *

* This method is intended to be used with lambdas and method references, for example: * *


           * String evenOrOdd(int num) {
           *     return Match(num).of(
           *             Case($$(i -> i % 2 == 0), "even"),
           *             Case($$(this::isOdd), "odd")
           *     );
           * }
           *
           * boolean isOdd(int i) {
           *     return i % 2 == 1;
           * }
           * 
* * It is also valid to pass {@code Predicate} instances: * *

           * Predicate<Integer> isOdd = i -> i % 2 == 1;
           *
           * Match(num).of(
           *         Case($$(i -> i % 2 == 0), "even"),
           *         Case($$(isOdd), "odd")
           * );
           * 
* * Note: Please take care when matching {@code Predicate} instances. In general, * function equality * is an undecidable problem in computer science. In Vavr we are only able to check, * if two functions are the same instance. *

* However, this code will fail: * *


           * Predicate<Integer> p = i -> true;
           * Match(p).of(
           *     Case($$(p), 1) // WRONG! It calls $$(Predicate)
           * );
           * 
* * Instead we have to use {@link Predicates#is(Object)}: * *

           * Predicate<Integer> p = i -> true;
           * Match(p).of(
           *     Case($$(is(p)), 1) // CORRECT! It calls $$(T)
           * );
           * 
* * @param type of the prototype * @param predicate the predicate that tests a given value * @return a new {@code Pattern0} instance */ @GwtIncompatible public static Pattern0 $$($PredicateType predicate) { $Objects.requireNonNull(predicate, "predicate is null"); return new Pattern0() { private static final long serialVersionUID = 1L; @Override public T apply(T obj) { return obj; } @Override public boolean isDefinedAt(T obj) { return predicate.test(obj); } }; } /** * Scala-like structural pattern matching for Java. Instances are obtained via {@link API#Match(Object)}. * @param type of the object that is matched */ @GwtIncompatible public static final class Match { private final T value; private Match(T value) { this.value = value; } @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final R of(Case... cases) { Objects.requireNonNull(cases, "cases is null"); for (Case _case : cases) { final Case __case = (Case) _case; if (__case.isDefinedAt(value)) { return __case.apply(value); } } throw new MatchError(value); } @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final $OptionType option(Case... cases) { Objects.requireNonNull(cases, "cases is null"); for (Case _case : cases) { final Case __case = (Case) _case; if (__case.isDefinedAt(value)) { return $OptionType.some(__case.apply(value)); } } return $OptionType.none(); } // -- CASES public interface Case extends $PartialFunctionType { /** * The serial version uid. */ long serialVersionUID = 1L; } public static final class Case0 implements Case { private static final long serialVersionUID = 1L; private final Pattern0 pattern; private final $FunctionType f; private Case0(Pattern0 pattern, $FunctionType f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return f.apply(pattern.apply(obj)); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } ${(1 to N).gen(i => { val argTypes = (1 to i).gen(j => s"? super T$j")(", ") val generics = (1 to i).gen(j => s"T$j")(", ") val functionType = i match { case 1 => FunctionType case 2 => BiFunctionType case _ => s"Function$i" } xs""" public static final class Case$i implements Case { private static final long serialVersionUID = 1L; private final Pattern$i pattern; private final $functionType<$argTypes, ? extends R> f; private Case$i(Pattern$i pattern, $functionType<$argTypes, ? extends R> f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { ${if (i == 1) xs""" return f.apply(pattern.apply(obj)); """ else xs""" return pattern.apply(obj).apply(f); """} } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } """ })("\n\n")} // -- PATTERNS /** * A Pattern is a partial {@link $FunctionType} in the sense that a function applications returns an * optional result of type {@code Option}. * * @param Class type that is matched by this pattern * @param Type of the single or composite part this pattern decomposes */ // javac needs fqn's here public interface Pattern extends $PartialFunctionType { } // These can't be @FunctionalInterfaces because of ambiguities. // For benchmarks lambda vs. abstract class see http://www.oracle.com/technetwork/java/jvmls2013kuksen-2014088.pdf public static abstract class Pattern0 implements Pattern { private static final long serialVersionUID = 1L; private static final Pattern0 ANY = new Pattern0() { private static final long serialVersionUID = 1L; @Override public Object apply(Object obj) { return obj; } @Override public boolean isDefinedAt(Object obj) { return true; } }; @SuppressWarnings("unchecked") public static Pattern0 any() { return (Pattern0) ANY; } // DEV-NOTE: We need the lower bound `Class` instead of the more appropriate `Class` // because it allows us to create patterns for generic types, which would otherwise not be // possible: `Pattern0> p = Pattern0.of(Some.class);` public static Pattern0 of(Class type) { return new Pattern0() { private static final long serialVersionUID = 1L; @Override public T apply(T obj) { return obj; } @Override public boolean isDefinedAt(T obj) { return obj != null && type.isAssignableFrom(obj.getClass()); } }; } } ${(1 to N).gen(i => { val declaredGenerics = (1 to i).gen(j => s"T$j extends U$j, U$j")(", ") val resultGenerics = (1 to i).gen(j => s"T$j")(", ") val resultType = if (i == 1) resultGenerics else s"Tuple$i<$resultGenerics>" val unapplyGenerics = (1 to i).gen(j => s"U$j")(", ") val unapplyTupleType = s"Tuple$i<$unapplyGenerics>" val args = (1 to i).gen(j => s"Pattern p$j")(", ") xs""" public static abstract class Pattern$i implements Pattern { private static final long serialVersionUID = 1L; public static Pattern$i of(Class type, $args, Function unapply) { return new Pattern$i() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public $resultType apply(T obj) { ${if (i == 1) xs""" return (T1) unapply.apply(obj)._1; """ else xs""" return ($resultType) unapply.apply(obj); """} } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final $unapplyTupleType u = unapply.apply(obj); return ${(1 to i).gen(j => s"((Pattern) p$j).isDefinedAt(u._$j)")(" &&\n")}; } } }; } } """ })("\n\n")} } """ def genShortcuts(im: ImportManager, packageName: String, className: String): String = { val FormatterType = im.getType("java.util.Formatter") val PrintStreamType = im.getType("java.io.PrintStream") xs""" // // Shortcuts // /** * A temporary replacement for an implementations used during prototyping. *

* Example: * *


           * public HttpResponse getResponse(HttpRequest request) {
           *     return TODO();
           * }
           *
           * final HttpResponse response = getHttpResponse(TODO());
           * 
* * @param The result type of the missing implementation. * @return Nothing - this methods always throws. * @throws NotImplementedError when this methods is called * @see NotImplementedError#NotImplementedError() */ public static T TODO() { throw new NotImplementedError(); } /** * A temporary replacement for an implementations used during prototyping. *

* Example: * *


           * public HttpResponse getResponse(HttpRequest request) {
           *     return TODO("fake response");
           * }
           *
           * final HttpResponse response = getHttpResponse(TODO("fake request"));
           * 
* * @param msg An error message * @param The result type of the missing implementation. * @return Nothing - this methods always throws. * @throws NotImplementedError when this methods is called * @see NotImplementedError#NotImplementedError(String) */ public static T TODO(String msg) { throw new NotImplementedError(msg); } /** * Shortcut for {@code System.out.print(obj)}. See {@link $PrintStreamType#print(Object)}. * * @param obj The Object to be printed */ public static void print(Object obj) { System.out.print(obj); } /** * Shortcut for {@code System.out.printf(format, args)}. See {@link $PrintStreamType#printf(String, Object...)}. * * @param format A format string as described in {@link $FormatterType}. * @param args Arguments referenced by the format specifiers */ @GwtIncompatible public static void printf(String format, Object... args) { System.out.printf(format, args); } /** * Shortcut for {@code System.out.println(obj)}. See {@link $PrintStreamType#println(Object)}. * * @param obj The Object to be printed */ public static void println(Object obj) { System.out.println(obj); } /** * Shortcut for {@code System.out.println()}. See {@link $PrintStreamType#println()}. */ public static void println() { System.out.println(); } """ } xs""" /** * The most basic Vavr functionality is accessed through this API class. * *

         * import static io.vavr.API.*;
         * 
* *

For-comprehension

*

* The {@code For}-comprehension is syntactic sugar for nested for-loops. We write * *


         * // lazily evaluated
         * Iterator<R> result = For(iterable1, iterable2, ..., iterableN).yield(f);
         * 
* * or * *

         * Iterator<R> result =
         *     For(iterable1, v1 ->
         *         For(iterable2, v2 ->
         *             ...
         *             For(iterableN).yield(vN -> f.apply(v1, v2, ..., vN))
         *         )
         *     );
         * 
* * instead of * *

         * for(T1 v1 : iterable1) {
         *     for (T2 v2 : iterable2) {
         *         ...
         *         for (TN vN : iterableN) {
         *             R result = f.apply(v1, v2, ..., VN);
         *             //
         *             // We are forced to perform side effects to do s.th. meaningful with the result.
         *             //
         *         }
         *     }
         * }
         * 
* * Please note that values like Option, Try, Future, etc. are also iterable. *

* Given a suitable function * f: {@code (v1, v2, ..., vN) -> ...} and 1 <= N <= 8 iterables, the result is a Stream of the * mapped cross product elements. * *


         * { f(v1, v2, ..., vN) | v1 ∈ iterable1, ... vN ∈ iterableN }
         * 
* * As with all Vavr Values, the result of a For-comprehension can be converted * to standard Java library and Vavr types. * @author Daniel Dietrich */ public final class API { private API() { } ${genShortcuts(im, packageName, className)} ${genAliases(im, packageName, className)} ${genJavaTypeTweaks(im, packageName, className)} ${genFor(im, packageName, className)} ${genMatch(im, packageName, className)} } """ } } /** * Generator of Functions */ def genFunctions(): Unit = { (0 to N).foreach(i => { genVavrFile("io.vavr", s"CheckedFunction$i")(genFunction("CheckedFunction", checked = true)) genVavrFile("io.vavr", s"Function$i")(genFunction("Function", checked = false)) def genFunction(name: String, checked: Boolean)(im: ImportManager, packageName: String, className: String): String = { val generics = (1 to i).gen(j => s"T$j")(", ") val fullGenerics = s"<${(i > 0).gen(s"$generics, ")}R>" val wideGenerics = (1 to i).gen(j => s"? super T$j")(", ") val fullWideGenerics = s"<${(i > 0).gen(s"$wideGenerics, ")}? extends R>" val genericsReversed = (1 to i).reverse.gen(j => s"T$j")(", ") val genericsTuple = if (i > 0) s"<$generics>" else "" val genericsFunction = if (i > 0) s"$generics, " else "" val genericsReversedFunction = if (i > 0) s"$genericsReversed, " else "" val genericsOptionReturnType = s"<${(i > 0).gen(s"$generics, ")}${im.getType("io.vavr.control.Option")}>" val genericsTryReturnType = s"<${(i > 0).gen(s"$generics, ")}${im.getType("io.vavr.control.Try")}>" val curried = if (i == 0) "v" else (1 to i).gen(j => s"t$j")(" -> ") val paramsDecl = (1 to i).gen(j => s"T$j t$j")(", ") val params = (1 to i).gen(j => s"t$j")(", ") val paramsReversed = (1 to i).reverse.gen(j => s"t$j")(", ") val tupled = (1 to i).gen(j => s"t._$j")(", ") val compositionType = if(checked) "CheckedFunction1" else im.getType("java.util.function.Function") // imports val Objects = im.getType("java.util.Objects") val Try = if (checked) im.getType("io.vavr.control.Try") else "" val Serializable = im.getType("java.io.Serializable") val additionalExtends = (checked, i) match { case (false, 0) => ", " + im.getType("java.util.function.Supplier") + "" case (false, 1) => ", " + im.getType("java.util.function.Function") + "" case (false, 2) => ", " + im.getType("java.util.function.BiFunction") + "" case _ => "" } def fullGenericsTypeF(checked: Boolean, i: Int): String = (checked, i) match { case (true, _) => im.getType(s"io.vavr.CheckedFunction$i") + fullWideGenerics case (false, 0) => im.getType("java.util.function.Supplier") + "" case (false, 1) => im.getType("java.util.function.Function") + "" case (false, 2) => im.getType("java.util.function.BiFunction") + "" case (false, _) => im.getType(s"io.vavr.Function$i") + fullWideGenerics } val fullGenericsType = fullGenericsTypeF(checked, i) val refApply = i match { case 0 => "get" case _ => "apply" } val callApply = s"$refApply($params)" def curriedType(max: Int, function: String, idx: Int = 1): String = max match { case 0 => s"$className" case 1 => s"${function}1" case _ => s"Function1" } def arguments(count: Int): String = count match { case 0 => "no arguments" case 1 => "one argument" case 2 => "two arguments" case 3 => "three arguments" case _ => s"$i arguments" } if (checked) { im.getStatic(s"io.vavr.${className}Module.sneakyThrow") } xs""" /** * Represents a function with ${arguments(i)}. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param argument $j of the function")("\n")} * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface $className$fullGenerics extends $Serializable$additionalExtends { /$javadoc * The serial version uid. */ long serialVersionUID = 1L; /$javadoc * Returns a function that always returns the constant * value that you give in parameter. * ${(1 to i).gen(j => s"* @param generic parameter type $j of the resulting function")("\n")} * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static $fullGenerics $className$fullGenerics constant(R value) { return ($params) -> value; } /$javadoc * Creates a {@code $className} based on * * * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
               * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
               *
               * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
               * Function1<Integer, Integer> add2 = Function1.of(this::method);
               *
               * // using a lambda reference
               * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
               * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
               * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
               *
               * // type of a method reference
               * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
               *
               * // type of a lambda reference
               * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
               * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} ${(0 to i).gen(j => if (j == 0) "* @param return type" else s"* @param ${j.ordinal} argument")("\n")} * @return a {@code $className} */ static $fullGenerics $className$fullGenerics of($className$fullGenerics methodReference) { return methodReference; } /$javadoc * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) ${(0 to i).gen(j => if (j == 0) "* @param return type" else s"* @param ${j.ordinal} argument")("\n")} * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static $fullGenerics ${im.getType(s"io.vavr.Function$i")}$genericsOptionReturnType lift($fullGenericsType partialFunction) { ${ val func = "partialFunction" val supplier = if (!checked && i == 0) s"$func::get" else if (checked && i == 0) s"$func::apply" else s"() -> $func.apply($params)" val lambdaArgs = if (i == 1) params else s"($params)" xs""" return $lambdaArgs -> ${im.getType("io.vavr.control.Try")}.of($supplier).toOption(); """ } } /$javadoc * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) ${(0 to i).gen(j => if (j == 0) "* @param return type" else s"* @param ${j.ordinal} argument")("\n")} * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static $fullGenerics ${im.getType(s"io.vavr.Function$i")}$genericsTryReturnType liftTry($fullGenericsType partialFunction) { ${ val supplier = if (!checked && i == 0) "partialFunction::get" else if (checked && i == 0) "partialFunction::apply" else s"() -> partialFunction.apply($params)" val lambdaArgs = if (i == 1) params else s"($params)" xs""" return $lambdaArgs -> ${im.getType("io.vavr.control.Try")}.of($supplier); """ } } /$javadoc * Narrows the given {@code $className$fullWideGenerics} to {@code $className$fullGenerics} * * @param f A {@code $className} ${(0 to i).gen(j => if (j == 0) "* @param return type" else s"* @param ${j.ordinal} argument")("\n")} * @return the given {@code f} instance as narrowed type {@code $className$fullGenerics} */ @SuppressWarnings("unchecked") static $fullGenerics $className$fullGenerics narrow($className$fullWideGenerics f) { return ($className$fullGenerics) f; } ${(i == 1).gen(xs""" /$javadoc * Returns the identity $className, i.e. the function that returns its input. * * @param argument type (and return type) of the identity function * @return the identity $className */ static ${name}1 identity() { return t -> t; } """)} /$javadoc * Applies this function to ${arguments(i)} and returns the result. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param t$j argument $j")("\n")} * @return the result of function application * ${checked.gen("@throws Throwable if something goes wrong applying this function to the given arguments")} */ R apply($paramsDecl)${checked.gen(" throws Throwable")}; ${(1 until i).gen(j => { val partialApplicationArgs = (1 to j).gen(k => s"T$k t$k")(", ") val resultFunctionGenerics = (j+1 to i).gen(k => s"T$k")(", ") val resultFunctionArgs = (j+1 to i).gen(k => s"T$k t$k")(", ") val fixedApplyArgs = (1 to j).gen(k => s"t$k")(", ") val variableApplyArgs = (j+1 to i).gen(k => s"t$k")(", ") xs""" /$javadoc * Applies this function partially to ${j.numerus("argument")}. * ${(1 to j).gen(k => s"* @param t$k argument $k")("\n")} * @return a partial application of this function */ default $name${i - j}<$resultFunctionGenerics, R> apply($partialApplicationArgs) { return ($resultFunctionArgs) -> apply($fixedApplyArgs, $variableApplyArgs); } """ })("\n\n")} ${(i == 0 && !checked).gen( xs""" /$javadoc * Implementation of {@linkplain java.util.function.Supplier#get()}, just calls {@linkplain #apply()}. * * @return the result of {@code apply()} */ @Override default R get() { return apply(); } """ )} /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return $i; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default ${curriedType(i, name)} curried() { return ${if (i < 2) "this" else s"$curried -> apply($params)"}; } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default ${name}1 tupled() { return t -> apply($tupled); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default $className<${genericsReversedFunction}R> reversed() { return ${if (i < 2) "this" else s"($paramsReversed) -> apply($params)"}; } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default $className$fullGenerics memoized() { if (isMemoized()) { return this; } else { ${if (i == 0) xs""" ${if (checked) xs""" final Lazy lazy = Lazy.of(() -> { try { return apply(); } catch (Throwable x) { throw new RuntimeException(x); } }); return (CheckedFunction0 & Memoized) () -> { try { return lazy.get(); } catch(RuntimeException x) { throw x.getCause(); } }; """ else xs""" return ($className$fullGenerics & Memoized) Lazy.of(this)::get; """} """ else if (i == 1) xs""" final ${im.getType("java.util.Map")}<$generics, R> cache = new ${im.getType("java.util.HashMap")}<>(); return ($className$fullGenerics & Memoized) ($params) -> { synchronized (cache) { if (cache.containsKey($params)) { return cache.get($params); } else { final R value = apply($params); cache.put($params, value); return value; } } }; """ else xs""" final ${im.getType("java.util.Map")}, R> cache = new ${im.getType("java.util.HashMap")}<>(); return ($className$fullGenerics & Memoized) ($params) -> { final Tuple$i$genericsTuple key = Tuple.of($params); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; """} } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } ${(i == 1 && !checked).gen(xs""" /$javadoc * Converts this {@code Function1} to a {@link PartialFunction} by adding an {@code isDefinedAt} condition. *

* @param isDefinedAt a predicate that states if an element is in the domain of the returned {@code PartialFunction}. * @return a new {@code PartialFunction} that has the same behavior like this function but is defined only for those elements that make it through the given {@code Predicate} * @throws NullPointerException if {@code isDefinedAt} is null */ default PartialFunction partial(${im.getType("java.util.function.Predicate")} isDefinedAt) { Objects.requireNonNull(isDefinedAt, "isDefinedAt is null"); final Function1 self = this; return new PartialFunction() { private static final long serialVersionUID = 1L; @Override public boolean isDefinedAt(T1 t1) { return isDefinedAt.test(t1); } @Override public R apply(T1 t1) { return self.apply(t1); } }; } """)} ${checked.gen(xs""" /$javadoc * Return a composed function that first applies this $className to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function$i$fullGenerics recover(${im.getType("java.util.function.Function")} recover) { Objects.requireNonNull(recover, "recover is null"); return ($params) -> { try { return this.apply($params); } catch (Throwable throwable) { final ${fullGenericsTypeF(checked = false, i)} func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.$callApply; } }; } /$javadoc * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function$i that throws a {@code Throwable}. */ default Function$i$fullGenerics unchecked() { return ($params) -> { try { return apply($params); } catch(Throwable t) { return sneakyThrow(t); } }; } """)} /$javadoc * Returns a composed function that first applies this $className to the given argument and then applies * {@linkplain $compositionType} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default $className<${genericsFunction}V> andThen($compositionType after) { $Objects.requireNonNull(after, "after is null"); return ($params) -> after.apply(apply($params)); } ${(i == 1).gen(xs""" /$javadoc * Returns a composed function that first applies the {@linkplain $compositionType} {@code before} the * given argument and then applies this $className to the result. * * @param argument type of before * @param before the function applied before this * @return a function composed of before and this * @throws NullPointerException if before is null */ default ${name}1 compose($compositionType before) { $Objects.requireNonNull(before, "before is null"); return v -> apply(before.apply(v)); } """)} } ${checked.gen(xs""" interface ${className}Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } } """)} """ } }) } /** * Generator of io.vavr.Tuple* */ def genTuples(): Unit = { genVavrFile("io.vavr", "Tuple")(genBaseTuple) (0 to N).foreach { i => genVavrFile("io.vavr", s"Tuple$i")(genTuple(i)) } /* * Generates Tuple1..N */ def genTuple(i: Int)(im: ImportManager, packageName: String, className: String): String = { val generics = if (i == 0) "" else s"<${(1 to i).gen(j => s"T$j")(", ")}>" val paramsDecl = (1 to i).gen(j => s"T$j t$j")(", ") val params = (1 to i).gen(j => s"_$j")(", ") val paramTypes = (1 to i).gen(j => s"? super T$j")(", ") val resultGenerics = if (i == 0) "" else s"<${(1 to i).gen(j => s"U$j")(", ")}>" val mapResult = i match { case 0 => "" case 1 => "? extends U1" case _ => s"Tuple$i<${(1 to i).gen(j => s"U$j")(", ")}>" } val comparableGenerics = if (i == 0) "" else s"<${(1 to i).gen(j => s"U$j extends Comparable")(", ")}>" val untyped = if (i == 0) "" else s"<${(1 to i).gen(j => "?")(", ")}>" val functionType = i match { case 0 => im.getType("java.util.function.Supplier") case 1 => im.getType("java.util.function.Function") case 2 => im.getType("java.util.function.BiFunction") case _ => s"Function$i" } val Comparator = im.getType("java.util.Comparator") val Objects = im.getType("java.util.Objects") val Seq = im.getType("io.vavr.collection.Seq") val List = im.getType("io.vavr.collection.List") if(i==2){ im.getType("java.util.Map") im.getType("java.util.AbstractMap") } xs""" /** * A tuple of ${i.numerus("element")} which can be seen as cartesian product of ${i.numerus("component")}. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param type of the ${j.ordinal} element")("\n")} * @author Daniel Dietrich */ public final class $className$generics implements Tuple, Comparable<$className$generics>, ${im.getType("java.io.Serializable")} { private static final long serialVersionUID = 1L; ${(1 to i).gen(j => xs""" /$javadoc * The ${j.ordinal} element of this tuple. */ public final T$j _$j; """)("\n\n")} ${if (i == 0) xs""" /$javadoc * The singleton instance of Tuple0. */ private static final Tuple0 INSTANCE = new Tuple0 (); /$javadoc * The singleton Tuple0 comparator. */ private static final Comparator COMPARATOR = (Comparator & Serializable) (t1, t2) -> 0; // hidden constructor, internally called private Tuple0 () { } /$javadoc * Returns the singleton instance of Tuple0. * * @return The singleton instance of Tuple0. */ public static Tuple0 instance() { return INSTANCE; } """ else xs""" /$javadoc * Constructs a tuple of ${i.numerus("element")}. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param t$j the ${j.ordinal} element")("\n")} */ public $className($paramsDecl) { ${(1 to i).gen(j => s"this._$j = t$j;")("\n")} } """} public static $generics $Comparator<$className$generics> comparator(${(1 to i).gen(j => s"$Comparator t${j}Comp")(", ")}) { ${if (i == 0) xs""" return COMPARATOR; """ else xs""" return (Comparator<$className$generics> & Serializable) (t1, t2) -> { ${(1 to i).gen(j => xs""" final int check$j = t${j}Comp.compare(t1._$j, t2._$j); if (check$j != 0) { return check$j; } """)("\n\n")} // all components are equal return 0; }; """} } ${(i > 0).gen(xs""" @SuppressWarnings("unchecked") private static $comparableGenerics int compareTo($className$untyped o1, $className$untyped o2) { final $className$resultGenerics t1 = ($className$resultGenerics) o1; final $className$resultGenerics t2 = ($className$resultGenerics) o2; ${(1 to i).gen(j => xs""" final int check$j = t1._$j.compareTo(t2._$j); if (check$j != 0) { return check$j; } """)("\n\n")} // all components are equal return 0; } """)} @Override public int arity() { return $i; } @Override public int compareTo($className$generics that) { ${if (i == 0) xs""" return 0; """ else xs""" return $className.compareTo(this, that); """} } ${(1 to i).gen(j => xs""" /$javadoc * Getter of the ${j.ordinal} element of this tuple. * * @return the ${j.ordinal} element of this Tuple. */ public T$j _$j() { return _$j; } /$javadoc * Sets the ${j.ordinal} element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the ${j.ordinal} element of this Tuple. */ public $className$generics update$j(T$j value) { return new $className<>(${(1 until j).gen(k => s"_$k")(", ")}${(j > 1).gen(", ")}value${(j < i).gen(", ")}${((j + 1) to i).gen(k => s"_$k")(", ")}); } """)("\n\n")} ${(i == 2).gen(xs""" /$javadoc * Swaps the elements of this {@code Tuple}. * * @return A new Tuple where the first element is the second element of this Tuple * and the second element is the first element of this Tuple. */ public Tuple2 swap() { return Tuple.of(_2, _1); } /$javadoc * Converts the tuple to java.util.Map.Entry {@code Tuple}. * * @return A java.util.Map.Entry where the first element is the key and the second * element is the value. */ public Map.Entry$generics toEntry() { return new AbstractMap.SimpleEntry<>(_1, _2); } """)} ${(i > 0).gen(xs""" /$javadoc * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function ${(1 to i).gen(j => s"* @param new type of the ${j.ordinal} component")("\n")} * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public $resultGenerics $className$resultGenerics map($functionType<$paramTypes, $mapResult> mapper) { Objects.requireNonNull(mapper, "mapper is null"); ${if (i == 1) "return Tuple.of(mapper.apply(_1));" else s"return mapper.apply($params);" } } """)} ${(i > 1).gen(xs""" /$javadoc * Maps the components of this tuple using a mapper function for each component. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param f$j the mapper function of the ${j.ordinal} component")("\n")} ${(1 to i).gen(j => s"* @param new type of the ${j.ordinal} component")("\n")} * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public $resultGenerics $className$resultGenerics map(${(1 to i).gen(j => s"${im.getType("java.util.function.Function")} f$j")(", ")}) { ${(1 to i).gen(j => s"""Objects.requireNonNull(f$j, "f$j is null");""")("\n")} return ${im.getType("io.vavr.Tuple")}.of(${(1 to i).gen(j => s"f$j.apply(_$j)")(", ")}); } """)} ${(i > 1) gen (1 to i).gen(j => xs""" /$javadoc * Maps the ${j.ordinal} component of this tuple to a new value. * * @param new type of the ${j.ordinal} component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted ${j.ordinal} component */ public $className<${(1 to i).gen(k => if (j == k) "U" else s"T$k")(", ")}> map$j(${im.getType("java.util.function.Function")} mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_$j); return Tuple.of(${(1 to i).gen(k => if (j == k) "u" else s"_$k")(", ")}); } """)("\n\n")} /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ ${if (i == 0) xs""" public U apply($functionType f) { $Objects.requireNonNull(f, "f is null"); return f.get(); } """ else xs""" public U apply($functionType<$paramTypes, ? extends U> f) { $Objects.requireNonNull(f, "f is null"); return f.apply($params); } """} @Override public $Seq toSeq() { ${if (i == 0) xs""" return $List.empty(); """ else xs""" return $List.of($params); """} } ${(i < N).gen(xs""" /$javadoc * Append a value to this tuple. * * @param type of the value to append * @param t${i+1} the value to append * @return a new Tuple with the value appended */ public Tuple${i+1}<${(1 to i+1).gen(j => s"T$j")(", ")}> append(T${i+1} t${i+1}) { return ${im.getType("io.vavr.Tuple")}.of(${(1 to i).gen(k => s"_$k")(", ")}${(i > 0).gen(", ")}t${i+1}); } """)} ${(i < N) gen (1 to N-i).gen(j => xs""" /$javadoc * Concat a tuple's values to this tuple. * ${(i+1 to i+j).gen(k => s"* @param the type of the ${k.ordinal} value in the tuple")("\n")} * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public <${(i+1 to i+j).gen(k => s"T$k")(", ")}> Tuple${i+j}<${(1 to i+j).gen(k => s"T$k")(", ")}> concat(Tuple$j<${(i+1 to i+j).gen(k => s"T$k")(", ")}> tuple) { Objects.requireNonNull(tuple, "tuple is null"); return ${im.getType("io.vavr.Tuple")}.of(${(1 to i).gen(k => s"_$k")(", ")}${(i > 0).gen(", ")}${(1 to j).gen(k => s"tuple._$k")(", ")}); } """)("\n\n")} // -- Object @Override public boolean equals(Object o) { ${if (i == 0) xs""" return o == this; """ else xs""" if (o == this) { return true; } else if (!(o instanceof $className)) { return false; } else { final $className$untyped that = ($className$untyped) o; return ${(1 to i).gen(j => s"${im.getType("java.util.Objects")}.equals(this._$j, that._$j)")("\n && ")}; }""" } } @Override public int hashCode() { return ${if (i == 0) "1" else s"""Tuple.hash(${(1 to i).gen(j => s"_$j")(", ")})"""}; } @Override public String toString() { return ${if (i == 0) "\"()\"" else s""""(" + ${(1 to i).gen(j => s"_$j")(" + \", \" + ")} + ")""""}; } ${(i == 0).gen(xs""" // -- Serializable implementation /$javadoc * Instance control for object serialization. * * @return The singleton instance of Tuple0. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } """)} } """ } /* * Generates Tuple */ def genBaseTuple(im: ImportManager, packageName: String, className: String): String = { val Map = im.getType("java.util.Map") val Objects = im.getType("java.util.Objects") val Seq = im.getType("io.vavr.collection.Seq") def genFactoryMethod(i: Int) = { val generics = (1 to i).gen(j => s"T$j")(", ") val paramsDecl = (1 to i).gen(j => s"T$j t$j")(", ") val params = (1 to i).gen(j => s"t$j")(", ") val wideGenerics = (1 to i).gen(j => s"? extends T$j")(", ") xs""" /** * Creates a tuple of ${i.numerus("element")}. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param type of the ${j.ordinal} element")("\n")} ${(1 to i).gen(j => s"* @param t$j the ${j.ordinal} element")("\n")} * @return a tuple of ${i.numerus("element")}. */ static <$generics> Tuple$i<$generics> of($paramsDecl) { return new Tuple$i<>($params); } """ } def genHashMethod(i: Int) = { val paramsDecl = (1 to i).gen(j => s"Object o$j")(", ") xs""" /** * Return the order-dependent hash of the ${i.numerus("given value")}. ${(0 to i).gen(j => if (j == 0) "*" else s"* @param o$j the ${j.ordinal} value to hash")("\n")} * @return the same result as {@link $Objects#${if (i == 1) "hashCode(Object)" else "hash(Object...)"}} */ static int hash($paramsDecl) { ${if (i == 1) { s"return $Objects.hashCode(o1);" } else { xs""" int result = 1; ${(1 to i).gen(j => s"result = 31 * result + hash(o$j);")("\n")} return result; """ }} } """ } def genNarrowMethod(i: Int) = { val generics = (1 to i).gen(j => s"T$j")(", ") val wideGenerics = (1 to i).gen(j => s"? extends T$j")(", ") xs""" /** * Narrows a widened {@code Tuple$i<$wideGenerics>} to {@code Tuple$i<$generics>}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple$i}. ${(1 to i).gen(j => s"* @param the ${j.ordinal} component type")("\n")} * @return the given {@code t} instance as narrowed type {@code Tuple$i<$generics>}. */ @SuppressWarnings("unchecked") static <$generics> Tuple$i<$generics> narrow(Tuple$i<$wideGenerics> t) { return (Tuple$i<$generics>) t; } """ } def genSeqMethod(i: Int) = { val generics = (1 to i).gen(j => s"T$j")(", ") val seqs = (1 to i).gen(j => s"Seq")(", ") val Stream = im.getType("io.vavr.collection.Stream") val widenedGenerics = (1 to i).gen(j => s"? extends T$j")(", ") xs""" /** * Turns a sequence of {@code Tuple$i} into a Tuple$i of {@code Seq}${(i > 1).gen("s")}. * ${(1 to i).gen(j => s"* @param ${j.ordinal} component type")("\n")} * @param tuples an {@code Iterable} of tuples * @return a tuple of ${i.numerus(s"{@link $Seq}")}. */ static <$generics> Tuple$i<$seqs> sequence$i(Iterable> tuples) { $Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = $Stream.ofAll(tuples); return new Tuple$i<>(${(1 to i).gen(j => s"s.map(Tuple$i::_$j)")(s", ")}); } """ } xs""" /** * The base interface of all tuples. * * @author Daniel Dietrich */ public interface Tuple { /** * The maximum arity of an Tuple. *

* Note: This value might be changed in a future version of Vavr. * So it is recommended to use this constant instead of hardcoding the current maximum arity. */ int MAX_ARITY = $N; /** * Returns the number of elements of this tuple. * * @return the number of elements. */ int arity(); /** * Converts this tuple to a sequence. * * @return A new {@code Seq}. */ $Seq toSeq(); // -- factory methods /$javadoc * Creates the empty tuple. * * @return the empty tuple. */ static Tuple0 empty() { return Tuple0.instance(); } /** * Creates a {@code Tuple2} from a {@link $Map.Entry}. * * @param Type of first component (entry key) * @param Type of second component (entry value) * @param entry A {@link java.util.Map.Entry} * @return a new {@code Tuple2} containing key and value of the given {@code entry} */ static Tuple2 fromEntry($Map.Entry entry) { $Objects.requireNonNull(entry, "entry is null"); return new Tuple2<>(entry.getKey(), entry.getValue()); } ${(1 to N).gen(genFactoryMethod)("\n\n")} ${(1 to N).gen(genHashMethod)("\n\n")} ${(1 to N).gen(genNarrowMethod)("\n\n")} ${(1 to N).gen(genSeqMethod)("\n\n")} } """ } } /** * Generator of io.vavr.collection.*ArrayType */ def genArrayTypes(): Unit = { val types = ListMap( "boolean" -> "Boolean", "byte" -> "Byte", "char" -> "Character", "double" -> "Double", "float" -> "Float", "int" -> "Integer", "long" -> "Long", "short" -> "Short", "Object" -> "Object" // fallback ) // note: there is no void[] in Java genVavrFile("io.vavr.collection", "ArrayType")((im: ImportManager, packageName: String, className: String) => xs""" import java.util.Collection; /** * Helper to replace reflective array access. * * @author Pap Lőrinc */ interface ArrayType { @SuppressWarnings("unchecked") static ArrayType obj() { return (ArrayType) ObjectArrayType.INSTANCE; } Class type(); int lengthOf(Object array); T getAt(Object array, int index); Object empty(); void setAt(Object array, int index, T value) throws ClassCastException; Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size); @SuppressWarnings("unchecked") static ArrayType of(Object array) { return of((Class) array.getClass().getComponentType()); } static ArrayType of(Class type) { return !type.isPrimitive() ? obj() : ofPrimitive(type); } @SuppressWarnings("unchecked") static ArrayType ofPrimitive(Class type) { if (boolean.class == type) { return (ArrayType) BooleanArrayType.INSTANCE; } else if (byte.class == type) { return (ArrayType) ByteArrayType.INSTANCE; } else if (char.class == type) { return (ArrayType) CharArrayType.INSTANCE; } else if (double.class == type) { return (ArrayType) DoubleArrayType.INSTANCE; } else if (float.class == type) { return (ArrayType) FloatArrayType.INSTANCE; } else if (int.class == type) { return (ArrayType) IntArrayType.INSTANCE; } else if (long.class == type) { return (ArrayType) LongArrayType.INSTANCE; } else if (short.class == type) { return (ArrayType) ShortArrayType.INSTANCE; } else { throw new IllegalArgumentException(String.valueOf(type)); } } default Object newInstance(int length) { return copy(empty(), length); } /** System.arrayCopy with same source and destination */ default Object copyRange(Object array, int from, int to) { final int length = to - from; return copy(array, length, from, 0, length); } /** Repeatedly group an array into equal sized sub-trees */ default Object grouped(Object array, int groupSize) { final int arrayLength = lengthOf(array); final Object results = obj().newInstance(1 + ((arrayLength - 1) / groupSize)); obj().setAt(results, 0, copyRange(array, 0, groupSize)); for (int start = groupSize, i = 1; start < arrayLength; i++) { final int nextLength = Math.min(groupSize, arrayLength - (i * groupSize)); obj().setAt(results, i, copyRange(array, start, start + nextLength)); start += nextLength; } return results; } /** clone the source and set the value at the given position */ default Object copyUpdate(Object array, int index, T element) { final Object copy = copy(array, index + 1); setAt(copy, index, element); return copy; } default Object copy(Object array, int minLength) { final int arrayLength = lengthOf(array); final int length = Math.max(arrayLength, minLength); return copy(array, length, 0, 0, arrayLength); } /** clone the source and keep everything after the index (pre-padding the values with null) */ default Object copyDrop(Object array, int index) { final int length = lengthOf(array); return copy(array, length, index, index, length - index); } /** clone the source and keep everything before and including the index */ default Object copyTake(Object array, int lastIndex) { return copyRange(array, 0, lastIndex + 1); } /** Create a single element array */ default Object asArray(T element) { final Object result = newInstance(1); setAt(result, 0, element); return result; } /** Store the content of an iterable in an array */ static Object[] asArray(java.util.Iterator it, int length) { final Object[] array = new Object[length]; for (int i = 0; i < length; i++) { array[i] = it.next(); } return array; } @SuppressWarnings("unchecked") static T asPrimitives(Class primitiveClass, Iterable values) { final Object[] array = Array.ofAll(values).toJavaArray(); final ArrayType type = of((Class) primitiveClass); final Object results = type.newInstance(array.length); for (int i = 0; i < array.length; i++) { type.setAt(results, i, (T) array[i]); } return (T) results; } ${types.keys.toSeq.gen(arrayType => genArrayType(arrayType)(im, packageName, arrayType.capitalize + className) )("\n\n")} } """) def genArrayType(arrayType: String)(im: ImportManager, packageName: String, className: String): String = { val wrapperType = types(arrayType) val isPrimitive = arrayType != "Object" xs""" final class $className implements ArrayType<$wrapperType>, ${im.getType("java.io.Serializable")} { private static final long serialVersionUID = 1L; static final $className INSTANCE = new $className(); static final $arrayType[] EMPTY = new $arrayType[0]; private static $arrayType[] cast(Object array) { return ($arrayType[]) array; } @Override public Class<$wrapperType> type() { return $arrayType.class; } @Override public $arrayType[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public $wrapperType getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, $wrapperType value) ${if (isPrimitive) "throws ClassCastException " else ""}{ ${if (isPrimitive) """if (value != null) { | cast(array)[index] = value; |} else { | throw new ClassCastException(); |}""".stripMargin else "cast(array)[index] = value;" } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new $arrayType[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final $arrayType[] result = new $arrayType[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } """ } } } /** * Generate Vavr src-gen/test/java classes */ def generateTestClasses(): Unit = { genAPITests() genFunctionTests() genMapOfEntriesTests() genTupleTests() /** * Generator of Function tests */ def genAPITests(): Unit = { genVavrFile("io.vavr", s"APITest", baseDir = TARGET_TEST)((im: ImportManager, packageName, className) => { val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") val test = im.getType("org.junit.Test") val API = im.getType("io.vavr.API") val AssertionsExtensions = im.getType("io.vavr.AssertionsExtensions") val ListType = im.getType("io.vavr.collection.List") val MapType = im.getType("io.vavr.collection.Map") val OptionType = im.getType("io.vavr.control.Option") val FutureType = im.getType("io.vavr.concurrent.Future") val ExecutorsType = im.getType("java.util.concurrent.Executors") val ExecutorService = s"$ExecutorsType.newSingleThreadExecutor()" val TryType = im.getType("io.vavr.control.Try") val JavaComparatorType = im.getType("java.util.Comparator") val monadicTypesFor = List(OptionType) val monadicFunctionTypesFor = List(FutureType, TryType) val d = "$" im.getStatic("io.vavr.API.*") def genFutureTests(name: String, value: String, success: Boolean): String = { val check = if (success) "isSuccess" else "isFailure" xs""" @$test public void shouldFutureWith${name}ReturnNotNull() { final $FutureType future = Future($value).await(); assertThat(future).isNotNull(); assertThat(future.$check()).isTrue(); } @$test public void shouldFutureWithinExecutorWith${name}ReturnNotNull() { final $FutureType future = Future($ExecutorService, $value).await(); assertThat(future).isNotNull(); assertThat(future.$check()).isTrue(); } """ } def genExtAliasTest(name: String, func: String, value: String, check: String): String = { xs""" @$test public void should$name() { assertThat($func($value)).$check; } """ } def genMediumAliasTest(name: String, func: String, value: String): String = genExtAliasTest(s"${name}ReturnNotNull", func, value, "isNotNull()") def genSimpleAliasTest(name: String, value: String): String = genMediumAliasTest(name, name, value) def genTraversableTests(func: String): String = { xs""" ${genMediumAliasTest(s"Empty$func", func, "")} ${genMediumAliasTest(s"${func}WithSingle", func, "'1'")} ${genMediumAliasTest(s"${func}WithVarArg", func, "'1', '2', '3'")} """ } def genSortedTraversableTests(func: String): String = { xs""" ${genMediumAliasTest(s"Empty$func", func, "")} ${genMediumAliasTest(s"Empty${func}WithComparator", func, s"($JavaComparatorType) Character::compareTo")} ${genMediumAliasTest(s"${func}WithSingle", func, "'1'")} ${genMediumAliasTest(s"${func}WithSingleAndComparator", func, "Character::compareTo, '1'")} ${genMediumAliasTest(s"${func}WithVarArg", func, "'1', '2', '3'")} ${genMediumAliasTest(s"${func}WithVarArgAndComparator", func, s"($JavaComparatorType) Character::compareTo, '1', '2', '3'")} """ } def genMapTests(func: String): String = { xs""" ${genMediumAliasTest(s"Empty$func", func, "")} ${genMediumAliasTest(s"${func}FromSingle", func, "1, '1'")} ${genMediumAliasTest(s"${func}FromTuples", func, "Tuple(1, '1'), Tuple(2, '2'), Tuple(3, '3')")} ${genMediumAliasTest(s"${func}FromPairs", func, "1, '1', 2, '2', 3, '3'")} ${(1 to VARARGS).gen(i => { xs""" @$test public void shouldCreate${func}From${i}Pairs() { $MapType map = $func(${(1 to i).gen(j => s"$j, ${j*2}")(", ")}); ${(1 to i).gen(j => s"assertThat(map.apply($j)).isEqualTo(${j*2});")("\n")} } """ })("\n\n")} """ } def genTryTests(func: String, value: String, success: Boolean): String = { val check = if (success) "isSuccess" else "isFailure" xs""" @$test public void should${func.firstUpper}ReturnNotNull() { final $TryType t = $func($value); assertThat(t).isNotNull(); assertThat(t.$check()).isTrue(); } """ } def genAliasesTests(im: ImportManager, packageName: String, className: String): String = { xs""" ${(0 to N).gen(i => { val params = (1 to i).gen(j => s"v$j")(", ") xs""" @$test public void shouldFunction${i}ReturnNotNull() { assertThat(Function(($params) -> null)).isNotNull(); } @$test public void shouldCheckedFunction${i}ReturnNotNull() { assertThat(CheckedFunction(($params) -> null)).isNotNull(); } """ })("\n\n")} ${(0 to N).gen(i => { val params = (1 to i).gen(j => s"v$j")(", ") genExtAliasTest(s"Unchecked${i}ReturnNonCheckedFunction", "unchecked", s"($params) -> null", s"isInstanceOf(Function$i.class)") })("\n\n")} ${(0 to N).gen(i => { val params = (1 to i).gen(j => s"$j")(", ") xs""" @$test public void shouldTuple${i}ReturnNotNull() { assertThat(Tuple($params)).isNotNull(); } """ })("\n\n")} ${Seq("Right", "Left").gen(name => { xs""" @$test public void should${name}ReturnNotNull() { assertThat($name(null)).isNotNull(); } """ })("\n\n")} ${genFutureTests("Supplier", "() -> 1", success = true)} ${genFutureTests("Value", "1", success = true)} ${genSimpleAliasTest("Lazy", "() -> 1")} ${genSimpleAliasTest("Option", "1")} ${genSimpleAliasTest("Some", "1")} ${genSimpleAliasTest("None", "")} ${genTryTests("Try", "() -> 1", success = true)} ${genTryTests("Success", "1", success = true)} ${genTryTests("Failure", "new Error()", success = false)} ${genSimpleAliasTest("Valid", "1")} ${genSimpleAliasTest("Invalid", "new Error()")} ${genMediumAliasTest("Char", "(Iterable) CharSeq", "'1'")} ${genMediumAliasTest("CharArray", "(Iterable) CharSeq", "'1', '2', '3'")} ${genMediumAliasTest("CharSeq", "(Iterable) CharSeq", "\"123\"")} ${genTraversableTests("Array")} ${genTraversableTests("Vector")} ${genTraversableTests("List")} ${genTraversableTests("Stream")} ${genTraversableTests("Queue")} ${genTraversableTests("LinkedSet")} ${genTraversableTests("Set")} ${genTraversableTests("Seq")} ${genTraversableTests("IndexedSeq")} ${genSortedTraversableTests("SortedSet")} ${genSortedTraversableTests("PriorityQueue")} ${genMapTests("LinkedMap")} ${genMapTests("Map")} ${genMapTests("SortedMap")} ${genMediumAliasTest("EmptySortedMapFromComparator", "SortedMap", "Integer::compareTo")} ${genMediumAliasTest("SortedMapFromSingleAndComparator", "SortedMap", "Integer::compareTo, 1, '1'")} ${genMediumAliasTest("SortedMapFromTuplesAndComparator", "SortedMap", s"($JavaComparatorType)Integer::compareTo, Tuple(1, '1'), Tuple(2, '2'), Tuple(3, '3')")} """ } def genShortcutsTests(im: ImportManager, packageName: String, className: String): String = { val fail = im.getStatic("org.junit.Assert.fail") val captureStdOut = im.getStatic("io.vavr.OutputTester.captureStdOut") xs""" @$test public void shouldCompileTODOAndThrowDefaultMessageAtRuntime() { try { final String s = TODO(); $fail("TODO() should throw. s: " + s); } catch(NotImplementedError err) { assertThat(err.getMessage()).isEqualTo("An implementation is missing."); } } @$test public void shouldCompileTODOAndThrowGivenMessageAtRuntime() { final String msg = "Don't try this in production!"; try { final String s = TODO(msg); $fail("TODO(String) should throw. s: " + s); } catch(NotImplementedError err) { assertThat(err.getMessage()).isEqualTo(msg); } } @$test public void shouldCallprint_Object() { assertThat($captureStdOut(()->print("ok"))).isEqualTo("ok"); } @$test public void shouldCallprintf() { assertThat($captureStdOut(()->printf("%s", "ok"))).isEqualTo("ok"); } @$test public void shouldCallprintln_Object() { assertThat($captureStdOut(()->println("ok"))).isEqualTo("ok\\n"); } @$test public void shouldCallprintln() { assertThat($captureStdOut(()->println())).isEqualTo("\\n"); } """ } xs""" @SuppressWarnings("deprecation") public class $className { @$test public void shouldNotBeInstantiable() { $AssertionsExtensions.assertThat($API.class).isNotInstantiable(); } // -- shortcuts ${genShortcutsTests(im, packageName, className)} // // Alias should return not null. // More specific test for each aliased class implemented in separate test class // ${genAliasesTests(im, packageName, className)} // -- run @$test public void shouldRunUnitAndReturnVoid() { int[] i = { 0 }; Void nothing = run(() -> i[0]++); $assertThat(nothing).isNull(); $assertThat(i[0]).isEqualTo(1); } // -- For @$test public void shouldIterateFor1UsingSimpleYield() { final $ListType list = List.of(1, 2, 3); final $ListType actual = For(list).yield().toList(); $assertThat(actual).isEqualTo(list); } ${(1 to N).gen(i => xs""" @$test public void shouldIterateFor$ListType$i() { final $ListType result = For( ${(1 to i).gen(j => s"$ListType.of(1, 2, 3)")(",\n")} ).yield(${(i > 1).gen("(")}${(1 to i).gen(j => s"i$j")(", ")}${(i > 1).gen(")")} -> ${(1 to i).gen(j => s"i$j")(" + ")}).toList(); $assertThat(result.length()).isEqualTo((int) Math.pow(3, $i)); $assertThat(result.head()).isEqualTo($i); $assertThat(result.last()).isEqualTo(3 * $i); } """)("\n\n")} ${monadicTypesFor.gen(mtype => (1 to N).gen(i => { xs""" @$test public void shouldIterateFor$mtype$i() { final $mtype result = For( ${(1 to i).gen(j => s"$mtype.of($j)")(",\n")} ).yield(${(i > 1).gen("(")}${(1 to i).gen(j => s"i$j")(", ")}${(i > 1).gen(")")} -> ${(1 to i).gen(j => s"i$j")(" + ")}); $assertThat(result.get()).isEqualTo(${(1 to i).sum}); } """})("\n\n"))("\n\n")} ${monadicFunctionTypesFor.gen(mtype => (1 to N).gen(i => { xs""" @$test public void shouldIterateFor$mtype$i() { final $mtype result = For( ${(1 to i).gen(j => s"$mtype.of(() -> $j)")(",\n")} ).yield(${(i > 1).gen("(")}${(1 to i).gen(j => s"i$j")(", ")}${(i > 1).gen(")")} -> ${(1 to i).gen(j => s"i$j")(" + ")}); $assertThat(result.get()).isEqualTo(${(1 to i).sum}); } """})("\n\n"))("\n\n")} @$test public void shouldIterateNestedFor() { final $ListType result = For(${im.getType("java.util.Arrays")}.asList(1, 2), i -> For(${im.getType("io.vavr.collection.List")}.of('a', 'b')).yield(c -> i + ":" + c)).toList(); assertThat(result).isEqualTo($ListType.of("1:a", "1:b", "2:a", "2:b")); } // -- Match @$test public void shouldReturnSomeWhenApplyingCaseGivenPredicateAndSupplier() { final Match.Case _case = Case($$(ignored -> true), ignored -> 1); assertThat(_case.isDefinedAt(null)).isTrue(); assertThat(_case.apply(null)).isEqualTo(1); } @$test public void shouldReturnNoneWhenApplyingCaseGivenPredicateAndSupplier() { assertThat(Case($$(ignored -> false), ignored -> 1).isDefinedAt(null)).isFalse(); } @$test public void shouldReturnSomeWhenApplyingCaseGivenPredicateAndValue() { final Match.Case _case = Case($$(ignored -> true), 1); assertThat(_case.isDefinedAt(null)).isTrue(); assertThat(_case.apply(null)).isEqualTo(1); } @$test public void shouldReturnNoneWhenApplyingCaseGivenPredicateAndValue() { assertThat(Case($$(ignored -> false), 1).isDefinedAt(null)).isFalse(); } // -- Match patterns static class ClzMatch {} static class ClzMatch1 extends ClzMatch {} static class ClzMatch2 extends ClzMatch {} ${(1 to N).gen(i => { im.getStatic("io.vavr.API.*") im.getStatic("io.vavr.Patterns.*") xs""" @$test public void shouldMatchPattern$i() { final Tuple$i<${(1 to i).gen(j => s"Integer")(", ")}> tuple = Tuple.of(${(1 to i).gen(j => s"1")(", ")}); final String func = Match(tuple).of( Case($$Tuple$i($d(0)${(2 to i).gen(j => s", $d()")}), (${(1 to i).gen(j => s"m$j")(", ")}) -> "fail"), Case($$Tuple$i(${(1 to i).gen(j => s"$d()")(", ")}), (${(1 to i).gen(j => s"m$j")(", ")}) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($$Tuple$i($d(0)${(2 to i).gen(j => s", $d()")}), () -> "fail"), Case($$Tuple$i(${(1 to i).gen(j => s"$d()")(", ")}), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($$Tuple$i($d(0)${(2 to i).gen(j => s", $d()")}), "fail"), Case($$Tuple$i(${(1 to i).gen(j => s"$d()")(", ")}), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern$i.of(ClzMatch1.class, ${(1 to i).gen(j => s"$d()")(", ")}, t -> Tuple.of(${(1 to i).gen(j => s"null")(", ")})), "fail"), Case(Match.Pattern$i.of(ClzMatch2.class, ${(1 to i).gen(j => s"$d()")(", ")}, t -> Tuple.of(${(1 to i).gen(j => s"null")(", ")})), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } """ })("\n\n")} } """ }) } /** * Generator of Function tests */ def genFunctionTests(): Unit = { (0 to N).foreach(i => { genVavrFile("io.vavr", s"CheckedFunction${i}Test", baseDir = TARGET_TEST)(genFunctionTest("CheckedFunction", checked = true)) genVavrFile("io.vavr", s"Function${i}Test", baseDir = TARGET_TEST)(genFunctionTest("Function", checked = false)) def genFunctionTest(name: String, checked: Boolean)(im: ImportManager, packageName: String, className: String): String = { val AtomicInteger = im.getType("java.util.concurrent.atomic.AtomicInteger") val functionArgsDecl = (1 to i).gen(j => s"Object o$j")(", ") val functionArgs = (1 to i).gen(j => s"o$j")(", ") val generics = (1 to i + 1).gen(j => "Object")(", ") val test = im.getType("org.junit.Test") val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") val recFuncF1 = if (i == 0) "11;" else s"i1 <= 0 ? i1 : $className.recurrent2.apply(${(1 to i).gen(j => s"i$j" + (j == 1).gen(s" - 1"))(", ")}) + 1;" def curriedType(max: Int, function: String): String = max match { case 0 => s"${function}0" case 1 => s"${function}1" case _ => s"Function1" } val wideGenericArgs = (1 to i).gen(j => "Number")(", ") val wideGenericResult = "String" val wideFunctionPattern = (1 to i).gen(j => "%s")(", ") val narrowGenericArgs = (1 to i).gen(j => "Integer")(", ") val narrowGenericResult = im.getType("java.lang.CharSequence") val narrowArgs = (1 to i).gen(j => j.toString)(", ") xs""" public class $className { @$test public void shouldCreateFromMethodReference() { class Type { Object methodReference($functionArgsDecl) { return null; } } final Type type = new Type(); assertThat($name$i.of(type::methodReference)).isNotNull(); } @$test public void shouldLiftPartialFunction() { assertThat($name$i.lift(($functionArgs) -> { while(true); })).isNotNull(); } ${(i == 1).gen(xs""" @$test public void shouldCreateIdentityFunction()${checked.gen(" throws Throwable")} { final $name$i identity = $name$i.identity(); final String s = "test"; assertThat(identity.apply(s)).isEqualTo(s); } """)} ${(i == 0 && !checked).gen( xs""" @$test public void shouldGetValue() { final String s = "test"; final ${name}0 supplier = () -> s; assertThat(supplier.get()).isEqualTo(s); } """ )} ${(i > 1).gen(xs""" @$test public void shouldPartiallyApply()${checked.gen(" throws Throwable")} { final $name$i<$generics> f = ($functionArgs) -> null; ${(1 until i).gen(j => { val partialArgs = (1 to j).gen(k => "null")(", ") s"$assertThat(f.apply($partialArgs)).isNotNull();" })("\n")} } """)} @$test public void shouldGetArity() { final $name$i<$generics> f = ($functionArgs) -> null; $assertThat(f.arity()).isEqualTo($i); } @$test public void shouldConstant()${checked.gen(" throws Throwable")} { final $name$i<$generics> f = $name$i.constant(6); $assertThat(f.apply(${(1 to i).gen(j => s"$j")(", ")})).isEqualTo(6); } @$test public void shouldCurry() { final $name$i<$generics> f = ($functionArgs) -> null; final ${curriedType(i, name)} curried = f.curried(); $assertThat(curried).isNotNull(); } @$test public void shouldTuple() { final $name$i<$generics> f = ($functionArgs) -> null; final ${name}1 0).gen(s"<${(1 to i).gen(j => "Object")(", ")}>")}, Object> tupled = f.tupled(); $assertThat(tupled).isNotNull(); } @$test public void shouldReverse() { final $name$i<$generics> f = ($functionArgs) -> null; $assertThat(f.reversed()).isNotNull(); } @$test public void shouldMemoize()${checked.gen(" throws Throwable")} { final $AtomicInteger integer = new $AtomicInteger(); final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> f = (${(1 to i).gen(j => s"i$j")(", ")}) -> ${(1 to i).gen(j => s"i$j")(" + ")}${(i > 0).gen(" + ")}integer.getAndIncrement(); final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(${(1 to i).gen(j => s"$j")(", ")}); // should return memoized value of second apply() $assertThat(memo.apply(${(1 to i).gen(j => s"$j")(", ")})).isEqualTo(expected); ${(i > 0).gen(xs""" // should calculate new values when called subsequently with different parameters $assertThat(memo.apply(${(1 to i).gen(j => s"${j + 1} ")(", ")})).isEqualTo(${(1 to i).gen(j => s"${j + 1} ")(" + ")} + 1); // should return memoized value of second apply() (for new value) $assertThat(memo.apply(${(1 to i).gen(j => s"${j + 1} ")(", ")})).isEqualTo(${(1 to i).gen(j => s"${j + 1} ")(" + ")} + 1); """)} } @$test public void shouldNotMemoizeAlreadyMemoizedFunction()${checked.gen(" throws Throwable")} { final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> f = (${(1 to i).gen(j => s"i$j")(", ")}) -> null; final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> memo = f.memoized(); $assertThat(memo.memoized() == memo).isTrue(); } ${(i > 0).gen(xs""" @$test public void shouldMemoizeValueGivenNullArguments()${checked.gen(" throws Throwable")} { final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> f = (${(1 to i).gen(j => s"i$j")(", ")}) -> null; final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> memo = f.memoized(); $assertThat(memo.apply(${(1 to i).gen(j => "null")(", ")})).isNull(); } """)} @$test public void shouldRecognizeMemoizedFunctions() { final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> f = (${(1 to i).gen(j => s"i$j")(", ")}) -> null; final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> memo = f.memoized(); $assertThat(f.isMemoized()).isFalse(); $assertThat(memo.isMemoized()).isTrue(); } ${(i == 1 && !checked).gen({ val assertThatThrownBy = im.getStatic("org.assertj.core.api.Assertions.assertThatThrownBy") xs""" @$test public void shouldThrowOnPartialWithNullPredicate() { final Function1 f = String::valueOf; $assertThatThrownBy(() -> f.partial(null)) .isInstanceOf(NullPointerException.class) .hasMessage("isDefinedAt is null"); } @$test public void shouldCreatePartialFunction() { final Function1 f = String::valueOf; final PartialFunction pf = f.partial(i -> i % 2 == 0); assertThat(pf.isDefinedAt(0)).isTrue(); assertThat(pf.isDefinedAt(1)).isFalse(); assertThat(pf.apply(0)).isEqualTo("0"); assertThat(pf.apply(1)).isEqualTo("1"); // it is valid to return a value, even if isDefinedAt returns false } """})} ${(!checked).gen(xs""" @$test public void shouldLiftTryPartialFunction() { $AtomicInteger integer = new $AtomicInteger(); $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> divByZero = (${(1 to i).gen(j => s"i$j")(", ")}) -> 10 / integer.get(); $name$i<${(1 to i).gen(j => "Integer, ")("")}Try> divByZeroTry = $name$i.liftTry(divByZero); ${im.getType("io.vavr.control.Try")} res = divByZeroTry.apply(${(1 to i).gen(j => s"0")(", ")}); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(${(1 to i).mkString(", ")}); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } """)} ${checked.gen(xs""" ${(i == 0).gen(xs""" @$test public void shouldRecover() { final $AtomicInteger integer = new $AtomicInteger(); $name$i digest = () -> ${im.getType("java.security.MessageDigest")}.getInstance(integer.get() == 0 ? "MD5" : "Unknown"); Function$i recover = digest.recover(throwable -> () -> null); MessageDigest md5 = recover.apply(); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); integer.incrementAndGet(); assertThat(recover.apply()).isNull(); } @$test public void shouldRecoverNonNull() { final $AtomicInteger integer = new $AtomicInteger(); $name$i digest = () -> ${im.getType("java.security.MessageDigest")}.getInstance(integer.get() == 0 ? "MD5" : "Unknown"); Function$i recover = digest.recover(throwable -> null); MessageDigest md5 = recover.apply(); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); integer.incrementAndGet(); ${im.getType("io.vavr.control.Try")} unknown = Function$i.liftTry(recover).apply(); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @$test public void shouldUncheckedWork() { $name$i digest = () -> ${im.getType("java.security.MessageDigest")}.getInstance("MD5"); Function$i unchecked = digest.unchecked(); MessageDigest md5 = unchecked.apply(); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @$test(expected = ${im.getType("java.security.NoSuchAlgorithmException")}.class) public void shouldThrowCheckedExceptionWhenUnchecked() { $name$i digest = () -> ${im.getType("java.security.MessageDigest")}.getInstance("Unknown"); Function$i unchecked = digest.unchecked(); unchecked.apply(); // Look ma, we throw an undeclared checked exception! } @$test public void shouldLiftTryPartialFunction() { final $AtomicInteger integer = new $AtomicInteger(); $name$i digest = () -> ${im.getType("java.security.MessageDigest")}.getInstance(integer.get() == 0 ? "MD5" : "Unknown"); Function$i> liftTry = $name$i.liftTry(digest); ${im.getType("io.vavr.control.Try")} md5 = liftTry.apply(); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); integer.incrementAndGet(); ${im.getType("io.vavr.control.Try")} unknown = liftTry.apply(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } """)} ${(i > 0).gen(xs""" ${ val types = s"<${(1 to i).gen(j => "String")(", ")}, MessageDigest>" def toArgList (s: String) = s.split("", i).mkString("\"", "\", \"", "\"") + (s.length + 2 to i).gen(j => ", \"\"") xs""" private static final $name$i$types digest = (${(1 to i).gen(j => s"s$j")(", ")}) -> ${im.getType("java.security.MessageDigest")}.getInstance(${(1 to i).gen(j => s"s$j")(" + ")}); @$test public void shouldRecover() { final Function$i<${(1 to i).gen(j => "String")(", ")}, MessageDigest> recover = digest.recover(throwable -> (${(1 to i).gen(j => s"s$j")(", ")}) -> null); final MessageDigest md5 = recover.apply(${toArgList("MD5")}); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply(${toArgList("Unknown")})).isNull(); } @$test public void shouldRecoverNonNull() { final Function$i<${(1 to i).gen(j => "String")(", ")}, MessageDigest> recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply(${toArgList("MD5")}); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final ${im.getType("io.vavr.control.Try")} unknown = Function$i.liftTry(recover).apply(${toArgList("Unknown")}); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @$test public void shouldUncheckedWork() { final Function$i<${(1 to i).gen(j => "String")(", ")}, MessageDigest> unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply(${toArgList("MD5")}); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @$test(expected = ${im.getType("java.security.NoSuchAlgorithmException")}.class) public void shouldUncheckedThrowIllegalState() { final Function$i<${(1 to i).gen(j => "String")(", ")}, MessageDigest> unchecked = digest.unchecked(); unchecked.apply(${toArgList("Unknown")}); // Look ma, we throw an undeclared checked exception! } @$test public void shouldLiftTryPartialFunction() { final Function$i<${(1 to i).gen(j => "String")(", ")}, Try> liftTry = $name$i.liftTry(digest); final ${im.getType("io.vavr.control.Try")} md5 = liftTry.apply(${toArgList("MD5")}); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final ${im.getType("io.vavr.control.Try")} unknown = liftTry.apply(${toArgList("Unknown")}); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } """ } """)} """)} private static final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> recurrent1 = (${(1 to i).gen(j => s"i$j")(", ")}) -> $recFuncF1 ${(i > 0).gen(xs""" private static final $name$i<${(1 to i + 1).gen(j => "Integer")(", ")}> recurrent2 = $className.recurrent1.memoized(); """)} @$test public void shouldCalculatedRecursively()${checked.gen(" throws Throwable")} { assertThat(recurrent1.apply(${(1 to i).gen(j => "11")(", ")})).isEqualTo(11); ${(i > 0).gen(s"assertThat(recurrent1.apply(${(1 to i).gen(j => "22")(", ")})).isEqualTo(22);")} } @$test public void shouldComposeWithAndThen() { final $name$i<$generics> f = ($functionArgs) -> null; final ${name}1 after = o -> null; final $name$i<$generics> composed = f.andThen(after); $assertThat(composed).isNotNull(); } ${(i == 1).gen(xs""" @$test public void shouldComposeWithCompose() { final $name$i<$generics> f = ($functionArgs) -> null; final ${name}1 before = o -> null; final $name$i<$generics> composed = f.compose(before); $assertThat(composed).isNotNull(); } """)} ${(i == 0).gen(xs""" @$test public void shouldNarrow()${checked.gen(" throws Throwable")}{ final $name$i<$wideGenericResult> wideFunction = () -> "Zero args"; final $name$i<$narrowGenericResult> narrowFunction = $name$i.narrow(wideFunction); $assertThat(narrowFunction.apply()).isEqualTo("Zero args"); } """)} ${(i > 0).gen(xs""" @$test public void shouldNarrow()${checked.gen(" throws Throwable")}{ final $name$i<$wideGenericArgs, $wideGenericResult> wideFunction = ($functionArgs) -> String.format("Numbers are: $wideFunctionPattern", $functionArgs); final $name$i<$narrowGenericArgs, $narrowGenericResult> narrowFunction = $name$i.narrow(wideFunction); $assertThat(narrowFunction.apply($narrowArgs)).isEqualTo("Numbers are: $narrowArgs"); } """)} } """ } }) } def genMapOfEntriesTests(): Unit = { def genAllArity(im: ImportManager, mapName: String, mapBuilder: String, builderComparator: Boolean, keyComparator: Boolean): String = { val test = im.getType("org.junit.Test") val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") val naturalComparator = if (builderComparator || keyComparator) im.getStatic(s"io.vavr.collection.Comparators.naturalComparator") else null val map = im.getType(s"io.vavr.collection.$mapName") (1 to VARARGS).gen(arity => xs""" @$test public void shouldConstructFrom${arity}Entries${if(builderComparator) "WithBuilderComparator" else ""}${if(keyComparator) "WithKeyComparator" else ""}${mapBuilder.capitalize}() { final $map map = $map${if (mapBuilder.isEmpty) "" else s".$mapBuilder"}${if (builderComparator) s"($naturalComparator())" else if (mapBuilder.isEmpty) "" else "()"} .of(${if(keyComparator) s"$naturalComparator(), " else ""}${(1 to arity).gen(j => s"""$j, "$j"""")(", ")}); $assertThat(map.size()).isEqualTo($arity); ${(1 to arity).gen(j => { s"""${if (mapBuilder.isEmpty) "" else s"$assertThat(map.get($j).get() instanceof ${im.getType(s"io.vavr.collection.${mapBuilder.substring(4)}")}).isTrue();\n"}$assertThat(map.get($j).get()${if (mapName.contains("Multimap")) ".head()" else ""}).isEqualTo("$j");""" })("\n")} } """)("\n\n") } def genMapOfEntriesTest(mapName: String): Unit = { val mapBuilders:List[String] = if (mapName.contains("Multimap")) List("withSeq", "withSet", "withSortedSet") else List("") val keyComparators:List[Boolean] = if (mapName.startsWith("Tree")) List(true, false) else List(false) genVavrFile("io.vavr.collection", s"${mapName}OfEntriesTest", baseDir = TARGET_TEST) ((im: ImportManager, packageName, className) => { xs""" public class ${mapName}OfEntriesTest { ${mapBuilders.flatMap(mapBuilder => { val builderComparators:List[Boolean] = if (mapBuilder.contains("Sorted")) List(true, false) else List(false) builderComparators.flatMap(builderComparator => keyComparators.map(keyComparator => xs""" ${genAllArity(im, mapName, mapBuilder, builderComparator, keyComparator)} """ )) }).mkString("\n\n")} } """ }) } genMapOfEntriesTest("HashMap") genMapOfEntriesTest("LinkedHashMap") genMapOfEntriesTest("TreeMap") genMapOfEntriesTest("HashMultimap") genMapOfEntriesTest("LinkedHashMultimap") genMapOfEntriesTest("TreeMultimap") } /** * Generator of Tuple tests */ def genTupleTests(): Unit = { def genArgsForComparing(digits: Int, p: Int): String = { (1 to digits).gen(i => if(i == p) "1" else "0")(", ") } (0 to N).foreach(i => { genVavrFile("io.vavr", s"Tuple${i}Test", baseDir = TARGET_TEST)((im: ImportManager, packageName, className) => { val test = im.getType("org.junit.Test") val seq = im.getType("io.vavr.collection.Seq") val list = im.getType("io.vavr.collection.List") val stream = if (i == 0) "" else im.getType("io.vavr.collection.Stream") val comparator = im.getType("java.util.Comparator") val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") val generics = if (i == 0) "" else s"<${(1 to i).gen(j => s"Object")(", ")}>" val intGenerics = if (i == 0) "" else s"<${(1 to i).gen(j => s"Integer")(", ")}>" val functionArgs = if (i == 0) "()" else s"${(i > 1).gen("(") + (1 to i).gen(j => s"o$j")(", ") + (i > 1).gen(")")}" val nullArgs = (1 to i).gen(j => "null")(", ") if(i==2){ im.getType("java.util.AbstractMap") im.getType("java.util.Map") } xs""" public class $className { @$test public void shouldCreateTuple() { final Tuple$i$generics tuple = createTuple(); $assertThat(tuple).isNotNull(); } @$test public void shouldGetArity() { final Tuple$i$generics tuple = createTuple(); $assertThat(tuple.arity()).isEqualTo($i); } ${(i > 0).gen(xs""" @$test public void shouldReturnElements() { final Tuple$i$intGenerics tuple = createIntTuple(${(1 to i).gen(j => s"$j")(", ")}); ${(1 to i).gen(j => s"$assertThat(tuple._$j).isEqualTo($j);\n")} } """)} ${(1 to i).gen(j => xs""" @$test public void shouldUpdate$j() { final Tuple$i$intGenerics tuple = createIntTuple(${(1 to i).gen(j => s"$j")(", ")}).update$j(42); ${(1 to i).gen(k => s"$assertThat(tuple._$k).isEqualTo(${if (j == k) 42 else k});\n")} } """)("\n\n")} @$test public void shouldConvertToSeq() { final $seq actual = createIntTuple(${genArgsForComparing(i, 1)}).toSeq(); $assertThat(actual).isEqualTo($list.of(${genArgsForComparing(i, 1)})); } @$test public void shouldCompareEqual() { final Tuple$i$intGenerics t0 = createIntTuple(${genArgsForComparing(i, 0)}); $assertThat(t0.compareTo(t0)).isZero(); $assertThat(intTupleComparator.compare(t0, t0)).isZero(); } ${(1 to i).gen(j => xs""" @$test public void shouldCompare${j.ordinal}Arg() { final Tuple$i$intGenerics t0 = createIntTuple(${genArgsForComparing(i, 0)}); final Tuple$i$intGenerics t$j = createIntTuple(${genArgsForComparing(i, j)}); $assertThat(t0.compareTo(t$j)).isNegative(); $assertThat(t$j.compareTo(t0)).isPositive(); $assertThat(intTupleComparator.compare(t0, t$j)).isNegative(); $assertThat(intTupleComparator.compare(t$j, t0)).isPositive(); } """)("\n\n")} ${(i == 2).gen(xs""" @$test public void shouldSwap() { $assertThat(createIntTuple(1, 2).swap()).isEqualTo(createIntTuple(2, 1)); } @$test public void shouldConvertToEntry() { Tuple$i$intGenerics tuple = createIntTuple(1,2); Map.Entry$intGenerics entry = new AbstractMap.SimpleEntry<>(1, 2); assertThat(tuple.toEntry().equals(entry)); } """)} ${(i > 0).gen(xs""" @$test public void shouldMap() { final Tuple$i$generics tuple = createTuple(); ${if (i == 1) xs""" final Tuple$i$generics actual = tuple.map(o -> o); $assertThat(actual).isEqualTo(tuple); """ else xs""" final Tuple$i$generics actual = tuple.map($functionArgs -> tuple); $assertThat(actual).isEqualTo(tuple); """} } @$test public void shouldMapComponents() { final Tuple$i$generics tuple = createTuple(); ${(1 to i).gen(j => xs"""final Function1 f$j = Function1.identity();""")("\n")} final Tuple$i$generics actual = tuple.map(${(1 to i).gen(j => s"f$j")(", ")}); $assertThat(actual).isEqualTo(tuple); } @$test public void shouldReturnTuple${i}OfSequence$i() { final $seq xs"Integer")(", ")}>> iterable = $list.of(${(1 to i).gen(j => xs"Tuple.of(${(1 to i).gen(k => xs"${k+2*j-1}")(", ")})")(", ")}); final Tuple$i<${(1 to i).gen(j => xs"$seq")(", ")}> expected = Tuple.of(${(1 to i).gen(j => xs"$stream.of(${(1 to i).gen(k => xs"${2*k+j-1}")(", ")})")(", ")}); $assertThat(Tuple.sequence$i(iterable)).isEqualTo(expected); } """)} ${(i > 1).gen(xs""" @$test public void shouldReturnTuple${i}OfSequence1() { final $seq xs"Integer")(", ")}>> iterable = $list.of(Tuple.of(${(1 to i).gen(k => xs"$k")(", ")})); final Tuple$i<${(1 to i).gen(j => xs"$seq")(", ")}> expected = Tuple.of(${(1 to i).gen(j => xs"$stream.of($j)")(", ")}); $assertThat(Tuple.sequence$i(iterable)).isEqualTo(expected); } """)} ${(i > 1) gen (1 to i).gen(j => { val substitutedResultTypes = if (i == 0) "" else s"<${(1 to i).gen(k => if (k == j) "String" else "Integer")(", ")}>" val ones = (1 to i).gen(_ => "1")(", ") val result = (1 to i).gen(k => if (k == j) "\"X\"" else "1")(", ") xs""" @$test public void shouldMap${j.ordinal}Component() { final Tuple$i$substitutedResultTypes actual = Tuple.of($ones).map$j(i -> "X"); final Tuple$i$substitutedResultTypes expected = Tuple.of($result); assertThat(actual).isEqualTo(expected); } """ })("\n\n")} @$test public void shouldApplyTuple() { final Tuple$i$generics tuple = createTuple(); final Tuple0 actual = tuple.apply($functionArgs -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } ${(i < N).gen(xs""" @$test public void shouldAppendValue() { final Tuple${i+1}<${(1 to i+1).gen(j => s"Integer")(", ")}> actual = ${ if (i == 0) "Tuple0.instance()" else s"Tuple.of(${(1 to i).gen(j => xs"$j")(", ")})"}.append(${i+1}); final Tuple${i+1}<${(1 to i+1).gen(j => s"Integer")(", ")}> expected = Tuple.of(${(1 to i+1).gen(j => xs"$j")(", ")}); assertThat(actual).isEqualTo(expected); } """)} ${(i < N) gen (1 to N-i).gen(j => xs""" @$test public void shouldConcatTuple$j() { final Tuple${i+j}<${(1 to i+j).gen(j => s"Integer")(", ")}> actual = ${ if (i == 0) "Tuple0.instance()" else s"Tuple.of(${(1 to i).gen(j => xs"$j")(", ")})"}.concat(Tuple.of(${(i+1 to i+j).gen(k => s"$k")(", ")})); final Tuple${i+j}<${(1 to i+j).gen(j => s"Integer")(", ")}> expected = Tuple.of(${(1 to i+j).gen(j => xs"$j")(", ")}); assertThat(actual).isEqualTo(expected); } """)("\n\n")} @$test public void shouldRecognizeEquality() { final Tuple$i$generics tuple1 = createTuple(); final Tuple$i$generics tuple2 = createTuple(); $assertThat((Object) tuple1).isEqualTo(tuple2); } @$test public void shouldRecognizeNonEquality() { final Tuple$i$generics tuple = createTuple(); final Object other = new Object(); $assertThat(tuple).isNotEqualTo(other); } ${(i > 0).gen(xs""" @$test public void shouldRecognizeNonEqualityPerComponent() { final Tuple$i<${(1 to i).gen(_ => "String")(", ")}> tuple = Tuple.of(${(1 to i).gen(j => "\"" + j + "\"")(", ")}); ${(1 to i).gen(j => { val that = "Tuple.of(" + (1 to i).gen(k => if (j == k) "\"X\"" else "\"" + k + "\"")(", ") + ")" s"$assertThat(tuple.equals($that)).isFalse();" })("\n")} } """)} @$test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = ${im.getType("java.util.Objects")}.${if (i == 1) "hashCode" else "hash"}($nullArgs); $assertThat(actual).isEqualTo(expected); } @$test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "($nullArgs)"; $assertThat(actual).isEqualTo(expected); } private $comparator intTupleComparator = Tuple$i.comparator(${(1 to i).gen($j => s"Integer::compare")(", ")}); private Tuple$i$generics createTuple() { return ${if (i == 0) "Tuple0.instance()" else s"new Tuple$i<>($nullArgs)"}; } private Tuple$i$intGenerics createIntTuple(${(1 to i).gen(j => s"Integer i$j")(", ")}) { return ${if (i == 0) "Tuple0.instance()" else s"new Tuple$i<>(${(1 to i).gen(j => s"i$j")(", ")})"}; } } """ }) }) } } /** * Adds the Vavr header to generated classes. * * @param packageName Java package name * @param className Simple java class name * @param gen A generator which produces a String. */ def genVavrFile(packageName: String, className: String, baseDir: String = TARGET_MAIN)(gen: (ImportManager, String, String) => String, knownSimpleClassNames: List[String] = List()) = genJavaFile(baseDir, packageName, className)(xraw""" /* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ """)(gen)(CHARSET) /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ J A V A G E N E R A T O R F R A M E W O R K \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ object JavaGenerator { import java.nio.charset.{Charset, StandardCharsets} import Generator._ /** * Generates a Java file. * * @param packageName Java package name * @param className Simple java class name * @param classHeader A class file header * @param gen A generator which produces a String. */ def genJavaFile(baseDir: String, packageName: String, className: String)(classHeader: String)(gen: (ImportManager, String, String) => String, knownSimpleClassNames: List[String] = List())(implicit charset: Charset = StandardCharsets.UTF_8): Unit = { // DEV-NOTE: using File.separator instead of "/" does *not* work on windows! val dirName = packageName.replaceAll("[.]", "/") val fileName = className + ".java" val importManager = new ImportManager(packageName, knownSimpleClassNames) val classBody = gen.apply(importManager, packageName, className) genFile(baseDir, dirName, fileName)(xraw""" $classHeader package $packageName; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ ${importManager.getImports} $classBody """) } /** * A stateful ImportManager which generates an import section of a Java class file. * * @param packageNameOfClass package name of the generated class * @param knownSimpleClassNames a list of class names which may not be imported from other packages */ class ImportManager(packageNameOfClass: String, knownSimpleClassNames: List[String], wildcardThreshold: Int = 5) { import scala.collection.mutable val nonStaticImports = new mutable.HashMap[String, String] val staticImports = new mutable.HashMap[String, String] def getType(fullQualifiedName: String): String = simplify(fullQualifiedName, nonStaticImports) def getStatic(fullQualifiedName: String): String = simplify(fullQualifiedName, staticImports) def getImports: String = { def optimizeImports(imports: Seq[String], static: Boolean): String = { val counts = imports.map(getPackageName).groupBy(s => s).map { case (s, list) => s -> list.length } val directImports = imports.filter(s => counts(getPackageName(s)) <= wildcardThreshold) val wildcardImports = counts.filter { case (_, count) => count > wildcardThreshold }.keySet.toIndexedSeq.map(s => s"$s.*") (directImports ++ wildcardImports).sorted.map(fqn => s"import ${static.gen("static ")}$fqn;").mkString("\n") } val staticImportSection = optimizeImports(staticImports.keySet.toIndexedSeq, static = true) val nonStaticImportSection = optimizeImports(nonStaticImports.keySet.toIndexedSeq, static = false) Seq(staticImportSection, nonStaticImportSection).mkString("\n\n") } private def simplify(fullQualifiedName: String, imports: mutable.HashMap[String, String]): String = { val simpleName = getSimpleName(fullQualifiedName) val packageName = getPackageName(fullQualifiedName) if (packageName.isEmpty && !packageNameOfClass.isEmpty) { throw new IllegalStateException(s"Can't import class '$simpleName' located in default package") } else if (packageName == packageNameOfClass) { simpleName } else if (imports.contains(fullQualifiedName)) { imports(fullQualifiedName) } else if (simpleName != "*" && (knownSimpleClassNames.contains(simpleName) || imports.values.exists(simpleName.equals(_)))) { fullQualifiedName } else { imports += fullQualifiedName -> simpleName simpleName } } private def getPackageName(fqn: String): String = fqn.substring(0, Math.max(fqn.lastIndexOf("."), 0)) private def getSimpleName(fqn: String): String = fqn.substring(fqn.lastIndexOf(".") + 1) } } /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ C O R E G E N E R A T O R F R A M E W O R K \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /** * Core generator API */ object Generator { import java.nio.charset.{Charset, StandardCharsets} import java.nio.file.{Files, Paths, StandardOpenOption} /** * Generates a file by writing string contents to the file system. * * @param baseDir The base directory, e.g. src-gen * @param dirName The directory relative to baseDir, e.g. main/java * @param fileName The file name within baseDir/dirName * @param createOption One of java.nio.file.{StandardOpenOption.CREATE_NEW, StandardOpenOption.CREATE}, default: CREATE_NEW * @param contents The string contents of the file * @param charset The charset, by default UTF-8 */ def genFile(baseDir: String, dirName: String, fileName: String, createOption: StandardOpenOption = StandardOpenOption.CREATE_NEW)(contents: => String)(implicit charset: Charset = StandardCharsets.UTF_8): Unit = { // println(s"Generating $dirName${File.separator}$fileName") Files.write( Files.createDirectories(Paths.get(baseDir, dirName)).resolve(fileName), contents.getBytes(charset), createOption, StandardOpenOption.WRITE) } implicit class IntExtensions(i: Int) { // returns i as ordinal, i.e. 1st, 2nd, 3rd, 4th, ... def ordinal: String = s"$i" + (if (i >= 4 && i <= 20) { "th" } else { i % 10 match { case 1 => "st" case 2 => "nd" case 3 => "rd" case _ => "th" } }) // returns the grammatical number of a string, i.e. `i.numerus("name")` is // 0: "no name", 1: "one name", 2: "two names", 3: "three names", 4: "4 names", ... def numerus(noun: String): String = Math.abs(i) match { case 0 => s"no ${noun}s" case 1 => s"one $noun" case 2 => s"two ${noun}s" case 3 => s"three ${noun}s" case _ => s"$i ${noun}s" } // returns the a pluralized noun, e.g. 0: "names", 1: "name", -1: "name", 2: "names" def plural(noun: String): String = noun + (i != 1).gen("s") } implicit class StringExtensions(s: String) { // gets first char of s as string. throws if string is empty def first: String = s.substring(0, 1) // converts first char of s to upper case. throws if string is empty def firstUpper: String = s(0).toUpper + s.substring(1) // converts first char of s to lower case. throws if string is empty def firstLower: String = s(0).toLower + s.substring(1) } implicit class BooleanExtensions(condition: Boolean) { def gen(s: => String): String = if (condition) s else "" } implicit class OptionExtensions(option: Option[Any]) { def gen(f: String => String): String = option.map(any => f.apply(any.toString)).getOrElse("") def gen: String = option.map(any => any.toString).getOrElse("") } /** * Generates a String based on ints within a specific range. * {{{ * (1 to 3).gen(i => s"x$i")(", ") // x1, x2, x3 * (1 to 3).reverse.gen(i -> s"x$i")(", ") // x3, x2, x1 * }}} * * @param range A Range */ implicit class RangeExtensions(range: Range) { def gen(f: Int => String = String.valueOf)(implicit delimiter: String = ""): String = range map f mkString delimiter } /** * Generates a String based on an Iterable of objects. Objects are converted to Strings via toString. * {{{ * // val a = "A" * // val b = "B" * // val c = "C" * Seq("a", "b", "c").gen(s => raw"""val $s = "${s.toUpperCase}"""")("\n") * }}} * * @param iterable An Interable */ implicit class IterableExtensions(iterable: Iterable[Any]) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = iterable.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple1Extensions(tuple: Tuple1[Any]) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = f.apply(tuple._1.toString) mkString delimiter } implicit class Tuple2Extensions(tuple: (Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } /** * Generates a String based on a tuple of objects. Objects are converted to Strings via toString. * {{{ * // val seq = Seq("a", "1", "true") * s"val seq = Seq(${("a", 1, true).gen(s => s""""$s"""")(", ")})" * }}} * * @param tuple A Tuple */ implicit class Tuple3Extensions(tuple: (Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple4Extensions(tuple: (Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple5Extensions(tuple: (Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple6Extensions(tuple: (Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple7Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple8Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple9Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple10Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple11Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple12Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple13Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple14Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple15Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple16Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple17Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple18Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple19Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple20Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple21Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } implicit class Tuple22Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { def gen(f: String => String = identity)(implicit delimiter: String = ""): String = tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter } /** * Provides StringContext extensions, e.g. indentation of cascaded rich strings. * * @param sc Current StringContext * @see this gist */ implicit class StringContextExtensions(sc: StringContext) { import scala.util.Properties.lineSeparator /** * Formats escaped strings. * * @param args StringContext parts * @return An aligned String */ def xs(args: Any*): String = align(sc.s, args) /** * Formats raw/unescaped strings. * * @param args StringContext parts * @return An aligned String */ def xraw(args: Any*): String = align(sc.raw, args) /** * Indenting a rich string, removing first and last newline. * A rich string consists of arguments surrounded by text parts. */ private def align(interpolator: Seq[Any] => String, args: Seq[Any]): String = { // indent embedded strings, invariant: parts.length = args.length + 1 val indentedArgs = for { (part, arg) <- sc.parts zip args.map(s => if (s == null) "" else s.toString) } yield { // get the leading space of last line of current part val space = """([ \t]*)[^\s]*$""".r.findFirstMatchIn(part).map(_.group(1)).getOrElse("") // add this leading space to each line (except the first) of current arg arg.split("\r?\n") match { case lines: Array[String] if lines.nonEmpty => lines reduce (_ + lineSeparator + space + _) case whitespace => whitespace mkString "" } } // remove first and last newline and split string into separate lines // adding termination symbol \u0000 in order to preserve empty strings between last newlines when splitting val split = (interpolator(indentedArgs).replaceAll( """(^[ \t]*\r?\n)|(\r?\n[ \t]*$)""", "") + '\u0000').split("\r?\n") // find smallest indentation val prefix = split filter (!_.trim().isEmpty) map { s => """^\s+""".r.findFirstIn(s).getOrElse("") } match { case prefixes: Array[String] if prefixes.length > 0 => prefixes reduce { (s1, s2) => if (s1.length <= s2.length) s1 else s2 } case _ => "" } // align all lines val aligned = split map { s => if (s.startsWith(prefix)) s.substring(prefix.length) else s } mkString lineSeparator dropRight 1 // dropping termination character \u0000 // combine multiple newlines to two aligned.replaceAll("""[ \t]*\r?\n ([ \t]*\r?\n)+""", lineSeparator * 2) } } } vavr-0.10.0/vavr/pom.xml000066400000000000000000000064541342074374400150620ustar00rootroot00000000000000 4.0.0 io.vavr vavr-parent 0.10.0 ../pom.xml vavr jar Vavr Vavr (formerly called Javaslang) is an object-functional language extension to Java 8+. http://vavr.io The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo ${project.groupId} vavr-match ${project.version} ${project.groupId} vavr-match-processor ${project.version} true junit junit test org.assertj assertj-core test org.apache.maven.plugins maven-source-plugin org.apache.maven.plugins maven-clean-plugin net.alchim31.maven scala-maven-plugin org.codehaus.mojo build-helper-maven-plugin org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-jar-plugin io.vavr org.apache.maven.plugins maven-javadoc-plugin org.apache.felix maven-bundle-plugin vavr-0.10.0/vavr/src-gen/000077500000000000000000000000001342074374400150725ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/main/000077500000000000000000000000001342074374400160165ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/main/java/000077500000000000000000000000001342074374400167375ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/main/java/io/000077500000000000000000000000001342074374400173465ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/main/java/io/vavr/000077500000000000000000000000001342074374400203245ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/main/java/io/vavr/API.java000066400000000000000000006354531342074374400216200ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.API.Match.*; import io.vavr.collection.*; import io.vavr.concurrent.Future; import io.vavr.control.Either; import io.vavr.control.Option; import io.vavr.control.Try; import io.vavr.control.Validation; import java.io.PrintStream; import java.util.Comparator; import java.util.Formatter; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * The most basic Vavr functionality is accessed through this API class. * *

 * import static io.vavr.API.*;
 * 
* *

For-comprehension

*

* The {@code For}-comprehension is syntactic sugar for nested for-loops. We write * *


 * // lazily evaluated
 * Iterator<R> result = For(iterable1, iterable2, ..., iterableN).yield(f);
 * 
* * or * *

 * Iterator<R> result =
 *     For(iterable1, v1 ->
 *         For(iterable2, v2 ->
 *             ...
 *             For(iterableN).yield(vN -> f.apply(v1, v2, ..., vN))
 *         )
 *     );
 * 
* * instead of * *

 * for(T1 v1 : iterable1) {
 *     for (T2 v2 : iterable2) {
 *         ...
 *         for (TN vN : iterableN) {
 *             R result = f.apply(v1, v2, ..., VN);
 *             //
 *             // We are forced to perform side effects to do s.th. meaningful with the result.
 *             //
 *         }
 *     }
 * }
 * 
* * Please note that values like Option, Try, Future, etc. are also iterable. *

* Given a suitable function * f: {@code (v1, v2, ..., vN) -> ...} and 1 <= N <= 8 iterables, the result is a Stream of the * mapped cross product elements. * *


 * { f(v1, v2, ..., vN) | v1 ∈ iterable1, ... vN ∈ iterableN }
 * 
* * As with all Vavr Values, the result of a For-comprehension can be converted * to standard Java library and Vavr types. * @author Daniel Dietrich */ public final class API { private API() { } // // Shortcuts // /** * A temporary replacement for an implementations used during prototyping. *

* Example: * *


     * public HttpResponse getResponse(HttpRequest request) {
     *     return TODO();
     * }
     *
     * final HttpResponse response = getHttpResponse(TODO());
     * 
* * @param The result type of the missing implementation. * @return Nothing - this methods always throws. * @throws NotImplementedError when this methods is called * @see NotImplementedError#NotImplementedError() */ public static T TODO() { throw new NotImplementedError(); } /** * A temporary replacement for an implementations used during prototyping. *

* Example: * *


     * public HttpResponse getResponse(HttpRequest request) {
     *     return TODO("fake response");
     * }
     *
     * final HttpResponse response = getHttpResponse(TODO("fake request"));
     * 
* * @param msg An error message * @param The result type of the missing implementation. * @return Nothing - this methods always throws. * @throws NotImplementedError when this methods is called * @see NotImplementedError#NotImplementedError(String) */ public static T TODO(String msg) { throw new NotImplementedError(msg); } /** * Shortcut for {@code System.out.print(obj)}. See {@link PrintStream#print(Object)}. * * @param obj The Object to be printed */ public static void print(Object obj) { System.out.print(obj); } /** * Shortcut for {@code System.out.printf(format, args)}. See {@link PrintStream#printf(String, Object...)}. * * @param format A format string as described in {@link Formatter}. * @param args Arguments referenced by the format specifiers */ @GwtIncompatible public static void printf(String format, Object... args) { System.out.printf(format, args); } /** * Shortcut for {@code System.out.println(obj)}. See {@link PrintStream#println(Object)}. * * @param obj The Object to be printed */ public static void println(Object obj) { System.out.println(obj); } /** * Shortcut for {@code System.out.println()}. See {@link PrintStream#println()}. */ public static void println() { System.out.println(); } // // Aliases for static factories // // -- Function /** * Alias for {@link Function0#of(Function0)} * * @param return type * @param methodReference A method reference * @return A {@link Function0} */ public static Function0 Function(Function0 methodReference) { return Function0.of(methodReference); } /** * Alias for {@link Function1#of(Function1)} * * @param return type * @param type of the 1st argument * @param methodReference A method reference * @return A {@link Function1} */ public static Function1 Function(Function1 methodReference) { return Function1.of(methodReference); } /** * Alias for {@link Function2#of(Function2)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param methodReference A method reference * @return A {@link Function2} */ public static Function2 Function(Function2 methodReference) { return Function2.of(methodReference); } /** * Alias for {@link Function3#of(Function3)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param methodReference A method reference * @return A {@link Function3} */ public static Function3 Function(Function3 methodReference) { return Function3.of(methodReference); } /** * Alias for {@link Function4#of(Function4)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param methodReference A method reference * @return A {@link Function4} */ public static Function4 Function(Function4 methodReference) { return Function4.of(methodReference); } /** * Alias for {@link Function5#of(Function5)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param methodReference A method reference * @return A {@link Function5} */ public static Function5 Function(Function5 methodReference) { return Function5.of(methodReference); } /** * Alias for {@link Function6#of(Function6)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param methodReference A method reference * @return A {@link Function6} */ public static Function6 Function(Function6 methodReference) { return Function6.of(methodReference); } /** * Alias for {@link Function7#of(Function7)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param type of the 7th argument * @param methodReference A method reference * @return A {@link Function7} */ public static Function7 Function(Function7 methodReference) { return Function7.of(methodReference); } /** * Alias for {@link Function8#of(Function8)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param type of the 7th argument * @param type of the 8th argument * @param methodReference A method reference * @return A {@link Function8} */ public static Function8 Function(Function8 methodReference) { return Function8.of(methodReference); } // -- CheckedFunction /** * Alias for {@link CheckedFunction0#of(CheckedFunction0)} * * @param return type * @param methodReference A method reference * @return A {@link CheckedFunction0} */ public static CheckedFunction0 CheckedFunction(CheckedFunction0 methodReference) { return CheckedFunction0.of(methodReference); } /** * Alias for {@link CheckedFunction1#of(CheckedFunction1)} * * @param return type * @param type of the 1st argument * @param methodReference A method reference * @return A {@link CheckedFunction1} */ public static CheckedFunction1 CheckedFunction(CheckedFunction1 methodReference) { return CheckedFunction1.of(methodReference); } /** * Alias for {@link CheckedFunction2#of(CheckedFunction2)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param methodReference A method reference * @return A {@link CheckedFunction2} */ public static CheckedFunction2 CheckedFunction(CheckedFunction2 methodReference) { return CheckedFunction2.of(methodReference); } /** * Alias for {@link CheckedFunction3#of(CheckedFunction3)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param methodReference A method reference * @return A {@link CheckedFunction3} */ public static CheckedFunction3 CheckedFunction(CheckedFunction3 methodReference) { return CheckedFunction3.of(methodReference); } /** * Alias for {@link CheckedFunction4#of(CheckedFunction4)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param methodReference A method reference * @return A {@link CheckedFunction4} */ public static CheckedFunction4 CheckedFunction(CheckedFunction4 methodReference) { return CheckedFunction4.of(methodReference); } /** * Alias for {@link CheckedFunction5#of(CheckedFunction5)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param methodReference A method reference * @return A {@link CheckedFunction5} */ public static CheckedFunction5 CheckedFunction(CheckedFunction5 methodReference) { return CheckedFunction5.of(methodReference); } /** * Alias for {@link CheckedFunction6#of(CheckedFunction6)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param methodReference A method reference * @return A {@link CheckedFunction6} */ public static CheckedFunction6 CheckedFunction(CheckedFunction6 methodReference) { return CheckedFunction6.of(methodReference); } /** * Alias for {@link CheckedFunction7#of(CheckedFunction7)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param type of the 7th argument * @param methodReference A method reference * @return A {@link CheckedFunction7} */ public static CheckedFunction7 CheckedFunction(CheckedFunction7 methodReference) { return CheckedFunction7.of(methodReference); } /** * Alias for {@link CheckedFunction8#of(CheckedFunction8)} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param type of the 7th argument * @param type of the 8th argument * @param methodReference A method reference * @return A {@link CheckedFunction8} */ public static CheckedFunction8 CheckedFunction(CheckedFunction8 methodReference) { return CheckedFunction8.of(methodReference); } // -- unchecked /** * Alias for {@link CheckedFunction0#unchecked} * * @param return type * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction0} */ public static Function0 unchecked(CheckedFunction0 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction1#unchecked} * * @param return type * @param type of the 1st argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction1} */ public static Function1 unchecked(CheckedFunction1 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction2#unchecked} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction2} */ public static Function2 unchecked(CheckedFunction2 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction3#unchecked} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction3} */ public static Function3 unchecked(CheckedFunction3 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction4#unchecked} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction4} */ public static Function4 unchecked(CheckedFunction4 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction5#unchecked} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction5} */ public static Function5 unchecked(CheckedFunction5 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction6#unchecked} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction6} */ public static Function6 unchecked(CheckedFunction6 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction7#unchecked} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param type of the 7th argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction7} */ public static Function7 unchecked(CheckedFunction7 f) { return f.unchecked(); } /** * Alias for {@link CheckedFunction8#unchecked} * * @param return type * @param type of the 1st argument * @param type of the 2nd argument * @param type of the 3rd argument * @param type of the 4th argument * @param type of the 5th argument * @param type of the 6th argument * @param type of the 7th argument * @param type of the 8th argument * @param f A method reference * @return An unchecked wrapper of supplied {@link CheckedFunction8} */ public static Function8 unchecked(CheckedFunction8 f) { return f.unchecked(); } // -- Tuple /** * Alias for {@link Tuple#empty()} * * @return the empty tuple. */ public static Tuple0 Tuple() { return Tuple.empty(); } /** * Alias for {@link Tuple#of(Object)} * * Creates a tuple of one element. * * @param type of the 1st element * @param t1 the 1st element * @return a tuple of one element. */ public static Tuple1 Tuple(T1 t1) { return Tuple.of(t1); } /** * Alias for {@link Tuple#of(Object, Object)} * * Creates a tuple of two elements. * * @param type of the 1st element * @param type of the 2nd element * @param t1 the 1st element * @param t2 the 2nd element * @return a tuple of two elements. */ public static Tuple2 Tuple(T1 t1, T2 t2) { return Tuple.of(t1, t2); } /** * Alias for {@link Tuple#of(Object, Object, Object)} * * Creates a tuple of three elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @return a tuple of three elements. */ public static Tuple3 Tuple(T1 t1, T2 t2, T3 t3) { return Tuple.of(t1, t2, t3); } /** * Alias for {@link Tuple#of(Object, Object, Object, Object)} * * Creates a tuple of 4 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @return a tuple of 4 elements. */ public static Tuple4 Tuple(T1 t1, T2 t2, T3 t3, T4 t4) { return Tuple.of(t1, t2, t3, t4); } /** * Alias for {@link Tuple#of(Object, Object, Object, Object, Object)} * * Creates a tuple of 5 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @return a tuple of 5 elements. */ public static Tuple5 Tuple(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return Tuple.of(t1, t2, t3, t4, t5); } /** * Alias for {@link Tuple#of(Object, Object, Object, Object, Object, Object)} * * Creates a tuple of 6 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @return a tuple of 6 elements. */ public static Tuple6 Tuple(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { return Tuple.of(t1, t2, t3, t4, t5, t6); } /** * Alias for {@link Tuple#of(Object, Object, Object, Object, Object, Object, Object)} * * Creates a tuple of 7 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param type of the 7th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @param t7 the 7th element * @return a tuple of 7 elements. */ public static Tuple7 Tuple(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { return Tuple.of(t1, t2, t3, t4, t5, t6, t7); } /** * Alias for {@link Tuple#of(Object, Object, Object, Object, Object, Object, Object, Object)} * * Creates a tuple of 8 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param type of the 7th element * @param type of the 8th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @param t7 the 7th element * @param t8 the 8th element * @return a tuple of 8 elements. */ public static Tuple8 Tuple(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { return Tuple.of(t1, t2, t3, t4, t5, t6, t7, t8); } // -- Either /** * Alias for {@link Either#right(Object)} * * @param Type of left value. * @param Type of right value. * @param right The value. * @return A new {@link Either.Right} instance. */ @SuppressWarnings("unchecked") public static Either.Right Right(R right) { return (Either.Right) Either.right(right); } /** * Alias for {@link Either#left(Object)} * * @param Type of left value. * @param Type of right value. * @param left The value. * @return A new {@link Either.Left} instance. */ @SuppressWarnings("unchecked") public static Either.Left Left(L left) { return (Either.Left) Either.left(left); } // -- Future /** * Alias for {@link Future#of(CheckedFunction0)} * * @param Type of the computation result. * @param computation A computation. * @return A new {@link Future} instance. * @throws NullPointerException if computation is null. */ public static Future Future(CheckedFunction0 computation) { return Future.of(computation); } /** * Alias for {@link Future#of(Executor, CheckedFunction0)} * * @param Type of the computation result. * @param executorService An executor service. * @param computation A computation. * @return A new {@link Future} instance. * @throws NullPointerException if one of executorService or computation is null. */ public static Future Future(Executor executorService, CheckedFunction0 computation) { return Future.of(executorService, computation); } /** * Alias for {@link Future#successful(Object)} * * @param The value type of a successful result. * @param result The result. * @return A succeeded {@link Future}. */ public static Future Future(T result) { return Future.successful(result); } /** * Alias for {@link Future#successful(Executor, Object)} * * @param The value type of a successful result. * @param executorService An {@code ExecutorService}. * @param result The result. * @return A succeeded {@link Future}. * @throws NullPointerException if executorService is null */ public static Future Future(Executor executorService, T result) { return Future.successful(executorService, result); } // -- Lazy /** * Alias for {@link Lazy#of(Supplier)} * * @param type of the lazy value * @param supplier A supplier * @return A new instance of {@link Lazy} */ public static Lazy Lazy(Supplier supplier) { return Lazy.of(supplier); } // -- Option /** * Alias for {@link Option#of(Object)} * * @param type of the value * @param value A value * @return {@link Option.Some} if value is not {@code null}, {@link Option.None} otherwise */ public static Option Option(T value) { return Option.of(value); } /** * Alias for {@link Option#some(Object)} * * @param type of the value * @param value A value * @return {@link Option.Some} */ @SuppressWarnings("unchecked") public static Option.Some Some(T value) { return (Option.Some) Option.some(value); } /** * Alias for {@link Option#none()} * * @param component type * @return the singleton instance of {@link Option.None} */ @SuppressWarnings("unchecked") public static Option.None None() { return (Option.None) Option.none(); } // -- Try /** * Alias for {@link Try#of(CheckedFunction0)} * * @param Component type * @param supplier A checked supplier * @return {@link Try.Success} if no exception occurs, otherwise {@link Try.Failure} if an * exception occurs calling {@code supplier.get()}. */ public static Try Try(CheckedFunction0 supplier) { return Try.of(supplier); } /** * Alias for {@link Try#success(Object)} * * @param Type of the given {@code value}. * @param value A value. * @return A new {@link Try.Success}. */ @SuppressWarnings("unchecked") public static Try.Success Success(T value) { return (Try.Success) Try.success(value); } /** * Alias for {@link Try#failure(Throwable)} * * @param Component type of the {@code Try}. * @param exception An exception. * @return A new {@link Try.Failure}. */ @SuppressWarnings("unchecked") public static Try.Failure Failure(Throwable exception) { return (Try.Failure) Try.failure(exception); } // -- Validation /** * Alias for {@link Validation#valid(Object)} * * @param type of the error * @param type of the given {@code value} * @param value A value * @return {@link Validation.Valid} * @throws NullPointerException if value is null */ @SuppressWarnings("unchecked") public static Validation.Valid Valid(T value) { return (Validation.Valid) Validation.valid(value); } /** * Alias for {@link Validation#invalid(Object)} * * @param type of the given {@code error} * @param type of the value * @param error An error * @return {@link Validation.Invalid} * @throws NullPointerException if error is null */ @SuppressWarnings("unchecked") public static Validation.Invalid Invalid(E error) { return (Validation.Invalid) Validation.invalid(error); } // -- CharSeq /** * Alias for {@link CharSeq#of(char)} * * @param character A character. * @return A new {@link CharSeq} instance containing the given element */ public static CharSeq CharSeq(char character) { return CharSeq.of(character); } /** * Alias for {@link CharSeq#of(char...)} * * @param characters Zero or more characters. * @return A new {@link CharSeq} instance containing the given characters in the same order. * @throws NullPointerException if {@code elements} is null */ public static CharSeq CharSeq(char... characters) { return CharSeq.of(characters); } /** * Alias for {@link CharSeq#of(CharSequence)} * * @param sequence {@code CharSequence} instance. * @return A new {@link CharSeq} instance */ public static CharSeq CharSeq(CharSequence sequence) { return CharSeq.of(sequence); } // -- TRAVERSABLES // -- PriorityQueue /** * Alias for {@link PriorityQueue#empty()} * * @param Component type of element. * @return A new {@link PriorityQueue} empty instance */ public static > PriorityQueue PriorityQueue() { return PriorityQueue.empty(); } /** * Alias for {@link PriorityQueue#empty(Comparator)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @return A new {@link PriorityQueue} empty instance */ public static > PriorityQueue PriorityQueue(Comparator comparator) { return PriorityQueue.empty(comparator); } /** * Alias for {@link PriorityQueue#of(Comparable)} * * @param Component type of element. * @param element An element. * @return A new {@link PriorityQueue} instance containing the given element */ public static > PriorityQueue PriorityQueue(T element) { return PriorityQueue.of(element); } /** * Alias for {@link PriorityQueue#of(Comparator, Object)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @param element An element. * @return A new {@link PriorityQueue} instance containing the given element */ public static PriorityQueue PriorityQueue(Comparator comparator, T element) { return PriorityQueue.of(comparator, element); } /** * Alias for {@link PriorityQueue#of(Comparable...)} * * @param Component type of element. * @param elements Zero or more elements. * @return A new {@link PriorityQueue} instance containing the given elements */ @SuppressWarnings("varargs") @SafeVarargs public static > PriorityQueue PriorityQueue(T... elements) { return PriorityQueue.of(elements); } /** * Alias for {@link PriorityQueue#of(Comparator, Object...)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @param elements Zero or more elements. * @return A new {@link PriorityQueue} instance containing the given elements */ @SuppressWarnings("varargs") @SafeVarargs public static PriorityQueue PriorityQueue(Comparator comparator, T... elements) { return PriorityQueue.of(comparator, elements); } // -- SEQUENCES // -- Seq /** * Alias for {@link List#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link List} */ public static Seq Seq() { return List.empty(); } /** * Alias for {@link List#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link List} instance containing the given element */ public static Seq Seq(T element) { return List.of(element); } /** * Alias for {@link List#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link List} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Seq Seq(T... elements) { return List.of(elements); } // -- IndexedSeq /** * Alias for {@link Vector#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link Vector} */ public static IndexedSeq IndexedSeq() { return Vector.empty(); } /** * Alias for {@link Vector#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link Vector} instance containing the given element */ public static IndexedSeq IndexedSeq(T element) { return Vector.of(element); } /** * Alias for {@link Vector#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link Vector} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static IndexedSeq IndexedSeq(T... elements) { return Vector.of(elements); } // -- Array /** * Alias for {@link Array#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link Array} */ public static Array Array() { return Array.empty(); } /** * Alias for {@link Array#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link Array} instance containing the given element */ public static Array Array(T element) { return Array.of(element); } /** * Alias for {@link Array#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link Array} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Array Array(T... elements) { return Array.of(elements); } // -- List /** * Alias for {@link List#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link List} */ public static List List() { return List.empty(); } /** * Alias for {@link List#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link List} instance containing the given element */ public static List List(T element) { return List.of(element); } /** * Alias for {@link List#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link List} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static List List(T... elements) { return List.of(elements); } // -- Queue /** * Alias for {@link Queue#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link Queue} */ public static Queue Queue() { return Queue.empty(); } /** * Alias for {@link Queue#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link Queue} instance containing the given element */ public static Queue Queue(T element) { return Queue.of(element); } /** * Alias for {@link Queue#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link Queue} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Queue Queue(T... elements) { return Queue.of(elements); } // -- Stream /** * Alias for {@link Stream#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link Stream} */ public static Stream Stream() { return Stream.empty(); } /** * Alias for {@link Stream#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link Stream} instance containing the given element */ public static Stream Stream(T element) { return Stream.of(element); } /** * Alias for {@link Stream#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link Stream} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Stream Stream(T... elements) { return Stream.of(elements); } // -- Vector /** * Alias for {@link Vector#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link Vector} */ public static Vector Vector() { return Vector.empty(); } /** * Alias for {@link Vector#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link Vector} instance containing the given element */ public static Vector Vector(T element) { return Vector.of(element); } /** * Alias for {@link Vector#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link Vector} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Vector Vector(T... elements) { return Vector.of(elements); } // -- SETS // -- Set /** * Alias for {@link HashSet#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link HashSet} */ public static Set Set() { return HashSet.empty(); } /** * Alias for {@link HashSet#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link HashSet} instance containing the given element */ public static Set Set(T element) { return HashSet.of(element); } /** * Alias for {@link HashSet#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link HashSet} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Set Set(T... elements) { return HashSet.of(elements); } // -- LinkedSet /** * Alias for {@link LinkedHashSet#empty()} * * @param Component type of element. * @return A singleton instance of empty {@link LinkedHashSet} */ public static Set LinkedSet() { return LinkedHashSet.empty(); } /** * Alias for {@link LinkedHashSet#of(Object)} * * @param Component type of element. * @param element An element. * @return A new {@link LinkedHashSet} instance containing the given element */ public static Set LinkedSet(T element) { return LinkedHashSet.of(element); } /** * Alias for {@link LinkedHashSet#of(Object...)} * * @param Component type of elements. * @param elements Zero or more elements. * @return A new {@link LinkedHashSet} instance containing the given elements * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Set LinkedSet(T... elements) { return LinkedHashSet.of(elements); } // -- SortedSet /** * Alias for {@link TreeSet#empty()} * * @param Component type of element. * @return A new {@link TreeSet} empty instance */ public static > SortedSet SortedSet() { return TreeSet.empty(); } /** * Alias for {@link TreeSet#empty(Comparator)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @return A new {@link TreeSet} empty instance */ public static > SortedSet SortedSet(Comparator comparator) { return TreeSet.empty(comparator); } /** * Alias for {@link TreeSet#of(Comparable)} * * @param Component type of element. * @param element An element. * @return A new {@link TreeSet} instance containing the given element */ public static > SortedSet SortedSet(T element) { return TreeSet.of(element); } /** * Alias for {@link TreeSet#of(Comparator, Object)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @param element An element. * @return A new {@link TreeSet} instance containing the given element */ public static SortedSet SortedSet(Comparator comparator, T element) { return TreeSet.of(comparator, element); } /** * Alias for {@link TreeSet#of(Comparable...)} * * @param Component type of element. * @param elements Zero or more elements. * @return A new {@link TreeSet} instance containing the given elements */ @SuppressWarnings("varargs") @SafeVarargs public static > SortedSet SortedSet(T... elements) { return TreeSet.of(elements); } /** * Alias for {@link TreeSet#of(Comparator, Object...)} * * @param Component type of element. * @param comparator The comparator used to sort the elements * @param elements Zero or more elements. * @return A new {@link TreeSet} instance containing the given elements */ @SuppressWarnings("varargs") @SafeVarargs public static SortedSet SortedSet(Comparator comparator, T... elements) { return TreeSet.of(comparator, elements); } // -- MAPS // -- Map /** * Alias for {@link HashMap#empty()} * * @param The key type. * @param The value type. * @return A singleton instance of empty {@link HashMap} */ public static Map Map() { return HashMap.empty(); } /** * Alias for {@link HashMap#ofEntries(Tuple2...)} * * @param The key type. * @param The value type. * @param entries Map entries. * @return A new {@link HashMap} instance containing the given entries * @deprecated Will be removed in a future version. */ @Deprecated @SuppressWarnings("varargs") @SafeVarargs public static Map Map(Tuple2... entries) { return HashMap.ofEntries(entries); } /** * Alias for {@link HashMap#of(Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key * @param v1 The value * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1) { return HashMap.of(k1, v1); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2) { return HashMap.of(k1, v1, k2, v2); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3) { return HashMap.of(k1, v1, k2, v2, k3, v3); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { return HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { return HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { return HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @param k9 The key of the 9th pair * @param v9 The value of the 9th pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { return HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** * Alias for {@link HashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @param k9 The key of the 9th pair * @param v9 The value of the 9th pair * @param k10 The key of the 10th pair * @param v10 The value of the 10th pair * @return A new {@link HashMap} instance containing the given entries */ public static Map Map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { return HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } // -- LinkedMap /** * Alias for {@link LinkedHashMap#empty()} * * @param The key type. * @param The value type. * @return A singleton instance of empty {@link LinkedHashMap} */ public static Map LinkedMap() { return LinkedHashMap.empty(); } /** * Alias for {@link LinkedHashMap#ofEntries(Tuple2...)} * * @param The key type. * @param The value type. * @param entries Map entries. * @return A new {@link LinkedHashMap} instance containing the given entries * @deprecated Will be removed in a future version. */ @Deprecated @SuppressWarnings("varargs") @SafeVarargs public static Map LinkedMap(Tuple2... entries) { return LinkedHashMap.ofEntries(entries); } /** * Alias for {@link LinkedHashMap#of(Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key * @param v1 The value * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1) { return LinkedHashMap.of(k1, v1); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2) { return LinkedHashMap.of(k1, v1, k2, v2); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3, k4, v4); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @param k9 The key of the 9th pair * @param v9 The value of the 9th pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** * Alias for {@link LinkedHashMap#of(Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @param k9 The key of the 9th pair * @param v9 The value of the 9th pair * @param k10 The key of the 10th pair * @param v10 The value of the 10th pair * @return A new {@link LinkedHashMap} instance containing the given entries */ public static Map LinkedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { return LinkedHashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } /** * Alias for {@link TreeMap#empty()} * * @param The key type. * @param The value type. * @return A new empty {@link TreeMap} instance */ public static , V> SortedMap SortedMap() { return TreeMap.empty(); } /** * Alias for {@link TreeMap#empty(Comparator)} * * @param The key type. * @param The value type. * @param keyComparator The comparator used to sort the entries by their key * @return A new empty {@link TreeMap} instance */ public static SortedMap SortedMap(Comparator keyComparator) { return TreeMap.empty(keyComparator); } /** * Alias for {@link TreeMap#of(Comparator, Object, Object)} * * @param The key type. * @param The value type. * @param keyComparator The comparator used to sort the entries by their key * @param key A singleton map key. * @param value A singleton map value. * @return A new {@link TreeMap} instance containing the given entry */ public static SortedMap SortedMap(Comparator keyComparator, K key, V value) { return TreeMap.of(keyComparator, key, value); } /** * Alias for {@link TreeMap#ofEntries(Tuple2...)} * * @param The key type. * @param The value type. * @param entries Map entries. * @return A new {@link TreeMap} instance containing the given entries * @deprecated Will be removed in a future version. */ @Deprecated @SuppressWarnings("varargs") @SafeVarargs public static , V> SortedMap SortedMap(Tuple2... entries) { return TreeMap.ofEntries(entries); } /** * Alias for {@link TreeMap#ofEntries(Comparator, Tuple2...)} * * @param The key type. * @param The value type. * @param keyComparator The comparator used to sort the entries by their key * @param entries Map entries. * @return A new {@link TreeMap} instance containing the given entry * @deprecated Will be removed in a future version. */ @Deprecated @SuppressWarnings("varargs") @SafeVarargs public static SortedMap SortedMap(Comparator keyComparator, Tuple2... entries) { return TreeMap.ofEntries(keyComparator, entries); } /** * Alias for {@link TreeMap#ofAll(java.util.Map)} * * @param The key type. * @param The value type. * @param map A map entry. * @return A new {@link TreeMap} instance containing the given map * @deprecated Will be removed in a future version. */ @Deprecated public static , V> SortedMap SortedMap(java.util.Map map) { return TreeMap.ofAll(map); } /** * Alias for {@link TreeMap#of(Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key * @param v1 The value * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1) { return TreeMap.of(k1, v1); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2) { return TreeMap.of(k1, v1, k2, v2); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3) { return TreeMap.of(k1, v1, k2, v2, k3, v3); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return TreeMap.of(k1, v1, k2, v2, k3, v3, k4, v4); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return TreeMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { return TreeMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { return TreeMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { return TreeMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @param k9 The key of the 9th pair * @param v9 The value of the 9th pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { return TreeMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** * Alias for {@link TreeMap#of(Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object, Comparable, Object)} * * @param The key type. * @param The value type. * @param k1 The key of the 1st pair * @param v1 The value of the 1st pair * @param k2 The key of the 2nd pair * @param v2 The value of the 2nd pair * @param k3 The key of the 3rd pair * @param v3 The value of the 3rd pair * @param k4 The key of the 4th pair * @param v4 The value of the 4th pair * @param k5 The key of the 5th pair * @param v5 The value of the 5th pair * @param k6 The key of the 6th pair * @param v6 The value of the 6th pair * @param k7 The key of the 7th pair * @param v7 The value of the 7th pair * @param k8 The key of the 8th pair * @param v8 The value of the 8th pair * @param k9 The key of the 9th pair * @param v9 The value of the 9th pair * @param k10 The key of the 10th pair * @param v10 The value of the 10th pair * @return A new {@link TreeMap} instance containing the given entries */ public static , V> SortedMap SortedMap(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { return TreeMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } // // Java type tweaks // /** * Runs a {@code unit} of work and returns {@code Void}. This is helpful when a return value is expected, * e.g. by {@code Match}: * *
Match(i).of(
     *     Case($(is(0)), i -> run(() -> System.out.println("zero"))),
     *     Case($(is(1)), i -> run(() -> System.out.println("one"))),
     *     Case($(), o -> run(() -> System.out.println("many")))
     * )
* * @param unit A block of code to be run. * @return the single instance of {@code Void}, namely {@code null} */ public static Void run(Runnable unit) { unit.run(); return null; } // // For-Comprehension // /** * A shortcut for {@code Iterator.ofAll(ts).flatMap(f)} which allows us to write real for-comprehensions using * {@code For(...).yield(...)}. *

* Example: *


     * For(getPersons(), person ->
     *     For(person.getTweets(), tweet ->
     *         For(tweet.getReplies())
     *             .yield(reply -> person + ", " + tweet + ", " + reply)));
     * 
* * @param ts An iterable * @param f A function {@code T -> Iterable} * @param element type of {@code ts} * @param component type of the resulting {@code Iterator} * @return A new Iterator */ public static Iterator For(Iterable ts, Function> f) { return Iterator.ofAll(ts).flatMap(f); } /** * Creates a {@code For}-comprehension of one Iterable. * * @param ts1 the 1st Iterable * @param component type of the 1st Iterable * @return a new {@code For}-comprehension of arity 1 */ public static For1 For(Iterable ts1) { Objects.requireNonNull(ts1, "ts1 is null"); return new For1<>(ts1); } /** * Creates a {@code For}-comprehension of two Iterables. * * @param ts1 the 1st Iterable * @param ts2 the 2nd Iterable * @param component type of the 1st Iterable * @param component type of the 2nd Iterable * @return a new {@code For}-comprehension of arity 2 */ public static For2 For(Iterable ts1, Iterable ts2) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); return new For2<>(ts1, ts2); } /** * Creates a {@code For}-comprehension of three Iterables. * * @param ts1 the 1st Iterable * @param ts2 the 2nd Iterable * @param ts3 the 3rd Iterable * @param component type of the 1st Iterable * @param component type of the 2nd Iterable * @param component type of the 3rd Iterable * @return a new {@code For}-comprehension of arity 3 */ public static For3 For(Iterable ts1, Iterable ts2, Iterable ts3) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); return new For3<>(ts1, ts2, ts3); } /** * Creates a {@code For}-comprehension of 4 Iterables. * * @param ts1 the 1st Iterable * @param ts2 the 2nd Iterable * @param ts3 the 3rd Iterable * @param ts4 the 4th Iterable * @param component type of the 1st Iterable * @param component type of the 2nd Iterable * @param component type of the 3rd Iterable * @param component type of the 4th Iterable * @return a new {@code For}-comprehension of arity 4 */ public static For4 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); return new For4<>(ts1, ts2, ts3, ts4); } /** * Creates a {@code For}-comprehension of 5 Iterables. * * @param ts1 the 1st Iterable * @param ts2 the 2nd Iterable * @param ts3 the 3rd Iterable * @param ts4 the 4th Iterable * @param ts5 the 5th Iterable * @param component type of the 1st Iterable * @param component type of the 2nd Iterable * @param component type of the 3rd Iterable * @param component type of the 4th Iterable * @param component type of the 5th Iterable * @return a new {@code For}-comprehension of arity 5 */ public static For5 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); return new For5<>(ts1, ts2, ts3, ts4, ts5); } /** * Creates a {@code For}-comprehension of 6 Iterables. * * @param ts1 the 1st Iterable * @param ts2 the 2nd Iterable * @param ts3 the 3rd Iterable * @param ts4 the 4th Iterable * @param ts5 the 5th Iterable * @param ts6 the 6th Iterable * @param component type of the 1st Iterable * @param component type of the 2nd Iterable * @param component type of the 3rd Iterable * @param component type of the 4th Iterable * @param component type of the 5th Iterable * @param component type of the 6th Iterable * @return a new {@code For}-comprehension of arity 6 */ public static For6 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); return new For6<>(ts1, ts2, ts3, ts4, ts5, ts6); } /** * Creates a {@code For}-comprehension of 7 Iterables. * * @param ts1 the 1st Iterable * @param ts2 the 2nd Iterable * @param ts3 the 3rd Iterable * @param ts4 the 4th Iterable * @param ts5 the 5th Iterable * @param ts6 the 6th Iterable * @param ts7 the 7th Iterable * @param component type of the 1st Iterable * @param component type of the 2nd Iterable * @param component type of the 3rd Iterable * @param component type of the 4th Iterable * @param component type of the 5th Iterable * @param component type of the 6th Iterable * @param component type of the 7th Iterable * @return a new {@code For}-comprehension of arity 7 */ public static For7 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); return new For7<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7); } /** * Creates a {@code For}-comprehension of 8 Iterables. * * @param ts1 the 1st Iterable * @param ts2 the 2nd Iterable * @param ts3 the 3rd Iterable * @param ts4 the 4th Iterable * @param ts5 the 5th Iterable * @param ts6 the 6th Iterable * @param ts7 the 7th Iterable * @param ts8 the 8th Iterable * @param component type of the 1st Iterable * @param component type of the 2nd Iterable * @param component type of the 3rd Iterable * @param component type of the 4th Iterable * @param component type of the 5th Iterable * @param component type of the 6th Iterable * @param component type of the 7th Iterable * @param component type of the 8th Iterable * @return a new {@code For}-comprehension of arity 8 */ public static For8 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7, Iterable ts8) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); Objects.requireNonNull(ts8, "ts8 is null"); return new For8<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8); } /** * Creates a {@code For}-comprehension of one Option. * * @param ts1 the 1st Option * @param component type of the 1st Option * @return a new {@code For}-comprehension of arity 1 */ public static For1Option For(Option ts1) { Objects.requireNonNull(ts1, "ts1 is null"); return new For1Option<>(ts1); } /** * Creates a {@code For}-comprehension of two Options. * * @param ts1 the 1st Option * @param ts2 the 2nd Option * @param component type of the 1st Option * @param component type of the 2nd Option * @return a new {@code For}-comprehension of arity 2 */ public static For2Option For(Option ts1, Option ts2) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); return new For2Option<>(ts1, ts2); } /** * Creates a {@code For}-comprehension of three Options. * * @param ts1 the 1st Option * @param ts2 the 2nd Option * @param ts3 the 3rd Option * @param component type of the 1st Option * @param component type of the 2nd Option * @param component type of the 3rd Option * @return a new {@code For}-comprehension of arity 3 */ public static For3Option For(Option ts1, Option ts2, Option ts3) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); return new For3Option<>(ts1, ts2, ts3); } /** * Creates a {@code For}-comprehension of 4 Options. * * @param ts1 the 1st Option * @param ts2 the 2nd Option * @param ts3 the 3rd Option * @param ts4 the 4th Option * @param component type of the 1st Option * @param component type of the 2nd Option * @param component type of the 3rd Option * @param component type of the 4th Option * @return a new {@code For}-comprehension of arity 4 */ public static For4Option For(Option ts1, Option ts2, Option ts3, Option ts4) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); return new For4Option<>(ts1, ts2, ts3, ts4); } /** * Creates a {@code For}-comprehension of 5 Options. * * @param ts1 the 1st Option * @param ts2 the 2nd Option * @param ts3 the 3rd Option * @param ts4 the 4th Option * @param ts5 the 5th Option * @param component type of the 1st Option * @param component type of the 2nd Option * @param component type of the 3rd Option * @param component type of the 4th Option * @param component type of the 5th Option * @return a new {@code For}-comprehension of arity 5 */ public static For5Option For(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); return new For5Option<>(ts1, ts2, ts3, ts4, ts5); } /** * Creates a {@code For}-comprehension of 6 Options. * * @param ts1 the 1st Option * @param ts2 the 2nd Option * @param ts3 the 3rd Option * @param ts4 the 4th Option * @param ts5 the 5th Option * @param ts6 the 6th Option * @param component type of the 1st Option * @param component type of the 2nd Option * @param component type of the 3rd Option * @param component type of the 4th Option * @param component type of the 5th Option * @param component type of the 6th Option * @return a new {@code For}-comprehension of arity 6 */ public static For6Option For(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5, Option ts6) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); return new For6Option<>(ts1, ts2, ts3, ts4, ts5, ts6); } /** * Creates a {@code For}-comprehension of 7 Options. * * @param ts1 the 1st Option * @param ts2 the 2nd Option * @param ts3 the 3rd Option * @param ts4 the 4th Option * @param ts5 the 5th Option * @param ts6 the 6th Option * @param ts7 the 7th Option * @param component type of the 1st Option * @param component type of the 2nd Option * @param component type of the 3rd Option * @param component type of the 4th Option * @param component type of the 5th Option * @param component type of the 6th Option * @param component type of the 7th Option * @return a new {@code For}-comprehension of arity 7 */ public static For7Option For(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5, Option ts6, Option ts7) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); return new For7Option<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7); } /** * Creates a {@code For}-comprehension of 8 Options. * * @param ts1 the 1st Option * @param ts2 the 2nd Option * @param ts3 the 3rd Option * @param ts4 the 4th Option * @param ts5 the 5th Option * @param ts6 the 6th Option * @param ts7 the 7th Option * @param ts8 the 8th Option * @param component type of the 1st Option * @param component type of the 2nd Option * @param component type of the 3rd Option * @param component type of the 4th Option * @param component type of the 5th Option * @param component type of the 6th Option * @param component type of the 7th Option * @param component type of the 8th Option * @return a new {@code For}-comprehension of arity 8 */ public static For8Option For(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5, Option ts6, Option ts7, Option ts8) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); Objects.requireNonNull(ts8, "ts8 is null"); return new For8Option<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8); } /** * Creates a {@code For}-comprehension of one Future. * * @param ts1 the 1st Future * @param component type of the 1st Future * @return a new {@code For}-comprehension of arity 1 */ public static For1Future For(Future ts1) { Objects.requireNonNull(ts1, "ts1 is null"); return new For1Future<>(ts1); } /** * Creates a {@code For}-comprehension of two Futures. * * @param ts1 the 1st Future * @param ts2 the 2nd Future * @param component type of the 1st Future * @param component type of the 2nd Future * @return a new {@code For}-comprehension of arity 2 */ public static For2Future For(Future ts1, Future ts2) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); return new For2Future<>(ts1, ts2); } /** * Creates a {@code For}-comprehension of three Futures. * * @param ts1 the 1st Future * @param ts2 the 2nd Future * @param ts3 the 3rd Future * @param component type of the 1st Future * @param component type of the 2nd Future * @param component type of the 3rd Future * @return a new {@code For}-comprehension of arity 3 */ public static For3Future For(Future ts1, Future ts2, Future ts3) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); return new For3Future<>(ts1, ts2, ts3); } /** * Creates a {@code For}-comprehension of 4 Futures. * * @param ts1 the 1st Future * @param ts2 the 2nd Future * @param ts3 the 3rd Future * @param ts4 the 4th Future * @param component type of the 1st Future * @param component type of the 2nd Future * @param component type of the 3rd Future * @param component type of the 4th Future * @return a new {@code For}-comprehension of arity 4 */ public static For4Future For(Future ts1, Future ts2, Future ts3, Future ts4) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); return new For4Future<>(ts1, ts2, ts3, ts4); } /** * Creates a {@code For}-comprehension of 5 Futures. * * @param ts1 the 1st Future * @param ts2 the 2nd Future * @param ts3 the 3rd Future * @param ts4 the 4th Future * @param ts5 the 5th Future * @param component type of the 1st Future * @param component type of the 2nd Future * @param component type of the 3rd Future * @param component type of the 4th Future * @param component type of the 5th Future * @return a new {@code For}-comprehension of arity 5 */ public static For5Future For(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); return new For5Future<>(ts1, ts2, ts3, ts4, ts5); } /** * Creates a {@code For}-comprehension of 6 Futures. * * @param ts1 the 1st Future * @param ts2 the 2nd Future * @param ts3 the 3rd Future * @param ts4 the 4th Future * @param ts5 the 5th Future * @param ts6 the 6th Future * @param component type of the 1st Future * @param component type of the 2nd Future * @param component type of the 3rd Future * @param component type of the 4th Future * @param component type of the 5th Future * @param component type of the 6th Future * @return a new {@code For}-comprehension of arity 6 */ public static For6Future For(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5, Future ts6) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); return new For6Future<>(ts1, ts2, ts3, ts4, ts5, ts6); } /** * Creates a {@code For}-comprehension of 7 Futures. * * @param ts1 the 1st Future * @param ts2 the 2nd Future * @param ts3 the 3rd Future * @param ts4 the 4th Future * @param ts5 the 5th Future * @param ts6 the 6th Future * @param ts7 the 7th Future * @param component type of the 1st Future * @param component type of the 2nd Future * @param component type of the 3rd Future * @param component type of the 4th Future * @param component type of the 5th Future * @param component type of the 6th Future * @param component type of the 7th Future * @return a new {@code For}-comprehension of arity 7 */ public static For7Future For(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5, Future ts6, Future ts7) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); return new For7Future<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7); } /** * Creates a {@code For}-comprehension of 8 Futures. * * @param ts1 the 1st Future * @param ts2 the 2nd Future * @param ts3 the 3rd Future * @param ts4 the 4th Future * @param ts5 the 5th Future * @param ts6 the 6th Future * @param ts7 the 7th Future * @param ts8 the 8th Future * @param component type of the 1st Future * @param component type of the 2nd Future * @param component type of the 3rd Future * @param component type of the 4th Future * @param component type of the 5th Future * @param component type of the 6th Future * @param component type of the 7th Future * @param component type of the 8th Future * @return a new {@code For}-comprehension of arity 8 */ public static For8Future For(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5, Future ts6, Future ts7, Future ts8) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); Objects.requireNonNull(ts8, "ts8 is null"); return new For8Future<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8); } /** * Creates a {@code For}-comprehension of one Try. * * @param ts1 the 1st Try * @param component type of the 1st Try * @return a new {@code For}-comprehension of arity 1 */ public static For1Try For(Try ts1) { Objects.requireNonNull(ts1, "ts1 is null"); return new For1Try<>(ts1); } /** * Creates a {@code For}-comprehension of two Trys. * * @param ts1 the 1st Try * @param ts2 the 2nd Try * @param component type of the 1st Try * @param component type of the 2nd Try * @return a new {@code For}-comprehension of arity 2 */ public static For2Try For(Try ts1, Try ts2) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); return new For2Try<>(ts1, ts2); } /** * Creates a {@code For}-comprehension of three Trys. * * @param ts1 the 1st Try * @param ts2 the 2nd Try * @param ts3 the 3rd Try * @param component type of the 1st Try * @param component type of the 2nd Try * @param component type of the 3rd Try * @return a new {@code For}-comprehension of arity 3 */ public static For3Try For(Try ts1, Try ts2, Try ts3) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); return new For3Try<>(ts1, ts2, ts3); } /** * Creates a {@code For}-comprehension of 4 Trys. * * @param ts1 the 1st Try * @param ts2 the 2nd Try * @param ts3 the 3rd Try * @param ts4 the 4th Try * @param component type of the 1st Try * @param component type of the 2nd Try * @param component type of the 3rd Try * @param component type of the 4th Try * @return a new {@code For}-comprehension of arity 4 */ public static For4Try For(Try ts1, Try ts2, Try ts3, Try ts4) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); return new For4Try<>(ts1, ts2, ts3, ts4); } /** * Creates a {@code For}-comprehension of 5 Trys. * * @param ts1 the 1st Try * @param ts2 the 2nd Try * @param ts3 the 3rd Try * @param ts4 the 4th Try * @param ts5 the 5th Try * @param component type of the 1st Try * @param component type of the 2nd Try * @param component type of the 3rd Try * @param component type of the 4th Try * @param component type of the 5th Try * @return a new {@code For}-comprehension of arity 5 */ public static For5Try For(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); return new For5Try<>(ts1, ts2, ts3, ts4, ts5); } /** * Creates a {@code For}-comprehension of 6 Trys. * * @param ts1 the 1st Try * @param ts2 the 2nd Try * @param ts3 the 3rd Try * @param ts4 the 4th Try * @param ts5 the 5th Try * @param ts6 the 6th Try * @param component type of the 1st Try * @param component type of the 2nd Try * @param component type of the 3rd Try * @param component type of the 4th Try * @param component type of the 5th Try * @param component type of the 6th Try * @return a new {@code For}-comprehension of arity 6 */ public static For6Try For(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5, Try ts6) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); return new For6Try<>(ts1, ts2, ts3, ts4, ts5, ts6); } /** * Creates a {@code For}-comprehension of 7 Trys. * * @param ts1 the 1st Try * @param ts2 the 2nd Try * @param ts3 the 3rd Try * @param ts4 the 4th Try * @param ts5 the 5th Try * @param ts6 the 6th Try * @param ts7 the 7th Try * @param component type of the 1st Try * @param component type of the 2nd Try * @param component type of the 3rd Try * @param component type of the 4th Try * @param component type of the 5th Try * @param component type of the 6th Try * @param component type of the 7th Try * @return a new {@code For}-comprehension of arity 7 */ public static For7Try For(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5, Try ts6, Try ts7) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); return new For7Try<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7); } /** * Creates a {@code For}-comprehension of 8 Trys. * * @param ts1 the 1st Try * @param ts2 the 2nd Try * @param ts3 the 3rd Try * @param ts4 the 4th Try * @param ts5 the 5th Try * @param ts6 the 6th Try * @param ts7 the 7th Try * @param ts8 the 8th Try * @param component type of the 1st Try * @param component type of the 2nd Try * @param component type of the 3rd Try * @param component type of the 4th Try * @param component type of the 5th Try * @param component type of the 6th Try * @param component type of the 7th Try * @param component type of the 8th Try * @return a new {@code For}-comprehension of arity 8 */ public static For8Try For(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5, Try ts6, Try ts7, Try ts8) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); Objects.requireNonNull(ts8, "ts8 is null"); return new For8Try<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8); } /** * Creates a {@code For}-comprehension of one List. * * @param ts1 the 1st List * @param component type of the 1st List * @return a new {@code For}-comprehension of arity 1 */ public static For1List For(List ts1) { Objects.requireNonNull(ts1, "ts1 is null"); return new For1List<>(ts1); } /** * Creates a {@code For}-comprehension of two Lists. * * @param ts1 the 1st List * @param ts2 the 2nd List * @param component type of the 1st List * @param component type of the 2nd List * @return a new {@code For}-comprehension of arity 2 */ public static For2List For(List ts1, List ts2) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); return new For2List<>(ts1, ts2); } /** * Creates a {@code For}-comprehension of three Lists. * * @param ts1 the 1st List * @param ts2 the 2nd List * @param ts3 the 3rd List * @param component type of the 1st List * @param component type of the 2nd List * @param component type of the 3rd List * @return a new {@code For}-comprehension of arity 3 */ public static For3List For(List ts1, List ts2, List ts3) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); return new For3List<>(ts1, ts2, ts3); } /** * Creates a {@code For}-comprehension of 4 Lists. * * @param ts1 the 1st List * @param ts2 the 2nd List * @param ts3 the 3rd List * @param ts4 the 4th List * @param component type of the 1st List * @param component type of the 2nd List * @param component type of the 3rd List * @param component type of the 4th List * @return a new {@code For}-comprehension of arity 4 */ public static For4List For(List ts1, List ts2, List ts3, List ts4) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); return new For4List<>(ts1, ts2, ts3, ts4); } /** * Creates a {@code For}-comprehension of 5 Lists. * * @param ts1 the 1st List * @param ts2 the 2nd List * @param ts3 the 3rd List * @param ts4 the 4th List * @param ts5 the 5th List * @param component type of the 1st List * @param component type of the 2nd List * @param component type of the 3rd List * @param component type of the 4th List * @param component type of the 5th List * @return a new {@code For}-comprehension of arity 5 */ public static For5List For(List ts1, List ts2, List ts3, List ts4, List ts5) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); return new For5List<>(ts1, ts2, ts3, ts4, ts5); } /** * Creates a {@code For}-comprehension of 6 Lists. * * @param ts1 the 1st List * @param ts2 the 2nd List * @param ts3 the 3rd List * @param ts4 the 4th List * @param ts5 the 5th List * @param ts6 the 6th List * @param component type of the 1st List * @param component type of the 2nd List * @param component type of the 3rd List * @param component type of the 4th List * @param component type of the 5th List * @param component type of the 6th List * @return a new {@code For}-comprehension of arity 6 */ public static For6List For(List ts1, List ts2, List ts3, List ts4, List ts5, List ts6) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); return new For6List<>(ts1, ts2, ts3, ts4, ts5, ts6); } /** * Creates a {@code For}-comprehension of 7 Lists. * * @param ts1 the 1st List * @param ts2 the 2nd List * @param ts3 the 3rd List * @param ts4 the 4th List * @param ts5 the 5th List * @param ts6 the 6th List * @param ts7 the 7th List * @param component type of the 1st List * @param component type of the 2nd List * @param component type of the 3rd List * @param component type of the 4th List * @param component type of the 5th List * @param component type of the 6th List * @param component type of the 7th List * @return a new {@code For}-comprehension of arity 7 */ public static For7List For(List ts1, List ts2, List ts3, List ts4, List ts5, List ts6, List ts7) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); return new For7List<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7); } /** * Creates a {@code For}-comprehension of 8 Lists. * * @param ts1 the 1st List * @param ts2 the 2nd List * @param ts3 the 3rd List * @param ts4 the 4th List * @param ts5 the 5th List * @param ts6 the 6th List * @param ts7 the 7th List * @param ts8 the 8th List * @param component type of the 1st List * @param component type of the 2nd List * @param component type of the 3rd List * @param component type of the 4th List * @param component type of the 5th List * @param component type of the 6th List * @param component type of the 7th List * @param component type of the 8th List * @return a new {@code For}-comprehension of arity 8 */ public static For8List For(List ts1, List ts2, List ts3, List ts4, List ts5, List ts6, List ts7, List ts8) { Objects.requireNonNull(ts1, "ts1 is null"); Objects.requireNonNull(ts2, "ts2 is null"); Objects.requireNonNull(ts3, "ts3 is null"); Objects.requireNonNull(ts4, "ts4 is null"); Objects.requireNonNull(ts5, "ts5 is null"); Objects.requireNonNull(ts6, "ts6 is null"); Objects.requireNonNull(ts7, "ts7 is null"); Objects.requireNonNull(ts8, "ts8 is null"); return new For8List<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8); } /** * For-comprehension with one Iterable. */ public static class For1 { private final Iterable ts1; private For1(Iterable ts1) { this.ts1 = ts1; } /** * Yields a result for elements of the cross product of the underlying Iterable. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(Function f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).map(f); } /** * A shortcut for {@code yield(Function.identity())}. * * @return an {@code Iterator} of mapped results */ public Iterator yield() { return yield(Function.identity()); } } /** * For-comprehension with two Iterables. */ public static class For2 { private final Iterable ts1; private final Iterable ts2; private For2(Iterable ts1, Iterable ts2) { this.ts1 = ts1; this.ts2 = ts2; } /** * Yields a result for elements of the cross product of the underlying Iterables. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(BiFunction f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).flatMap(t1 -> Iterator.ofAll(ts2).map(t2 -> f.apply(t1, t2))); } } /** * For-comprehension with three Iterables. */ public static class For3 { private final Iterable ts1; private final Iterable ts2; private final Iterable ts3; private For3(Iterable ts1, Iterable ts2, Iterable ts3) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; } /** * Yields a result for elements of the cross product of the underlying Iterables. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(Function3 f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).flatMap(t1 -> Iterator.ofAll(ts2).flatMap(t2 -> Iterator.ofAll(ts3).map(t3 -> f.apply(t1, t2, t3)))); } } /** * For-comprehension with 4 Iterables. */ public static class For4 { private final Iterable ts1; private final Iterable ts2; private final Iterable ts3; private final Iterable ts4; private For4(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; } /** * Yields a result for elements of the cross product of the underlying Iterables. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(Function4 f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).flatMap(t1 -> Iterator.ofAll(ts2).flatMap(t2 -> Iterator.ofAll(ts3).flatMap(t3 -> Iterator.ofAll(ts4).map(t4 -> f.apply(t1, t2, t3, t4))))); } } /** * For-comprehension with 5 Iterables. */ public static class For5 { private final Iterable ts1; private final Iterable ts2; private final Iterable ts3; private final Iterable ts4; private final Iterable ts5; private For5(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; } /** * Yields a result for elements of the cross product of the underlying Iterables. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(Function5 f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).flatMap(t1 -> Iterator.ofAll(ts2).flatMap(t2 -> Iterator.ofAll(ts3).flatMap(t3 -> Iterator.ofAll(ts4).flatMap(t4 -> Iterator.ofAll(ts5).map(t5 -> f.apply(t1, t2, t3, t4, t5)))))); } } /** * For-comprehension with 6 Iterables. */ public static class For6 { private final Iterable ts1; private final Iterable ts2; private final Iterable ts3; private final Iterable ts4; private final Iterable ts5; private final Iterable ts6; private For6(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; } /** * Yields a result for elements of the cross product of the underlying Iterables. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(Function6 f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).flatMap(t1 -> Iterator.ofAll(ts2).flatMap(t2 -> Iterator.ofAll(ts3).flatMap(t3 -> Iterator.ofAll(ts4).flatMap(t4 -> Iterator.ofAll(ts5).flatMap(t5 -> Iterator.ofAll(ts6).map(t6 -> f.apply(t1, t2, t3, t4, t5, t6))))))); } } /** * For-comprehension with 7 Iterables. */ public static class For7 { private final Iterable ts1; private final Iterable ts2; private final Iterable ts3; private final Iterable ts4; private final Iterable ts5; private final Iterable ts6; private final Iterable ts7; private For7(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; } /** * Yields a result for elements of the cross product of the underlying Iterables. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(Function7 f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).flatMap(t1 -> Iterator.ofAll(ts2).flatMap(t2 -> Iterator.ofAll(ts3).flatMap(t3 -> Iterator.ofAll(ts4).flatMap(t4 -> Iterator.ofAll(ts5).flatMap(t5 -> Iterator.ofAll(ts6).flatMap(t6 -> Iterator.ofAll(ts7).map(t7 -> f.apply(t1, t2, t3, t4, t5, t6, t7)))))))); } } /** * For-comprehension with 8 Iterables. */ public static class For8 { private final Iterable ts1; private final Iterable ts2; private final Iterable ts3; private final Iterable ts4; private final Iterable ts5; private final Iterable ts6; private final Iterable ts7; private final Iterable ts8; private For8(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7, Iterable ts8) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; this.ts8 = ts8; } /** * Yields a result for elements of the cross product of the underlying Iterables. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Iterator} elements * @return an {@code Iterator} of mapped results */ public Iterator yield(Function8 f) { Objects.requireNonNull(f, "f is null"); return Iterator.ofAll(ts1).flatMap(t1 -> Iterator.ofAll(ts2).flatMap(t2 -> Iterator.ofAll(ts3).flatMap(t3 -> Iterator.ofAll(ts4).flatMap(t4 -> Iterator.ofAll(ts5).flatMap(t5 -> Iterator.ofAll(ts6).flatMap(t6 -> Iterator.ofAll(ts7).flatMap(t7 -> Iterator.ofAll(ts8).map(t8 -> f.apply(t1, t2, t3, t4, t5, t6, t7, t8))))))))); } } /** * For-comprehension with one Option. */ public static class For1Option { private final Option ts1; private For1Option(Option ts1) { this.ts1 = ts1; } /** * Yields a result for elements of the cross product of the underlying Option. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(Function f) { Objects.requireNonNull(f, "f is null"); return ts1.map(f); } /** * A shortcut for {@code yield(Function.identity())}. * * @return an {@code Iterator} of mapped results */ public Option yield() { return yield(Function.identity()); } } /** * For-comprehension with two Options. */ public static class For2Option { private final Option ts1; private final Option ts2; private For2Option(Option ts1, Option ts2) { this.ts1 = ts1; this.ts2 = ts2; } /** * Yields a result for elements of the cross product of the underlying Options. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(BiFunction f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.map(t2 -> f.apply(t1, t2))); } } /** * For-comprehension with three Options. */ public static class For3Option { private final Option ts1; private final Option ts2; private final Option ts3; private For3Option(Option ts1, Option ts2, Option ts3) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; } /** * Yields a result for elements of the cross product of the underlying Options. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(Function3 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.map(t3 -> f.apply(t1, t2, t3)))); } } /** * For-comprehension with 4 Options. */ public static class For4Option { private final Option ts1; private final Option ts2; private final Option ts3; private final Option ts4; private For4Option(Option ts1, Option ts2, Option ts3, Option ts4) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; } /** * Yields a result for elements of the cross product of the underlying Options. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(Function4 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.map(t4 -> f.apply(t1, t2, t3, t4))))); } } /** * For-comprehension with 5 Options. */ public static class For5Option { private final Option ts1; private final Option ts2; private final Option ts3; private final Option ts4; private final Option ts5; private For5Option(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; } /** * Yields a result for elements of the cross product of the underlying Options. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(Function5 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.map(t5 -> f.apply(t1, t2, t3, t4, t5)))))); } } /** * For-comprehension with 6 Options. */ public static class For6Option { private final Option ts1; private final Option ts2; private final Option ts3; private final Option ts4; private final Option ts5; private final Option ts6; private For6Option(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5, Option ts6) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; } /** * Yields a result for elements of the cross product of the underlying Options. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(Function6 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.map(t6 -> f.apply(t1, t2, t3, t4, t5, t6))))))); } } /** * For-comprehension with 7 Options. */ public static class For7Option { private final Option ts1; private final Option ts2; private final Option ts3; private final Option ts4; private final Option ts5; private final Option ts6; private final Option ts7; private For7Option(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5, Option ts6, Option ts7) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; } /** * Yields a result for elements of the cross product of the underlying Options. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(Function7 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.map(t7 -> f.apply(t1, t2, t3, t4, t5, t6, t7)))))))); } } /** * For-comprehension with 8 Options. */ public static class For8Option { private final Option ts1; private final Option ts2; private final Option ts3; private final Option ts4; private final Option ts5; private final Option ts6; private final Option ts7; private final Option ts8; private For8Option(Option ts1, Option ts2, Option ts3, Option ts4, Option ts5, Option ts6, Option ts7, Option ts8) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; this.ts8 = ts8; } /** * Yields a result for elements of the cross product of the underlying Options. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Option} elements * @return an {@code Option} of mapped results */ public Option yield(Function8 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.flatMap(t7 -> ts8.map(t8 -> f.apply(t1, t2, t3, t4, t5, t6, t7, t8))))))))); } } /** * For-comprehension with one Future. */ public static class For1Future { private final Future ts1; private For1Future(Future ts1) { this.ts1 = ts1; } /** * Yields a result for elements of the cross product of the underlying Future. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(Function f) { Objects.requireNonNull(f, "f is null"); return ts1.map(f); } /** * A shortcut for {@code yield(Function.identity())}. * * @return an {@code Iterator} of mapped results */ public Future yield() { return yield(Function.identity()); } } /** * For-comprehension with two Futures. */ public static class For2Future { private final Future ts1; private final Future ts2; private For2Future(Future ts1, Future ts2) { this.ts1 = ts1; this.ts2 = ts2; } /** * Yields a result for elements of the cross product of the underlying Futures. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(BiFunction f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.map(t2 -> f.apply(t1, t2))); } } /** * For-comprehension with three Futures. */ public static class For3Future { private final Future ts1; private final Future ts2; private final Future ts3; private For3Future(Future ts1, Future ts2, Future ts3) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; } /** * Yields a result for elements of the cross product of the underlying Futures. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(Function3 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.map(t3 -> f.apply(t1, t2, t3)))); } } /** * For-comprehension with 4 Futures. */ public static class For4Future { private final Future ts1; private final Future ts2; private final Future ts3; private final Future ts4; private For4Future(Future ts1, Future ts2, Future ts3, Future ts4) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; } /** * Yields a result for elements of the cross product of the underlying Futures. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(Function4 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.map(t4 -> f.apply(t1, t2, t3, t4))))); } } /** * For-comprehension with 5 Futures. */ public static class For5Future { private final Future ts1; private final Future ts2; private final Future ts3; private final Future ts4; private final Future ts5; private For5Future(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; } /** * Yields a result for elements of the cross product of the underlying Futures. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(Function5 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.map(t5 -> f.apply(t1, t2, t3, t4, t5)))))); } } /** * For-comprehension with 6 Futures. */ public static class For6Future { private final Future ts1; private final Future ts2; private final Future ts3; private final Future ts4; private final Future ts5; private final Future ts6; private For6Future(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5, Future ts6) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; } /** * Yields a result for elements of the cross product of the underlying Futures. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(Function6 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.map(t6 -> f.apply(t1, t2, t3, t4, t5, t6))))))); } } /** * For-comprehension with 7 Futures. */ public static class For7Future { private final Future ts1; private final Future ts2; private final Future ts3; private final Future ts4; private final Future ts5; private final Future ts6; private final Future ts7; private For7Future(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5, Future ts6, Future ts7) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; } /** * Yields a result for elements of the cross product of the underlying Futures. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(Function7 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.map(t7 -> f.apply(t1, t2, t3, t4, t5, t6, t7)))))))); } } /** * For-comprehension with 8 Futures. */ public static class For8Future { private final Future ts1; private final Future ts2; private final Future ts3; private final Future ts4; private final Future ts5; private final Future ts6; private final Future ts7; private final Future ts8; private For8Future(Future ts1, Future ts2, Future ts3, Future ts4, Future ts5, Future ts6, Future ts7, Future ts8) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; this.ts8 = ts8; } /** * Yields a result for elements of the cross product of the underlying Futures. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Future} elements * @return an {@code Future} of mapped results */ public Future yield(Function8 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.flatMap(t7 -> ts8.map(t8 -> f.apply(t1, t2, t3, t4, t5, t6, t7, t8))))))))); } } /** * For-comprehension with one Try. */ public static class For1Try { private final Try ts1; private For1Try(Try ts1) { this.ts1 = ts1; } /** * Yields a result for elements of the cross product of the underlying Try. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(Function f) { Objects.requireNonNull(f, "f is null"); return ts1.map(f); } /** * A shortcut for {@code yield(Function.identity())}. * * @return an {@code Iterator} of mapped results */ public Try yield() { return yield(Function.identity()); } } /** * For-comprehension with two Trys. */ public static class For2Try { private final Try ts1; private final Try ts2; private For2Try(Try ts1, Try ts2) { this.ts1 = ts1; this.ts2 = ts2; } /** * Yields a result for elements of the cross product of the underlying Trys. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(BiFunction f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.map(t2 -> f.apply(t1, t2))); } } /** * For-comprehension with three Trys. */ public static class For3Try { private final Try ts1; private final Try ts2; private final Try ts3; private For3Try(Try ts1, Try ts2, Try ts3) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; } /** * Yields a result for elements of the cross product of the underlying Trys. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(Function3 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.map(t3 -> f.apply(t1, t2, t3)))); } } /** * For-comprehension with 4 Trys. */ public static class For4Try { private final Try ts1; private final Try ts2; private final Try ts3; private final Try ts4; private For4Try(Try ts1, Try ts2, Try ts3, Try ts4) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; } /** * Yields a result for elements of the cross product of the underlying Trys. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(Function4 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.map(t4 -> f.apply(t1, t2, t3, t4))))); } } /** * For-comprehension with 5 Trys. */ public static class For5Try { private final Try ts1; private final Try ts2; private final Try ts3; private final Try ts4; private final Try ts5; private For5Try(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; } /** * Yields a result for elements of the cross product of the underlying Trys. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(Function5 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.map(t5 -> f.apply(t1, t2, t3, t4, t5)))))); } } /** * For-comprehension with 6 Trys. */ public static class For6Try { private final Try ts1; private final Try ts2; private final Try ts3; private final Try ts4; private final Try ts5; private final Try ts6; private For6Try(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5, Try ts6) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; } /** * Yields a result for elements of the cross product of the underlying Trys. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(Function6 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.map(t6 -> f.apply(t1, t2, t3, t4, t5, t6))))))); } } /** * For-comprehension with 7 Trys. */ public static class For7Try { private final Try ts1; private final Try ts2; private final Try ts3; private final Try ts4; private final Try ts5; private final Try ts6; private final Try ts7; private For7Try(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5, Try ts6, Try ts7) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; } /** * Yields a result for elements of the cross product of the underlying Trys. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(Function7 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.map(t7 -> f.apply(t1, t2, t3, t4, t5, t6, t7)))))))); } } /** * For-comprehension with 8 Trys. */ public static class For8Try { private final Try ts1; private final Try ts2; private final Try ts3; private final Try ts4; private final Try ts5; private final Try ts6; private final Try ts7; private final Try ts8; private For8Try(Try ts1, Try ts2, Try ts3, Try ts4, Try ts5, Try ts6, Try ts7, Try ts8) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; this.ts8 = ts8; } /** * Yields a result for elements of the cross product of the underlying Trys. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code Try} elements * @return an {@code Try} of mapped results */ public Try yield(Function8 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.flatMap(t7 -> ts8.map(t8 -> f.apply(t1, t2, t3, t4, t5, t6, t7, t8))))))))); } } /** * For-comprehension with one List. */ public static class For1List { private final List ts1; private For1List(List ts1) { this.ts1 = ts1; } /** * Yields a result for elements of the cross product of the underlying List. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(Function f) { Objects.requireNonNull(f, "f is null"); return ts1.map(f); } /** * A shortcut for {@code yield(Function.identity())}. * * @return an {@code Iterator} of mapped results */ public List yield() { return yield(Function.identity()); } } /** * For-comprehension with two Lists. */ public static class For2List { private final List ts1; private final List ts2; private For2List(List ts1, List ts2) { this.ts1 = ts1; this.ts2 = ts2; } /** * Yields a result for elements of the cross product of the underlying Lists. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(BiFunction f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.map(t2 -> f.apply(t1, t2))); } } /** * For-comprehension with three Lists. */ public static class For3List { private final List ts1; private final List ts2; private final List ts3; private For3List(List ts1, List ts2, List ts3) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; } /** * Yields a result for elements of the cross product of the underlying Lists. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(Function3 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.map(t3 -> f.apply(t1, t2, t3)))); } } /** * For-comprehension with 4 Lists. */ public static class For4List { private final List ts1; private final List ts2; private final List ts3; private final List ts4; private For4List(List ts1, List ts2, List ts3, List ts4) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; } /** * Yields a result for elements of the cross product of the underlying Lists. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(Function4 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.map(t4 -> f.apply(t1, t2, t3, t4))))); } } /** * For-comprehension with 5 Lists. */ public static class For5List { private final List ts1; private final List ts2; private final List ts3; private final List ts4; private final List ts5; private For5List(List ts1, List ts2, List ts3, List ts4, List ts5) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; } /** * Yields a result for elements of the cross product of the underlying Lists. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(Function5 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.map(t5 -> f.apply(t1, t2, t3, t4, t5)))))); } } /** * For-comprehension with 6 Lists. */ public static class For6List { private final List ts1; private final List ts2; private final List ts3; private final List ts4; private final List ts5; private final List ts6; private For6List(List ts1, List ts2, List ts3, List ts4, List ts5, List ts6) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; } /** * Yields a result for elements of the cross product of the underlying Lists. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(Function6 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.map(t6 -> f.apply(t1, t2, t3, t4, t5, t6))))))); } } /** * For-comprehension with 7 Lists. */ public static class For7List { private final List ts1; private final List ts2; private final List ts3; private final List ts4; private final List ts5; private final List ts6; private final List ts7; private For7List(List ts1, List ts2, List ts3, List ts4, List ts5, List ts6, List ts7) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; } /** * Yields a result for elements of the cross product of the underlying Lists. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(Function7 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.map(t7 -> f.apply(t1, t2, t3, t4, t5, t6, t7)))))))); } } /** * For-comprehension with 8 Lists. */ public static class For8List { private final List ts1; private final List ts2; private final List ts3; private final List ts4; private final List ts5; private final List ts6; private final List ts7; private final List ts8; private For8List(List ts1, List ts2, List ts3, List ts4, List ts5, List ts6, List ts7, List ts8) { this.ts1 = ts1; this.ts2 = ts2; this.ts3 = ts3; this.ts4 = ts4; this.ts5 = ts5; this.ts6 = ts6; this.ts7 = ts7; this.ts8 = ts8; } /** * Yields a result for elements of the cross product of the underlying Lists. * * @param f a function that maps an element of the cross product to a result * @param type of the resulting {@code List} elements * @return an {@code List} of mapped results */ public List yield(Function8 f) { Objects.requireNonNull(f, "f is null"); return ts1.flatMap(t1 -> ts2.flatMap(t2 -> ts3.flatMap(t3 -> ts4.flatMap(t4 -> ts5.flatMap(t5 -> ts6.flatMap(t6 -> ts7.flatMap(t7 -> ts8.map(t8 -> f.apply(t1, t2, t3, t4, t5, t6, t7, t8))))))))); } } // // Structural Pattern Matching // // -- static Match API /** * Entry point of the match API. * * @param value a value to be matched * @param type of the value * @return a new {@code Match} instance */ @GwtIncompatible public static Match Match(T value) { return new Match<>(value); } // -- static Case API // - Pattern0 @GwtIncompatible public static Case Case(Pattern0 pattern, Function f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case0<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern0 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case0<>(pattern, ignored -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern0 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case0<>(pattern, ignored -> retVal); } // - Pattern1 @GwtIncompatible public static Case Case(Pattern1 pattern, Function f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case1<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern1 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case1<>(pattern, _1 -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern1 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case1<>(pattern, _1 -> retVal); } // - Pattern2 @GwtIncompatible public static Case Case(Pattern2 pattern, BiFunction f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case2<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern2 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case2<>(pattern, (_1, _2) -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern2 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case2<>(pattern, (_1, _2) -> retVal); } // - Pattern3 @GwtIncompatible public static Case Case(Pattern3 pattern, Function3 f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case3<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern3 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case3<>(pattern, (_1, _2, _3) -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern3 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case3<>(pattern, (_1, _2, _3) -> retVal); } // - Pattern4 @GwtIncompatible public static Case Case(Pattern4 pattern, Function4 f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case4<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern4 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case4<>(pattern, (_1, _2, _3, _4) -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern4 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case4<>(pattern, (_1, _2, _3, _4) -> retVal); } // - Pattern5 @GwtIncompatible public static Case Case(Pattern5 pattern, Function5 f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case5<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern5 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case5<>(pattern, (_1, _2, _3, _4, _5) -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern5 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case5<>(pattern, (_1, _2, _3, _4, _5) -> retVal); } // - Pattern6 @GwtIncompatible public static Case Case(Pattern6 pattern, Function6 f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case6<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern6 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case6<>(pattern, (_1, _2, _3, _4, _5, _6) -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern6 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case6<>(pattern, (_1, _2, _3, _4, _5, _6) -> retVal); } // - Pattern7 @GwtIncompatible public static Case Case(Pattern7 pattern, Function7 f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case7<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern7 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case7<>(pattern, (_1, _2, _3, _4, _5, _6, _7) -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern7 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case7<>(pattern, (_1, _2, _3, _4, _5, _6, _7) -> retVal); } // - Pattern8 @GwtIncompatible public static Case Case(Pattern8 pattern, Function8 f) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(f, "f is null"); return new Case8<>(pattern, f); } @GwtIncompatible public static Case Case(Pattern8 pattern, Supplier supplier) { Objects.requireNonNull(pattern, "pattern is null"); Objects.requireNonNull(supplier, "supplier is null"); return new Case8<>(pattern, (_1, _2, _3, _4, _5, _6, _7, _8) -> supplier.get()); } @GwtIncompatible public static Case Case(Pattern8 pattern, R retVal) { Objects.requireNonNull(pattern, "pattern is null"); return new Case8<>(pattern, (_1, _2, _3, _4, _5, _6, _7, _8) -> retVal); } // PRE-DEFINED PATTERNS // 1) Atomic patterns $(), $(value), $(predicate) /** * Wildcard pattern, matches any value. * * @param injected type of the underlying value * @return a new {@code Pattern0} instance */ @GwtIncompatible public static Pattern0 $() { return Pattern0.any(); } /** * Value pattern, checks for equality. * * @param type of the prototype * @param prototype the value that should be equal to the underlying object * @return a new {@code Pattern0} instance */ @GwtIncompatible public static Pattern0 $(T prototype) { return new Pattern0() { private static final long serialVersionUID = 1L; @Override public T apply(T obj) { return obj; } @Override public boolean isDefinedAt(T obj) { return Objects.equals(obj, prototype); } }; } /** * Guard pattern, checks if a predicate is satisfied. *

* This method is intended to be used with lambdas and method references, for example: * *


     * String evenOrOdd(int num) {
     *     return Match(num).of(
     *             Case($(i -> i % 2 == 0), "even"),
     *             Case($(this::isOdd), "odd")
     *     );
     * }
     *
     * boolean isOdd(int i) {
     *     return i % 2 == 1;
     * }
     * 
* * It is also valid to pass {@code Predicate} instances: * *

     * Predicate<Integer> isOdd = i -> i % 2 == 1;
     *
     * Match(num).of(
     *         Case($(i -> i % 2 == 0), "even"),
     *         Case($(isOdd), "odd")
     * );
     * 
* * Note: Please take care when matching {@code Predicate} instances. In general, * function equality * is an undecidable problem in computer science. In Vavr we are only able to check, * if two functions are the same instance. *

* However, this code will fail: * *


     * Predicate<Integer> p = i -> true;
     * Match(p).of(
     *     Case($(p), 1) // WRONG! It calls $(Predicate)
     * );
     * 
* * Instead we have to use {@link Predicates#is(Object)}: * *

     * Predicate<Integer> p = i -> true;
     * Match(p).of(
     *     Case($(is(p)), 1) // CORRECT! It calls $(T)
     * );
     * 
* * @param type of the prototype * @param predicate the predicate that tests a given value * @return a new {@code Pattern0} instance */ @GwtIncompatible public static Pattern0 $(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return new Pattern0() { private static final long serialVersionUID = 1L; @Override public T apply(T obj) { return obj; } @Override public boolean isDefinedAt(T obj) { return predicate.test(obj); } }; } /** * Scala-like structural pattern matching for Java. Instances are obtained via {@link API#Match(Object)}. * @param type of the object that is matched */ @GwtIncompatible public static final class Match { private final T value; private Match(T value) { this.value = value; } @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final R of(Case... cases) { Objects.requireNonNull(cases, "cases is null"); for (Case _case : cases) { final Case __case = (Case) _case; if (__case.isDefinedAt(value)) { return __case.apply(value); } } throw new MatchError(value); } @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final Option option(Case... cases) { Objects.requireNonNull(cases, "cases is null"); for (Case _case : cases) { final Case __case = (Case) _case; if (__case.isDefinedAt(value)) { return Option.some(__case.apply(value)); } } return Option.none(); } // -- CASES public interface Case extends PartialFunction { /** * The serial version uid. */ long serialVersionUID = 1L; } public static final class Case0 implements Case { private static final long serialVersionUID = 1L; private final Pattern0 pattern; private final Function f; private Case0(Pattern0 pattern, Function f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return f.apply(pattern.apply(obj)); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case1 implements Case { private static final long serialVersionUID = 1L; private final Pattern1 pattern; private final Function f; private Case1(Pattern1 pattern, Function f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return f.apply(pattern.apply(obj)); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case2 implements Case { private static final long serialVersionUID = 1L; private final Pattern2 pattern; private final BiFunction f; private Case2(Pattern2 pattern, BiFunction f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return pattern.apply(obj).apply(f); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case3 implements Case { private static final long serialVersionUID = 1L; private final Pattern3 pattern; private final Function3 f; private Case3(Pattern3 pattern, Function3 f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return pattern.apply(obj).apply(f); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case4 implements Case { private static final long serialVersionUID = 1L; private final Pattern4 pattern; private final Function4 f; private Case4(Pattern4 pattern, Function4 f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return pattern.apply(obj).apply(f); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case5 implements Case { private static final long serialVersionUID = 1L; private final Pattern5 pattern; private final Function5 f; private Case5(Pattern5 pattern, Function5 f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return pattern.apply(obj).apply(f); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case6 implements Case { private static final long serialVersionUID = 1L; private final Pattern6 pattern; private final Function6 f; private Case6(Pattern6 pattern, Function6 f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return pattern.apply(obj).apply(f); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case7 implements Case { private static final long serialVersionUID = 1L; private final Pattern7 pattern; private final Function7 f; private Case7(Pattern7 pattern, Function7 f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return pattern.apply(obj).apply(f); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } public static final class Case8 implements Case { private static final long serialVersionUID = 1L; private final Pattern8 pattern; private final Function8 f; private Case8(Pattern8 pattern, Function8 f) { this.pattern = pattern; this.f = f; } @Override public R apply(T obj) { return pattern.apply(obj).apply(f); } @Override public boolean isDefinedAt(T obj) { return pattern.isDefinedAt(obj); } } // -- PATTERNS /** * A Pattern is a partial {@link Function} in the sense that a function applications returns an * optional result of type {@code Option}. * * @param Class type that is matched by this pattern * @param Type of the single or composite part this pattern decomposes */ // javac needs fqn's here public interface Pattern extends PartialFunction { } // These can't be @FunctionalInterfaces because of ambiguities. // For benchmarks lambda vs. abstract class see http://www.oracle.com/technetwork/java/jvmls2013kuksen-2014088.pdf public static abstract class Pattern0 implements Pattern { private static final long serialVersionUID = 1L; private static final Pattern0 ANY = new Pattern0() { private static final long serialVersionUID = 1L; @Override public Object apply(Object obj) { return obj; } @Override public boolean isDefinedAt(Object obj) { return true; } }; @SuppressWarnings("unchecked") public static Pattern0 any() { return (Pattern0) ANY; } // DEV-NOTE: We need the lower bound `Class` instead of the more appropriate `Class` // because it allows us to create patterns for generic types, which would otherwise not be // possible: `Pattern0> p = Pattern0.of(Some.class);` public static Pattern0 of(Class type) { return new Pattern0() { private static final long serialVersionUID = 1L; @Override public T apply(T obj) { return obj; } @Override public boolean isDefinedAt(T obj) { return obj != null && type.isAssignableFrom(obj.getClass()); } }; } } public static abstract class Pattern1 implements Pattern { private static final long serialVersionUID = 1L; public static Pattern1 of(Class type, Pattern p1, Function> unapply) { return new Pattern1() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public T1 apply(T obj) { return (T1) unapply.apply(obj)._1; } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple1 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1); } } }; } } public static abstract class Pattern2 implements Pattern> { private static final long serialVersionUID = 1L; public static Pattern2 of(Class type, Pattern p1, Pattern p2, Function> unapply) { return new Pattern2() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Tuple2 apply(T obj) { return (Tuple2) unapply.apply(obj); } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple2 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2); } } }; } } public static abstract class Pattern3 implements Pattern> { private static final long serialVersionUID = 1L; public static Pattern3 of(Class type, Pattern p1, Pattern p2, Pattern p3, Function> unapply) { return new Pattern3() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Tuple3 apply(T obj) { return (Tuple3) unapply.apply(obj); } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple3 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3); } } }; } } public static abstract class Pattern4 implements Pattern> { private static final long serialVersionUID = 1L; public static Pattern4 of(Class type, Pattern p1, Pattern p2, Pattern p3, Pattern p4, Function> unapply) { return new Pattern4() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Tuple4 apply(T obj) { return (Tuple4) unapply.apply(obj); } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple4 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3) && ((Pattern) p4).isDefinedAt(u._4); } } }; } } public static abstract class Pattern5 implements Pattern> { private static final long serialVersionUID = 1L; public static Pattern5 of(Class type, Pattern p1, Pattern p2, Pattern p3, Pattern p4, Pattern p5, Function> unapply) { return new Pattern5() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Tuple5 apply(T obj) { return (Tuple5) unapply.apply(obj); } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple5 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3) && ((Pattern) p4).isDefinedAt(u._4) && ((Pattern) p5).isDefinedAt(u._5); } } }; } } public static abstract class Pattern6 implements Pattern> { private static final long serialVersionUID = 1L; public static Pattern6 of(Class type, Pattern p1, Pattern p2, Pattern p3, Pattern p4, Pattern p5, Pattern p6, Function> unapply) { return new Pattern6() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Tuple6 apply(T obj) { return (Tuple6) unapply.apply(obj); } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple6 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3) && ((Pattern) p4).isDefinedAt(u._4) && ((Pattern) p5).isDefinedAt(u._5) && ((Pattern) p6).isDefinedAt(u._6); } } }; } } public static abstract class Pattern7 implements Pattern> { private static final long serialVersionUID = 1L; public static Pattern7 of(Class type, Pattern p1, Pattern p2, Pattern p3, Pattern p4, Pattern p5, Pattern p6, Pattern p7, Function> unapply) { return new Pattern7() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Tuple7 apply(T obj) { return (Tuple7) unapply.apply(obj); } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple7 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3) && ((Pattern) p4).isDefinedAt(u._4) && ((Pattern) p5).isDefinedAt(u._5) && ((Pattern) p6).isDefinedAt(u._6) && ((Pattern) p7).isDefinedAt(u._7); } } }; } } public static abstract class Pattern8 implements Pattern> { private static final long serialVersionUID = 1L; public static Pattern8 of(Class type, Pattern p1, Pattern p2, Pattern p3, Pattern p4, Pattern p5, Pattern p6, Pattern p7, Pattern p8, Function> unapply) { return new Pattern8() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Tuple8 apply(T obj) { return (Tuple8) unapply.apply(obj); } @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { if (obj == null || !type.isAssignableFrom(obj.getClass())) { return false; } else { final Tuple8 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3) && ((Pattern) p4).isDefinedAt(u._4) && ((Pattern) p5).isDefinedAt(u._5) && ((Pattern) p6).isDefinedAt(u._6) && ((Pattern) p7).isDefinedAt(u._7) && ((Pattern) p8).isDefinedAt(u._8); } } }; } } } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction0.java000066400000000000000000000232331342074374400243060ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction0Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.Objects; import java.util.function.Function; import java.util.function.Supplier; /** * Represents a function with no arguments. * * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction0 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction0 constant(R value) { return () -> value; } /** * Creates a {@code CheckedFunction0} based on * * * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @return a {@code CheckedFunction0} */ static CheckedFunction0 of(CheckedFunction0 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function0> lift(CheckedFunction0 partialFunction) { return () -> Try.of(partialFunction::apply).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function0> liftTry(CheckedFunction0 partialFunction) { return () -> Try.of(partialFunction::apply); } /** * Narrows the given {@code CheckedFunction0} to {@code CheckedFunction0} * * @param f A {@code CheckedFunction0} * @param return type * @return the given {@code f} instance as narrowed type {@code CheckedFunction0} */ @SuppressWarnings("unchecked") static CheckedFunction0 narrow(CheckedFunction0 f) { return (CheckedFunction0) f; } /** * Applies this function to no arguments and returns the result. * * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply() throws Throwable; /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 0; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default CheckedFunction0 curried() { return this; } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1 tupled() { return t -> apply(); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction0 reversed() { return this; } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction0 memoized() { if (isMemoized()) { return this; } else { final Lazy lazy = Lazy.of(() -> { try { return apply(); } catch (Throwable x) { throw new RuntimeException(x); } }); return (CheckedFunction0 & Memoized) () -> { try { return lazy.get(); } catch(RuntimeException x) { throw x.getCause(); } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction0 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function0 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return () -> { try { return this.apply(); } catch (Throwable throwable) { final Supplier func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.get(); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function0 that throws a {@code Throwable}. */ default Function0 unchecked() { return () -> { try { return apply(); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction0 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction0 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return () -> after.apply(apply()); } } interface CheckedFunction0Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction1.java000066400000000000000000000260011342074374400243030ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction1Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with one argument. * * @param argument 1 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction1 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction1 constant(R value) { return (t1) -> value; } /** * Creates a {@code CheckedFunction1} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @return a {@code CheckedFunction1} */ static CheckedFunction1 of(CheckedFunction1 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function1> lift(CheckedFunction1 partialFunction) { return t1 -> Try.of(() -> partialFunction.apply(t1)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function1> liftTry(CheckedFunction1 partialFunction) { return t1 -> Try.of(() -> partialFunction.apply(t1)); } /** * Narrows the given {@code CheckedFunction1} to {@code CheckedFunction1} * * @param f A {@code CheckedFunction1} * @param return type * @param 1st argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction1} */ @SuppressWarnings("unchecked") static CheckedFunction1 narrow(CheckedFunction1 f) { return (CheckedFunction1) f; } /** * Returns the identity CheckedFunction1, i.e. the function that returns its input. * * @param argument type (and return type) of the identity function * @return the identity CheckedFunction1 */ static CheckedFunction1 identity() { return t -> t; } /** * Applies this function to one argument and returns the result. * * @param t1 argument 1 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1) throws Throwable; /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 1; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default CheckedFunction1 curried() { return this; } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction1 reversed() { return this; } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction1 memoized() { if (isMemoized()) { return this; } else { final Map cache = new HashMap<>(); return (CheckedFunction1 & Memoized) (t1) -> { synchronized (cache) { if (cache.containsKey(t1)) { return cache.get(t1); } else { final R value = apply(t1); cache.put(t1, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction1 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function1 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1) -> { try { return this.apply(t1); } catch (Throwable throwable) { final Function func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function1 that throws a {@code Throwable}. */ default Function1 unchecked() { return (t1) -> { try { return apply(t1); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction1 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction1 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1) -> after.apply(apply(t1)); } /** * Returns a composed function that first applies the {@linkplain CheckedFunction1} {@code before} the * given argument and then applies this CheckedFunction1 to the result. * * @param argument type of before * @param before the function applied before this * @return a function composed of before and this * @throws NullPointerException if before is null */ default CheckedFunction1 compose(CheckedFunction1 before) { Objects.requireNonNull(before, "before is null"); return v -> apply(before.apply(v)); } } interface CheckedFunction1Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction2.java000066400000000000000000000260201342074374400243050ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction2Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; /** * Represents a function with two arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction2 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction2 constant(R value) { return (t1, t2) -> value; } /** * Creates a {@code CheckedFunction2} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @return a {@code CheckedFunction2} */ static CheckedFunction2 of(CheckedFunction2 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function2> lift(CheckedFunction2 partialFunction) { return (t1, t2) -> Try.of(() -> partialFunction.apply(t1, t2)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function2> liftTry(CheckedFunction2 partialFunction) { return (t1, t2) -> Try.of(() -> partialFunction.apply(t1, t2)); } /** * Narrows the given {@code CheckedFunction2} to {@code CheckedFunction2} * * @param f A {@code CheckedFunction2} * @param return type * @param 1st argument * @param 2nd argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction2} */ @SuppressWarnings("unchecked") static CheckedFunction2 narrow(CheckedFunction2 f) { return (CheckedFunction2) f; } /** * Applies this function to two arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1, T2 t2) throws Throwable; /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default CheckedFunction1 apply(T1 t1) { return (T2 t2) -> apply(t1, t2); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 2; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1> curried() { return t1 -> t2 -> apply(t1, t2); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1, t._2); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction2 reversed() { return (t2, t1) -> apply(t1, t2); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction2 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (CheckedFunction2 & Memoized) (t1, t2) -> { final Tuple2 key = Tuple.of(t1, t2); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction2 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function2 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1, t2) -> { try { return this.apply(t1, t2); } catch (Throwable throwable) { final BiFunction func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1, t2); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function2 that throws a {@code Throwable}. */ default Function2 unchecked() { return (t1, t2) -> { try { return apply(t1, t2); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction2 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction2 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1, t2) -> after.apply(apply(t1, t2)); } } interface CheckedFunction2Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction3.java000066400000000000000000000275011342074374400243130ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction3Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with three arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction3 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction3 constant(R value) { return (t1, t2, t3) -> value; } /** * Creates a {@code CheckedFunction3} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return a {@code CheckedFunction3} */ static CheckedFunction3 of(CheckedFunction3 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function3> lift(CheckedFunction3 partialFunction) { return (t1, t2, t3) -> Try.of(() -> partialFunction.apply(t1, t2, t3)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function3> liftTry(CheckedFunction3 partialFunction) { return (t1, t2, t3) -> Try.of(() -> partialFunction.apply(t1, t2, t3)); } /** * Narrows the given {@code CheckedFunction3} to {@code CheckedFunction3} * * @param f A {@code CheckedFunction3} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction3} */ @SuppressWarnings("unchecked") static CheckedFunction3 narrow(CheckedFunction3 f) { return (CheckedFunction3) f; } /** * Applies this function to three arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1, T2 t2, T3 t3) throws Throwable; /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default CheckedFunction2 apply(T1 t1) { return (T2 t2, T3 t3) -> apply(t1, t2, t3); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default CheckedFunction1 apply(T1 t1, T2 t2) { return (T3 t3) -> apply(t1, t2, t3); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 3; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>> curried() { return t1 -> t2 -> t3 -> apply(t1, t2, t3); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1, t._2, t._3); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction3 reversed() { return (t3, t2, t1) -> apply(t1, t2, t3); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction3 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (CheckedFunction3 & Memoized) (t1, t2, t3) -> { final Tuple3 key = Tuple.of(t1, t2, t3); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction3 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function3 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1, t2, t3) -> { try { return this.apply(t1, t2, t3); } catch (Throwable throwable) { final Function3 func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1, t2, t3); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function3 that throws a {@code Throwable}. */ default Function3 unchecked() { return (t1, t2, t3) -> { try { return apply(t1, t2, t3); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction3 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction3 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3) -> after.apply(apply(t1, t2, t3)); } } interface CheckedFunction3Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction4.java000066400000000000000000000313061342074374400243120ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction4Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 4 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction4 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction4 constant(R value) { return (t1, t2, t3, t4) -> value; } /** * Creates a {@code CheckedFunction4} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return a {@code CheckedFunction4} */ static CheckedFunction4 of(CheckedFunction4 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function4> lift(CheckedFunction4 partialFunction) { return (t1, t2, t3, t4) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function4> liftTry(CheckedFunction4 partialFunction) { return (t1, t2, t3, t4) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4)); } /** * Narrows the given {@code CheckedFunction4} to {@code CheckedFunction4} * * @param f A {@code CheckedFunction4} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction4} */ @SuppressWarnings("unchecked") static CheckedFunction4 narrow(CheckedFunction4 f) { return (CheckedFunction4) f; } /** * Applies this function to 4 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1, T2 t2, T3 t3, T4 t4) throws Throwable; /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default CheckedFunction3 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4) -> apply(t1, t2, t3, t4); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default CheckedFunction2 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4) -> apply(t1, t2, t3, t4); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default CheckedFunction1 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4) -> apply(t1, t2, t3, t4); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 4; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>> curried() { return t1 -> t2 -> t3 -> t4 -> apply(t1, t2, t3, t4); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction4 reversed() { return (t4, t3, t2, t1) -> apply(t1, t2, t3, t4); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction4 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (CheckedFunction4 & Memoized) (t1, t2, t3, t4) -> { final Tuple4 key = Tuple.of(t1, t2, t3, t4); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction4 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function4 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1, t2, t3, t4) -> { try { return this.apply(t1, t2, t3, t4); } catch (Throwable throwable) { final Function4 func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1, t2, t3, t4); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function4 that throws a {@code Throwable}. */ default Function4 unchecked() { return (t1, t2, t3, t4) -> { try { return apply(t1, t2, t3, t4); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction4 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction4 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4) -> after.apply(apply(t1, t2, t3, t4)); } } interface CheckedFunction4Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction5.java000066400000000000000000000332051342074374400243130ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction5Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 5 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction5 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction5 constant(R value) { return (t1, t2, t3, t4, t5) -> value; } /** * Creates a {@code CheckedFunction5} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return a {@code CheckedFunction5} */ static CheckedFunction5 of(CheckedFunction5 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function5> lift(CheckedFunction5 partialFunction) { return (t1, t2, t3, t4, t5) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function5> liftTry(CheckedFunction5 partialFunction) { return (t1, t2, t3, t4, t5) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5)); } /** * Narrows the given {@code CheckedFunction5} to {@code CheckedFunction5} * * @param f A {@code CheckedFunction5} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction5} */ @SuppressWarnings("unchecked") static CheckedFunction5 narrow(CheckedFunction5 f) { return (CheckedFunction5) f; } /** * Applies this function to 5 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) throws Throwable; /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default CheckedFunction4 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default CheckedFunction3 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default CheckedFunction2 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default CheckedFunction1 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 5; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> apply(t1, t2, t3, t4, t5); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction5 reversed() { return (t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction5 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (CheckedFunction5 & Memoized) (t1, t2, t3, t4, t5) -> { final Tuple5 key = Tuple.of(t1, t2, t3, t4, t5); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction5 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function5 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1, t2, t3, t4, t5) -> { try { return this.apply(t1, t2, t3, t4, t5); } catch (Throwable throwable) { final Function5 func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1, t2, t3, t4, t5); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function5 that throws a {@code Throwable}. */ default Function5 unchecked() { return (t1, t2, t3, t4, t5) -> { try { return apply(t1, t2, t3, t4, t5); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction5 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction5 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5) -> after.apply(apply(t1, t2, t3, t4, t5)); } } interface CheckedFunction5Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction6.java000066400000000000000000000351721342074374400243210ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction6Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 6 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param argument 6 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction6 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param generic parameter type 6 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction6 constant(R value) { return (t1, t2, t3, t4, t5, t6) -> value; } /** * Creates a {@code CheckedFunction6} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return a {@code CheckedFunction6} */ static CheckedFunction6 of(CheckedFunction6 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function6> lift(CheckedFunction6 partialFunction) { return (t1, t2, t3, t4, t5, t6) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function6> liftTry(CheckedFunction6 partialFunction) { return (t1, t2, t3, t4, t5, t6) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6)); } /** * Narrows the given {@code CheckedFunction6} to {@code CheckedFunction6} * * @param f A {@code CheckedFunction6} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction6} */ @SuppressWarnings("unchecked") static CheckedFunction6 narrow(CheckedFunction6 f) { return (CheckedFunction6) f; } /** * Applies this function to 6 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) throws Throwable; /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default CheckedFunction5 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default CheckedFunction4 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default CheckedFunction3 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default CheckedFunction2 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to 5 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return a partial application of this function */ default CheckedFunction1 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return (T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 6; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> t6 -> apply(t1, t2, t3, t4, t5, t6); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5, t._6); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction6 reversed() { return (t6, t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5, t6); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction6 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (CheckedFunction6 & Memoized) (t1, t2, t3, t4, t5, t6) -> { final Tuple6 key = Tuple.of(t1, t2, t3, t4, t5, t6); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction6 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function6 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1, t2, t3, t4, t5, t6) -> { try { return this.apply(t1, t2, t3, t4, t5, t6); } catch (Throwable throwable) { final Function6 func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1, t2, t3, t4, t5, t6); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function6 that throws a {@code Throwable}. */ default Function6 unchecked() { return (t1, t2, t3, t4, t5, t6) -> { try { return apply(t1, t2, t3, t4, t5, t6); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction6 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction6 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5, t6) -> after.apply(apply(t1, t2, t3, t4, t5, t6)); } } interface CheckedFunction6Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction7.java000066400000000000000000000372451342074374400243250ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction7Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 7 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param argument 6 of the function * @param argument 7 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction7 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param generic parameter type 6 of the resulting function * @param generic parameter type 7 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction7 constant(R value) { return (t1, t2, t3, t4, t5, t6, t7) -> value; } /** * Creates a {@code CheckedFunction7} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return a {@code CheckedFunction7} */ static CheckedFunction7 of(CheckedFunction7 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function7> lift(CheckedFunction7 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function7> liftTry(CheckedFunction7 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7)); } /** * Narrows the given {@code CheckedFunction7} to {@code CheckedFunction7} * * @param f A {@code CheckedFunction7} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction7} */ @SuppressWarnings("unchecked") static CheckedFunction7 narrow(CheckedFunction7 f) { return (CheckedFunction7) f; } /** * Applies this function to 7 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @param t7 argument 7 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) throws Throwable; /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default CheckedFunction6 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default CheckedFunction5 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default CheckedFunction4 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default CheckedFunction3 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to 5 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return a partial application of this function */ default CheckedFunction2 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return (T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to 6 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @return a partial application of this function */ default CheckedFunction1 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { return (T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 7; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> t6 -> t7 -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5, t._6, t._7); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction7 reversed() { return (t7, t6, t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction7 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (CheckedFunction7 & Memoized) (t1, t2, t3, t4, t5, t6, t7) -> { final Tuple7 key = Tuple.of(t1, t2, t3, t4, t5, t6, t7); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction7 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function7 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1, t2, t3, t4, t5, t6, t7) -> { try { return this.apply(t1, t2, t3, t4, t5, t6, t7); } catch (Throwable throwable) { final Function7 func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1, t2, t3, t4, t5, t6, t7); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function7 that throws a {@code Throwable}. */ default Function7 unchecked() { return (t1, t2, t3, t4, t5, t6, t7) -> { try { return apply(t1, t2, t3, t4, t5, t6, t7); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction7 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction7 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5, t6, t7) -> after.apply(apply(t1, t2, t3, t4, t5, t6, t7)); } } interface CheckedFunction7Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/CheckedFunction8.java000066400000000000000000000414061342074374400243200ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.CheckedFunction8Module.sneakyThrow; import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 8 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param argument 6 of the function * @param argument 7 of the function * @param argument 8 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface CheckedFunction8 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param generic parameter type 6 of the resulting function * @param generic parameter type 7 of the resulting function * @param generic parameter type 8 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static CheckedFunction8 constant(R value) { return (t1, t2, t3, t4, t5, t6, t7, t8) -> value; } /** * Creates a {@code CheckedFunction8} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return a {@code CheckedFunction8} */ static CheckedFunction8 of(CheckedFunction8 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function8> lift(CheckedFunction8 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7, t8) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7, t8)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function8> liftTry(CheckedFunction8 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7, t8) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7, t8)); } /** * Narrows the given {@code CheckedFunction8} to {@code CheckedFunction8} * * @param f A {@code CheckedFunction8} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return the given {@code f} instance as narrowed type {@code CheckedFunction8} */ @SuppressWarnings("unchecked") static CheckedFunction8 narrow(CheckedFunction8 f) { return (CheckedFunction8) f; } /** * Applies this function to 8 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @param t7 argument 7 * @param t8 argument 8 * @return the result of function application * @throws Throwable if something goes wrong applying this function to the given arguments */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) throws Throwable; /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default CheckedFunction7 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default CheckedFunction6 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default CheckedFunction5 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default CheckedFunction4 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 5 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return a partial application of this function */ default CheckedFunction3 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return (T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 6 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @return a partial application of this function */ default CheckedFunction2 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { return (T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 7 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @param t7 argument 7 * @return a partial application of this function */ default CheckedFunction1 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { return (T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 8; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> t6 -> t7 -> t8 -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default CheckedFunction1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5, t._6, t._7, t._8); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default CheckedFunction8 reversed() { return (t8, t7, t6, t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default CheckedFunction8 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (CheckedFunction8 & Memoized) (t1, t2, t3, t4, t5, t6, t7, t8) -> { final Tuple8 key = Tuple.of(t1, t2, t3, t4, t5, t6, t7, t8); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Return a composed function that first applies this CheckedFunction8 to the given arguments and in case of throwable * try to get value from {@code recover} function with same arguments and throwable information. * * @param recover the function applied in case of throwable * @return a function composed of this and recover * @throws NullPointerException if recover is null */ default Function8 recover(Function> recover) { Objects.requireNonNull(recover, "recover is null"); return (t1, t2, t3, t4, t5, t6, t7, t8) -> { try { return this.apply(t1, t2, t3, t4, t5, t6, t7, t8); } catch (Throwable throwable) { final Function8 func = recover.apply(throwable); Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage()); return func.apply(t1, t2, t3, t4, t5, t6, t7, t8); } }; } /** * Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function. * * @return a new Function8 that throws a {@code Throwable}. */ default Function8 unchecked() { return (t1, t2, t3, t4, t5, t6, t7, t8) -> { try { return apply(t1, t2, t3, t4, t5, t6, t7, t8); } catch(Throwable t) { return sneakyThrow(t); } }; } /** * Returns a composed function that first applies this CheckedFunction8 to the given argument and then applies * {@linkplain CheckedFunction1} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default CheckedFunction8 andThen(CheckedFunction1 after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5, t6, t7, t8) -> after.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8)); } } interface CheckedFunction8Module { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function0.java000066400000000000000000000170461342074374400230440ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.Objects; import java.util.function.Function; import java.util.function.Supplier; /** * Represents a function with no arguments. * * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function0 extends Serializable, Supplier { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function0 constant(R value) { return () -> value; } /** * Creates a {@code Function0} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @return a {@code Function0} */ static Function0 of(Function0 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function0> lift(Supplier partialFunction) { return () -> Try.of(partialFunction::get).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function0> liftTry(Supplier partialFunction) { return () -> Try.of(partialFunction::get); } /** * Narrows the given {@code Function0} to {@code Function0} * * @param f A {@code Function0} * @param return type * @return the given {@code f} instance as narrowed type {@code Function0} */ @SuppressWarnings("unchecked") static Function0 narrow(Function0 f) { return (Function0) f; } /** * Applies this function to no arguments and returns the result. * * @return the result of function application * */ R apply(); /** * Implementation of {@linkplain java.util.function.Supplier#get()}, just calls {@linkplain #apply()}. * * @return the result of {@code apply()} */ @Override default R get() { return apply(); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 0; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function0 curried() { return this; } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1 tupled() { return t -> apply(); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function0 reversed() { return this; } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function0 memoized() { if (isMemoized()) { return this; } else { return (Function0 & Memoized) Lazy.of(this)::get; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function0 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function0 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return () -> after.apply(apply()); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function1.java000066400000000000000000000241011342074374400230330ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; /** * Represents a function with one argument. * * @param argument 1 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function1 extends Serializable, Function { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function1 constant(R value) { return (t1) -> value; } /** * Creates a {@code Function1} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @return a {@code Function1} */ static Function1 of(Function1 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function1> lift(Function partialFunction) { return t1 -> Try.of(() -> partialFunction.apply(t1)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function1> liftTry(Function partialFunction) { return t1 -> Try.of(() -> partialFunction.apply(t1)); } /** * Narrows the given {@code Function1} to {@code Function1} * * @param f A {@code Function1} * @param return type * @param 1st argument * @return the given {@code f} instance as narrowed type {@code Function1} */ @SuppressWarnings("unchecked") static Function1 narrow(Function1 f) { return (Function1) f; } /** * Returns the identity Function1, i.e. the function that returns its input. * * @param argument type (and return type) of the identity function * @return the identity Function1 */ static Function1 identity() { return t -> t; } /** * Applies this function to one argument and returns the result. * * @param t1 argument 1 * @return the result of function application * */ R apply(T1 t1); /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 1; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1 curried() { return this; } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function1 reversed() { return this; } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function1 memoized() { if (isMemoized()) { return this; } else { final Map cache = new HashMap<>(); return (Function1 & Memoized) (t1) -> { synchronized (cache) { if (cache.containsKey(t1)) { return cache.get(t1); } else { final R value = apply(t1); cache.put(t1, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Converts this {@code Function1} to a {@link PartialFunction} by adding an {@code isDefinedAt} condition. *

* @param isDefinedAt a predicate that states if an element is in the domain of the returned {@code PartialFunction}. * @return a new {@code PartialFunction} that has the same behavior like this function but is defined only for those elements that make it through the given {@code Predicate} * @throws NullPointerException if {@code isDefinedAt} is null */ default PartialFunction partial(Predicate isDefinedAt) { Objects.requireNonNull(isDefinedAt, "isDefinedAt is null"); final Function1 self = this; return new PartialFunction() { private static final long serialVersionUID = 1L; @Override public boolean isDefinedAt(T1 t1) { return isDefinedAt.test(t1); } @Override public R apply(T1 t1) { return self.apply(t1); } }; } /** * Returns a composed function that first applies this Function1 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function1 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1) -> after.apply(apply(t1)); } /** * Returns a composed function that first applies the {@linkplain Function} {@code before} the * given argument and then applies this Function1 to the result. * * @param argument type of before * @param before the function applied before this * @return a function composed of before and this * @throws NullPointerException if before is null */ default Function1 compose(Function before) { Objects.requireNonNull(before, "before is null"); return v -> apply(before.apply(v)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function2.java000066400000000000000000000220001342074374400230300ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; /** * Represents a function with two arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function2 extends Serializable, BiFunction { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function2 constant(R value) { return (t1, t2) -> value; } /** * Creates a {@code Function2} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @return a {@code Function2} */ static Function2 of(Function2 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function2> lift(BiFunction partialFunction) { return (t1, t2) -> Try.of(() -> partialFunction.apply(t1, t2)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function2> liftTry(BiFunction partialFunction) { return (t1, t2) -> Try.of(() -> partialFunction.apply(t1, t2)); } /** * Narrows the given {@code Function2} to {@code Function2} * * @param f A {@code Function2} * @param return type * @param 1st argument * @param 2nd argument * @return the given {@code f} instance as narrowed type {@code Function2} */ @SuppressWarnings("unchecked") static Function2 narrow(Function2 f) { return (Function2) f; } /** * Applies this function to two arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @return the result of function application * */ R apply(T1 t1, T2 t2); /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default Function1 apply(T1 t1) { return (T2 t2) -> apply(t1, t2); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 2; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1> curried() { return t1 -> t2 -> apply(t1, t2); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1, t._2); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function2 reversed() { return (t2, t1) -> apply(t1, t2); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function2 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (Function2 & Memoized) (t1, t2) -> { final Tuple2 key = Tuple.of(t1, t2); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function2 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function2 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1, t2) -> after.apply(apply(t1, t2)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function3.java000066400000000000000000000233371342074374400230470ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with three arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function3 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function3 constant(R value) { return (t1, t2, t3) -> value; } /** * Creates a {@code Function3} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return a {@code Function3} */ static Function3 of(Function3 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function3> lift(Function3 partialFunction) { return (t1, t2, t3) -> Try.of(() -> partialFunction.apply(t1, t2, t3)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function3> liftTry(Function3 partialFunction) { return (t1, t2, t3) -> Try.of(() -> partialFunction.apply(t1, t2, t3)); } /** * Narrows the given {@code Function3} to {@code Function3} * * @param f A {@code Function3} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @return the given {@code f} instance as narrowed type {@code Function3} */ @SuppressWarnings("unchecked") static Function3 narrow(Function3 f) { return (Function3) f; } /** * Applies this function to three arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return the result of function application * */ R apply(T1 t1, T2 t2, T3 t3); /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default Function2 apply(T1 t1) { return (T2 t2, T3 t3) -> apply(t1, t2, t3); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default Function1 apply(T1 t1, T2 t2) { return (T3 t3) -> apply(t1, t2, t3); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 3; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>> curried() { return t1 -> t2 -> t3 -> apply(t1, t2, t3); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1, t._2, t._3); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function3 reversed() { return (t3, t2, t1) -> apply(t1, t2, t3); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function3 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (Function3 & Memoized) (t1, t2, t3) -> { final Tuple3 key = Tuple.of(t1, t2, t3); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function3 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function3 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3) -> after.apply(apply(t1, t2, t3)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function4.java000066400000000000000000000250511342074374400230430ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 4 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function4 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function4 constant(R value) { return (t1, t2, t3, t4) -> value; } /** * Creates a {@code Function4} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return a {@code Function4} */ static Function4 of(Function4 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function4> lift(Function4 partialFunction) { return (t1, t2, t3, t4) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function4> liftTry(Function4 partialFunction) { return (t1, t2, t3, t4) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4)); } /** * Narrows the given {@code Function4} to {@code Function4} * * @param f A {@code Function4} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @return the given {@code f} instance as narrowed type {@code Function4} */ @SuppressWarnings("unchecked") static Function4 narrow(Function4 f) { return (Function4) f; } /** * Applies this function to 4 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return the result of function application * */ R apply(T1 t1, T2 t2, T3 t3, T4 t4); /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default Function3 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4) -> apply(t1, t2, t3, t4); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default Function2 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4) -> apply(t1, t2, t3, t4); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default Function1 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4) -> apply(t1, t2, t3, t4); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 4; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>> curried() { return t1 -> t2 -> t3 -> t4 -> apply(t1, t2, t3, t4); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function4 reversed() { return (t4, t3, t2, t1) -> apply(t1, t2, t3, t4); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function4 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (Function4 & Memoized) (t1, t2, t3, t4) -> { final Tuple4 key = Tuple.of(t1, t2, t3, t4); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function4 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function4 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4) -> after.apply(apply(t1, t2, t3, t4)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function5.java000066400000000000000000000266551342074374400230570ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 5 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function5 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function5 constant(R value) { return (t1, t2, t3, t4, t5) -> value; } /** * Creates a {@code Function5} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return a {@code Function5} */ static Function5 of(Function5 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function5> lift(Function5 partialFunction) { return (t1, t2, t3, t4, t5) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function5> liftTry(Function5 partialFunction) { return (t1, t2, t3, t4, t5) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5)); } /** * Narrows the given {@code Function5} to {@code Function5} * * @param f A {@code Function5} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @return the given {@code f} instance as narrowed type {@code Function5} */ @SuppressWarnings("unchecked") static Function5 narrow(Function5 f) { return (Function5) f; } /** * Applies this function to 5 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return the result of function application * */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5); /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default Function4 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default Function3 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default Function2 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default Function1 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5) -> apply(t1, t2, t3, t4, t5); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 5; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> apply(t1, t2, t3, t4, t5); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function5 reversed() { return (t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function5 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (Function5 & Memoized) (t1, t2, t3, t4, t5) -> { final Tuple5 key = Tuple.of(t1, t2, t3, t4, t5); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function5 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function5 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5) -> after.apply(apply(t1, t2, t3, t4, t5)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function6.java000066400000000000000000000305471342074374400230530ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 6 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param argument 6 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function6 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param generic parameter type 6 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function6 constant(R value) { return (t1, t2, t3, t4, t5, t6) -> value; } /** * Creates a {@code Function6} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return a {@code Function6} */ static Function6 of(Function6 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function6> lift(Function6 partialFunction) { return (t1, t2, t3, t4, t5, t6) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function6> liftTry(Function6 partialFunction) { return (t1, t2, t3, t4, t5, t6) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6)); } /** * Narrows the given {@code Function6} to {@code Function6} * * @param f A {@code Function6} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @return the given {@code f} instance as narrowed type {@code Function6} */ @SuppressWarnings("unchecked") static Function6 narrow(Function6 f) { return (Function6) f; } /** * Applies this function to 6 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @return the result of function application * */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6); /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default Function5 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default Function4 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default Function3 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default Function2 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5, T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Applies this function partially to 5 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return a partial application of this function */ default Function1 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return (T6 t6) -> apply(t1, t2, t3, t4, t5, t6); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 6; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> t6 -> apply(t1, t2, t3, t4, t5, t6); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5, t._6); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function6 reversed() { return (t6, t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5, t6); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function6 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (Function6 & Memoized) (t1, t2, t3, t4, t5, t6) -> { final Tuple6 key = Tuple.of(t1, t2, t3, t4, t5, t6); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function6 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function6 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5, t6) -> after.apply(apply(t1, t2, t3, t4, t5, t6)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function7.java000066400000000000000000000325271342074374400230540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 7 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param argument 6 of the function * @param argument 7 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function7 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param generic parameter type 6 of the resulting function * @param generic parameter type 7 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function7 constant(R value) { return (t1, t2, t3, t4, t5, t6, t7) -> value; } /** * Creates a {@code Function7} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return a {@code Function7} */ static Function7 of(Function7 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function7> lift(Function7 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function7> liftTry(Function7 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7)); } /** * Narrows the given {@code Function7} to {@code Function7} * * @param f A {@code Function7} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @return the given {@code f} instance as narrowed type {@code Function7} */ @SuppressWarnings("unchecked") static Function7 narrow(Function7 f) { return (Function7) f; } /** * Applies this function to 7 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @param t7 argument 7 * @return the result of function application * */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7); /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default Function6 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default Function5 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default Function4 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default Function3 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5, T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to 5 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return a partial application of this function */ default Function2 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return (T6 t6, T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Applies this function partially to 6 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @return a partial application of this function */ default Function1 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { return (T7 t7) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 7; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> t6 -> t7 -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5, t._6, t._7); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function7 reversed() { return (t7, t6, t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5, t6, t7); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function7 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (Function7 & Memoized) (t1, t2, t3, t4, t5, t6, t7) -> { final Tuple7 key = Tuple.of(t1, t2, t3, t4, t5, t6, t7); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function7 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function7 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5, t6, t7) -> after.apply(apply(t1, t2, t3, t4, t5, t6, t7)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Function8.java000066400000000000000000000345751342074374400230620ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.control.Option; import io.vavr.control.Try; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Represents a function with 8 arguments. * * @param argument 1 of the function * @param argument 2 of the function * @param argument 3 of the function * @param argument 4 of the function * @param argument 5 of the function * @param argument 6 of the function * @param argument 7 of the function * @param argument 8 of the function * @param return type of the function * @author Daniel Dietrich */ @FunctionalInterface public interface Function8 extends Serializable { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Returns a function that always returns the constant * value that you give in parameter. * * @param generic parameter type 1 of the resulting function * @param generic parameter type 2 of the resulting function * @param generic parameter type 3 of the resulting function * @param generic parameter type 4 of the resulting function * @param generic parameter type 5 of the resulting function * @param generic parameter type 6 of the resulting function * @param generic parameter type 7 of the resulting function * @param generic parameter type 8 of the resulting function * @param the result type * @param value the value to be returned * @return a function always returning the given value */ static Function8 constant(R value) { return (t1, t2, t3, t4, t5, t6, t7, t8) -> value; } /** * Creates a {@code Function8} based on *

* * Examples (w.l.o.g. referring to Function1): *
// using a lambda expression
     * Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
     *
     * // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
     * Function1<Integer, Integer> add2 = Function1.of(this::method);
     *
     * // using a lambda reference
     * Function1<Integer, Integer> add3 = Function1.of(add1::apply);
     * 
*

* Caution: Reflection loses type information of lambda references. *

// type of a lambda expression
     * Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
     *
     * // type of a method reference
     * Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
     *
     * // type of a lambda reference
     * Type<?, ?> type3 = add3.getType(); // (Object) -> Object
     * 
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return a {@code Function8} */ static Function8 of(Function8 methodReference) { return methodReference; } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ @SuppressWarnings("RedundantTypeArguments") static Function8> lift(Function8 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7, t8) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7, t8)).toOption(); } /** * Lifts the given {@code partialFunction} into a total function that returns an {@code Try} result. * * @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing) * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)} * if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise. */ static Function8> liftTry(Function8 partialFunction) { return (t1, t2, t3, t4, t5, t6, t7, t8) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4, t5, t6, t7, t8)); } /** * Narrows the given {@code Function8} to {@code Function8} * * @param f A {@code Function8} * @param return type * @param 1st argument * @param 2nd argument * @param 3rd argument * @param 4th argument * @param 5th argument * @param 6th argument * @param 7th argument * @param 8th argument * @return the given {@code f} instance as narrowed type {@code Function8} */ @SuppressWarnings("unchecked") static Function8 narrow(Function8 f) { return (Function8) f; } /** * Applies this function to 8 arguments and returns the result. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @param t7 argument 7 * @param t8 argument 8 * @return the result of function application * */ R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8); /** * Applies this function partially to one argument. * * @param t1 argument 1 * @return a partial application of this function */ default Function7 apply(T1 t1) { return (T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to two arguments. * * @param t1 argument 1 * @param t2 argument 2 * @return a partial application of this function */ default Function6 apply(T1 t1, T2 t2) { return (T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to three arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @return a partial application of this function */ default Function5 apply(T1 t1, T2 t2, T3 t3) { return (T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 4 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @return a partial application of this function */ default Function4 apply(T1 t1, T2 t2, T3 t3, T4 t4) { return (T5 t5, T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 5 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @return a partial application of this function */ default Function3 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return (T6 t6, T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 6 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @return a partial application of this function */ default Function2 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { return (T7 t7, T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Applies this function partially to 7 arguments. * * @param t1 argument 1 * @param t2 argument 2 * @param t3 argument 3 * @param t4 argument 4 * @param t5 argument 5 * @param t6 argument 6 * @param t7 argument 7 * @return a partial application of this function */ default Function1 apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { return (T8 t8) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Returns the number of function arguments. * @return an int value >= 0 * @see Arity */ default int arity() { return 8; } /** * Returns a curried version of this function. * * @return a curried function equivalent to this. */ default Function1>>>>>>> curried() { return t1 -> t2 -> t3 -> t4 -> t5 -> t6 -> t7 -> t8 -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Returns a tupled version of this function. * * @return a tupled function equivalent to this. */ default Function1, R> tupled() { return t -> apply(t._1, t._2, t._3, t._4, t._5, t._6, t._7, t._8); } /** * Returns a reversed version of this function. This may be useful in a recursive context. * * @return a reversed function equivalent to this. */ default Function8 reversed() { return (t8, t7, t6, t5, t4, t3, t2, t1) -> apply(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Returns a memoizing version of this function, which computes the return value for given arguments only one time. * On subsequent calls given the same arguments the memoized value is returned. *

* Please note that memoizing functions do not permit {@code null} as single argument or return value. * * @return a memoizing function equivalent to this. */ default Function8 memoized() { if (isMemoized()) { return this; } else { final Map, R> cache = new HashMap<>(); return (Function8 & Memoized) (t1, t2, t3, t4, t5, t6, t7, t8) -> { final Tuple8 key = Tuple.of(t1, t2, t3, t4, t5, t6, t7, t8); synchronized (cache) { if (cache.containsKey(key)) { return cache.get(key); } else { final R value = tupled().apply(key); cache.put(key, value); return value; } } }; } } /** * Checks if this function is memoizing (= caching) computed values. * * @return true, if this function is memoizing, false otherwise */ default boolean isMemoized() { return this instanceof Memoized; } /** * Returns a composed function that first applies this Function8 to the given argument and then applies * {@linkplain Function} {@code after} to the result. * * @param return type of after * @param after the function applied after this * @return a function composed of this and after * @throws NullPointerException if after is null */ default Function8 andThen(Function after) { Objects.requireNonNull(after, "after is null"); return (t1, t2, t3, t4, t5, t6, t7, t8) -> after.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple.java000066400000000000000000000607061342074374400222710ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Map; import java.util.Objects; /** * The base interface of all tuples. * * @author Daniel Dietrich */ public interface Tuple { /** * The maximum arity of an Tuple. *

* Note: This value might be changed in a future version of Vavr. * So it is recommended to use this constant instead of hardcoding the current maximum arity. */ int MAX_ARITY = 8; /** * Returns the number of elements of this tuple. * * @return the number of elements. */ int arity(); /** * Converts this tuple to a sequence. * * @return A new {@code Seq}. */ Seq toSeq(); // -- factory methods /** * Creates the empty tuple. * * @return the empty tuple. */ static Tuple0 empty() { return Tuple0.instance(); } /** * Creates a {@code Tuple2} from a {@link Map.Entry}. * * @param Type of first component (entry key) * @param Type of second component (entry value) * @param entry A {@link java.util.Map.Entry} * @return a new {@code Tuple2} containing key and value of the given {@code entry} */ static Tuple2 fromEntry(Map.Entry entry) { Objects.requireNonNull(entry, "entry is null"); return new Tuple2<>(entry.getKey(), entry.getValue()); } /** * Creates a tuple of one element. * * @param type of the 1st element * @param t1 the 1st element * @return a tuple of one element. */ static Tuple1 of(T1 t1) { return new Tuple1<>(t1); } /** * Creates a tuple of two elements. * * @param type of the 1st element * @param type of the 2nd element * @param t1 the 1st element * @param t2 the 2nd element * @return a tuple of two elements. */ static Tuple2 of(T1 t1, T2 t2) { return new Tuple2<>(t1, t2); } /** * Creates a tuple of three elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @return a tuple of three elements. */ static Tuple3 of(T1 t1, T2 t2, T3 t3) { return new Tuple3<>(t1, t2, t3); } /** * Creates a tuple of 4 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @return a tuple of 4 elements. */ static Tuple4 of(T1 t1, T2 t2, T3 t3, T4 t4) { return new Tuple4<>(t1, t2, t3, t4); } /** * Creates a tuple of 5 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @return a tuple of 5 elements. */ static Tuple5 of(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return new Tuple5<>(t1, t2, t3, t4, t5); } /** * Creates a tuple of 6 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @return a tuple of 6 elements. */ static Tuple6 of(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { return new Tuple6<>(t1, t2, t3, t4, t5, t6); } /** * Creates a tuple of 7 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param type of the 7th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @param t7 the 7th element * @return a tuple of 7 elements. */ static Tuple7 of(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { return new Tuple7<>(t1, t2, t3, t4, t5, t6, t7); } /** * Creates a tuple of 8 elements. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param type of the 7th element * @param type of the 8th element * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @param t7 the 7th element * @param t8 the 8th element * @return a tuple of 8 elements. */ static Tuple8 of(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { return new Tuple8<>(t1, t2, t3, t4, t5, t6, t7, t8); } /** * Return the order-dependent hash of the one given value. * * @param o1 the 1st value to hash * @return the same result as {@link Objects#hashCode(Object)} */ static int hash(Object o1) { return Objects.hashCode(o1); } /** * Return the order-dependent hash of the two given values. * * @param o1 the 1st value to hash * @param o2 the 2nd value to hash * @return the same result as {@link Objects#hash(Object...)} */ static int hash(Object o1, Object o2) { int result = 1; result = 31 * result + hash(o1); result = 31 * result + hash(o2); return result; } /** * Return the order-dependent hash of the three given values. * * @param o1 the 1st value to hash * @param o2 the 2nd value to hash * @param o3 the 3rd value to hash * @return the same result as {@link Objects#hash(Object...)} */ static int hash(Object o1, Object o2, Object o3) { int result = 1; result = 31 * result + hash(o1); result = 31 * result + hash(o2); result = 31 * result + hash(o3); return result; } /** * Return the order-dependent hash of the 4 given values. * * @param o1 the 1st value to hash * @param o2 the 2nd value to hash * @param o3 the 3rd value to hash * @param o4 the 4th value to hash * @return the same result as {@link Objects#hash(Object...)} */ static int hash(Object o1, Object o2, Object o3, Object o4) { int result = 1; result = 31 * result + hash(o1); result = 31 * result + hash(o2); result = 31 * result + hash(o3); result = 31 * result + hash(o4); return result; } /** * Return the order-dependent hash of the 5 given values. * * @param o1 the 1st value to hash * @param o2 the 2nd value to hash * @param o3 the 3rd value to hash * @param o4 the 4th value to hash * @param o5 the 5th value to hash * @return the same result as {@link Objects#hash(Object...)} */ static int hash(Object o1, Object o2, Object o3, Object o4, Object o5) { int result = 1; result = 31 * result + hash(o1); result = 31 * result + hash(o2); result = 31 * result + hash(o3); result = 31 * result + hash(o4); result = 31 * result + hash(o5); return result; } /** * Return the order-dependent hash of the 6 given values. * * @param o1 the 1st value to hash * @param o2 the 2nd value to hash * @param o3 the 3rd value to hash * @param o4 the 4th value to hash * @param o5 the 5th value to hash * @param o6 the 6th value to hash * @return the same result as {@link Objects#hash(Object...)} */ static int hash(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) { int result = 1; result = 31 * result + hash(o1); result = 31 * result + hash(o2); result = 31 * result + hash(o3); result = 31 * result + hash(o4); result = 31 * result + hash(o5); result = 31 * result + hash(o6); return result; } /** * Return the order-dependent hash of the 7 given values. * * @param o1 the 1st value to hash * @param o2 the 2nd value to hash * @param o3 the 3rd value to hash * @param o4 the 4th value to hash * @param o5 the 5th value to hash * @param o6 the 6th value to hash * @param o7 the 7th value to hash * @return the same result as {@link Objects#hash(Object...)} */ static int hash(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7) { int result = 1; result = 31 * result + hash(o1); result = 31 * result + hash(o2); result = 31 * result + hash(o3); result = 31 * result + hash(o4); result = 31 * result + hash(o5); result = 31 * result + hash(o6); result = 31 * result + hash(o7); return result; } /** * Return the order-dependent hash of the 8 given values. * * @param o1 the 1st value to hash * @param o2 the 2nd value to hash * @param o3 the 3rd value to hash * @param o4 the 4th value to hash * @param o5 the 5th value to hash * @param o6 the 6th value to hash * @param o7 the 7th value to hash * @param o8 the 8th value to hash * @return the same result as {@link Objects#hash(Object...)} */ static int hash(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8) { int result = 1; result = 31 * result + hash(o1); result = 31 * result + hash(o2); result = 31 * result + hash(o3); result = 31 * result + hash(o4); result = 31 * result + hash(o5); result = 31 * result + hash(o6); result = 31 * result + hash(o7); result = 31 * result + hash(o8); return result; } /** * Narrows a widened {@code Tuple1} to {@code Tuple1}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple1}. * @param the 1st component type * @return the given {@code t} instance as narrowed type {@code Tuple1}. */ @SuppressWarnings("unchecked") static Tuple1 narrow(Tuple1 t) { return (Tuple1) t; } /** * Narrows a widened {@code Tuple2} to {@code Tuple2}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple2}. * @param the 1st component type * @param the 2nd component type * @return the given {@code t} instance as narrowed type {@code Tuple2}. */ @SuppressWarnings("unchecked") static Tuple2 narrow(Tuple2 t) { return (Tuple2) t; } /** * Narrows a widened {@code Tuple3} to {@code Tuple3}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple3}. * @param the 1st component type * @param the 2nd component type * @param the 3rd component type * @return the given {@code t} instance as narrowed type {@code Tuple3}. */ @SuppressWarnings("unchecked") static Tuple3 narrow(Tuple3 t) { return (Tuple3) t; } /** * Narrows a widened {@code Tuple4} to {@code Tuple4}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple4}. * @param the 1st component type * @param the 2nd component type * @param the 3rd component type * @param the 4th component type * @return the given {@code t} instance as narrowed type {@code Tuple4}. */ @SuppressWarnings("unchecked") static Tuple4 narrow(Tuple4 t) { return (Tuple4) t; } /** * Narrows a widened {@code Tuple5} to {@code Tuple5}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple5}. * @param the 1st component type * @param the 2nd component type * @param the 3rd component type * @param the 4th component type * @param the 5th component type * @return the given {@code t} instance as narrowed type {@code Tuple5}. */ @SuppressWarnings("unchecked") static Tuple5 narrow(Tuple5 t) { return (Tuple5) t; } /** * Narrows a widened {@code Tuple6} to {@code Tuple6}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple6}. * @param the 1st component type * @param the 2nd component type * @param the 3rd component type * @param the 4th component type * @param the 5th component type * @param the 6th component type * @return the given {@code t} instance as narrowed type {@code Tuple6}. */ @SuppressWarnings("unchecked") static Tuple6 narrow(Tuple6 t) { return (Tuple6) t; } /** * Narrows a widened {@code Tuple7} to {@code Tuple7}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple7}. * @param the 1st component type * @param the 2nd component type * @param the 3rd component type * @param the 4th component type * @param the 5th component type * @param the 6th component type * @param the 7th component type * @return the given {@code t} instance as narrowed type {@code Tuple7}. */ @SuppressWarnings("unchecked") static Tuple7 narrow(Tuple7 t) { return (Tuple7) t; } /** * Narrows a widened {@code Tuple8} to {@code Tuple8}. * This is eligible because immutable/read-only tuples are covariant. * @param t A {@code Tuple8}. * @param the 1st component type * @param the 2nd component type * @param the 3rd component type * @param the 4th component type * @param the 5th component type * @param the 6th component type * @param the 7th component type * @param the 8th component type * @return the given {@code t} instance as narrowed type {@code Tuple8}. */ @SuppressWarnings("unchecked") static Tuple8 narrow(Tuple8 t) { return (Tuple8) t; } /** * Turns a sequence of {@code Tuple1} into a Tuple1 of {@code Seq}. * * @param 1st component type * @param tuples an {@code Iterable} of tuples * @return a tuple of one {@link Seq}. */ static Tuple1> sequence1(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple1<>(s.map(Tuple1::_1)); } /** * Turns a sequence of {@code Tuple2} into a Tuple2 of {@code Seq}s. * * @param 1st component type * @param 2nd component type * @param tuples an {@code Iterable} of tuples * @return a tuple of two {@link Seq}s. */ static Tuple2, Seq> sequence2(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple2<>(s.map(Tuple2::_1), s.map(Tuple2::_2)); } /** * Turns a sequence of {@code Tuple3} into a Tuple3 of {@code Seq}s. * * @param 1st component type * @param 2nd component type * @param 3rd component type * @param tuples an {@code Iterable} of tuples * @return a tuple of three {@link Seq}s. */ static Tuple3, Seq, Seq> sequence3(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple3<>(s.map(Tuple3::_1), s.map(Tuple3::_2), s.map(Tuple3::_3)); } /** * Turns a sequence of {@code Tuple4} into a Tuple4 of {@code Seq}s. * * @param 1st component type * @param 2nd component type * @param 3rd component type * @param 4th component type * @param tuples an {@code Iterable} of tuples * @return a tuple of 4 {@link Seq}s. */ static Tuple4, Seq, Seq, Seq> sequence4(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple4<>(s.map(Tuple4::_1), s.map(Tuple4::_2), s.map(Tuple4::_3), s.map(Tuple4::_4)); } /** * Turns a sequence of {@code Tuple5} into a Tuple5 of {@code Seq}s. * * @param 1st component type * @param 2nd component type * @param 3rd component type * @param 4th component type * @param 5th component type * @param tuples an {@code Iterable} of tuples * @return a tuple of 5 {@link Seq}s. */ static Tuple5, Seq, Seq, Seq, Seq> sequence5(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple5<>(s.map(Tuple5::_1), s.map(Tuple5::_2), s.map(Tuple5::_3), s.map(Tuple5::_4), s.map(Tuple5::_5)); } /** * Turns a sequence of {@code Tuple6} into a Tuple6 of {@code Seq}s. * * @param 1st component type * @param 2nd component type * @param 3rd component type * @param 4th component type * @param 5th component type * @param 6th component type * @param tuples an {@code Iterable} of tuples * @return a tuple of 6 {@link Seq}s. */ static Tuple6, Seq, Seq, Seq, Seq, Seq> sequence6(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple6<>(s.map(Tuple6::_1), s.map(Tuple6::_2), s.map(Tuple6::_3), s.map(Tuple6::_4), s.map(Tuple6::_5), s.map(Tuple6::_6)); } /** * Turns a sequence of {@code Tuple7} into a Tuple7 of {@code Seq}s. * * @param 1st component type * @param 2nd component type * @param 3rd component type * @param 4th component type * @param 5th component type * @param 6th component type * @param 7th component type * @param tuples an {@code Iterable} of tuples * @return a tuple of 7 {@link Seq}s. */ static Tuple7, Seq, Seq, Seq, Seq, Seq, Seq> sequence7(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple7<>(s.map(Tuple7::_1), s.map(Tuple7::_2), s.map(Tuple7::_3), s.map(Tuple7::_4), s.map(Tuple7::_5), s.map(Tuple7::_6), s.map(Tuple7::_7)); } /** * Turns a sequence of {@code Tuple8} into a Tuple8 of {@code Seq}s. * * @param 1st component type * @param 2nd component type * @param 3rd component type * @param 4th component type * @param 5th component type * @param 6th component type * @param 7th component type * @param 8th component type * @param tuples an {@code Iterable} of tuples * @return a tuple of 8 {@link Seq}s. */ static Tuple8, Seq, Seq, Seq, Seq, Seq, Seq, Seq> sequence8(Iterable> tuples) { Objects.requireNonNull(tuples, "tuples is null"); final Stream> s = Stream.ofAll(tuples); return new Tuple8<>(s.map(Tuple8::_1), s.map(Tuple8::_2), s.map(Tuple8::_3), s.map(Tuple8::_4), s.map(Tuple8::_5), s.map(Tuple8::_6), s.map(Tuple8::_7), s.map(Tuple8::_8)); } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple0.java000066400000000000000000000216601342074374400223450ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Supplier; /** * A tuple of no elements which can be seen as cartesian product of no components. * * @author Daniel Dietrich */ public final class Tuple0 implements Tuple, Comparable, Serializable { private static final long serialVersionUID = 1L; /** * The singleton instance of Tuple0. */ private static final Tuple0 INSTANCE = new Tuple0 (); /** * The singleton Tuple0 comparator. */ private static final Comparator COMPARATOR = (Comparator & Serializable) (t1, t2) -> 0; // hidden constructor, internally called private Tuple0 () { } /** * Returns the singleton instance of Tuple0. * * @return The singleton instance of Tuple0. */ public static Tuple0 instance() { return INSTANCE; } public static Comparator comparator() { return COMPARATOR; } @Override public int arity() { return 0; } @Override public int compareTo(Tuple0 that) { return 0; } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Supplier f) { Objects.requireNonNull(f, "f is null"); return f.get(); } @Override public Seq toSeq() { return List.empty(); } /** * Append a value to this tuple. * * @param type of the value to append * @param t1 the value to append * @return a new Tuple with the value appended */ public Tuple1 append(T1 t1) { return Tuple.of(t1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple1 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param the type of the 2nd value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple2 concat(Tuple2 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1, tuple._2); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple3 concat(Tuple3 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1, tuple._2, tuple._3); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple4 concat(Tuple4 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1, tuple._2, tuple._3, tuple._4); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple5 concat(Tuple5 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1, tuple._2, tuple._3, tuple._4, tuple._5); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple6 concat(Tuple6 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple7 concat(Tuple7 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6, tuple._7); } /** * Concat a tuple's values to this tuple. * * @param the type of the 1st value in the tuple * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple8 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6, tuple._7, tuple._8); } // -- Object @Override public boolean equals(Object o) { return o == this; } @Override public int hashCode() { return 1; } @Override public String toString() { return "()"; } // -- Serializable implementation /** * Instance control for object serialization. * * @return The singleton instance of Tuple0. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple1.java000066400000000000000000000225721342074374400223510ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; /** * A tuple of one element which can be seen as cartesian product of one component. * * @param type of the 1st element * @author Daniel Dietrich */ public final class Tuple1 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * Constructs a tuple of one element. * * @param t1 the 1st element */ public Tuple1(T1 t1) { this._1 = t1; } public static Comparator> comparator(Comparator t1Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static > int compareTo(Tuple1 o1, Tuple1 o2) { final Tuple1 t1 = (Tuple1) o1; final Tuple1 t2 = (Tuple1) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } // all components are equal return 0; } @Override public int arity() { return 1; } @Override public int compareTo(Tuple1 that) { return Tuple1.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple1 update1(T1 value) { return new Tuple1<>(value); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple1 map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return Tuple.of(mapper.apply(_1)); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Function f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1); } @Override public Seq toSeq() { return List.of(_1); } /** * Append a value to this tuple. * * @param type of the value to append * @param t2 the value to append * @return a new Tuple with the value appended */ public Tuple2 append(T2 t2) { return Tuple.of(_1, t2); } /** * Concat a tuple's values to this tuple. * * @param the type of the 2nd value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple2 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, tuple._1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple3 concat(Tuple2 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, tuple._1, tuple._2); } /** * Concat a tuple's values to this tuple. * * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple4 concat(Tuple3 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, tuple._1, tuple._2, tuple._3); } /** * Concat a tuple's values to this tuple. * * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple5 concat(Tuple4 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, tuple._1, tuple._2, tuple._3, tuple._4); } /** * Concat a tuple's values to this tuple. * * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple6 concat(Tuple5 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, tuple._1, tuple._2, tuple._3, tuple._4, tuple._5); } /** * Concat a tuple's values to this tuple. * * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple7 concat(Tuple6 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6); } /** * Concat a tuple's values to this tuple. * * @param the type of the 2nd value in the tuple * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple7 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6, tuple._7); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple1)) { return false; } else { final Tuple1 that = (Tuple1) o; return Objects.equals(this._1, that._1); } } @Override public int hashCode() { return Tuple.hash(_1); } @Override public String toString() { return "(" + _1 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple2.java000066400000000000000000000277311342074374400223540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.AbstractMap; import java.util.Comparator; import java.util.Map; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; /** * A tuple of two elements which can be seen as cartesian product of two components. * * @param type of the 1st element * @param type of the 2nd element * @author Daniel Dietrich */ public final class Tuple2 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * The 2nd element of this tuple. */ public final T2 _2; /** * Constructs a tuple of two elements. * * @param t1 the 1st element * @param t2 the 2nd element */ public Tuple2(T1 t1, T2 t2) { this._1 = t1; this._2 = t2; } public static Comparator> comparator(Comparator t1Comp, Comparator t2Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } final int check2 = t2Comp.compare(t1._2, t2._2); if (check2 != 0) { return check2; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static , U2 extends Comparable> int compareTo(Tuple2 o1, Tuple2 o2) { final Tuple2 t1 = (Tuple2) o1; final Tuple2 t2 = (Tuple2) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } final int check2 = t1._2.compareTo(t2._2); if (check2 != 0) { return check2; } // all components are equal return 0; } @Override public int arity() { return 2; } @Override public int compareTo(Tuple2 that) { return Tuple2.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple2 update1(T1 value) { return new Tuple2<>(value, _2); } /** * Getter of the 2nd element of this tuple. * * @return the 2nd element of this Tuple. */ public T2 _2() { return _2; } /** * Sets the 2nd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 2nd element of this Tuple. */ public Tuple2 update2(T2 value) { return new Tuple2<>(_1, value); } /** * Swaps the elements of this {@code Tuple}. * * @return A new Tuple where the first element is the second element of this Tuple * and the second element is the first element of this Tuple. */ public Tuple2 swap() { return Tuple.of(_2, _1); } /** * Converts the tuple to java.util.Map.Entry {@code Tuple}. * * @return A java.util.Map.Entry where the first element is the key and the second * element is the value. */ public Map.Entry toEntry() { return new AbstractMap.SimpleEntry<>(_1, _2); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @param new type of the 2nd component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple2 map(BiFunction> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapper.apply(_1, _2); } /** * Maps the components of this tuple using a mapper function for each component. * * @param f1 the mapper function of the 1st component * @param f2 the mapper function of the 2nd component * @param new type of the 1st component * @param new type of the 2nd component * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public Tuple2 map(Function f1, Function f2) { Objects.requireNonNull(f1, "f1 is null"); Objects.requireNonNull(f2, "f2 is null"); return Tuple.of(f1.apply(_1), f2.apply(_2)); } /** * Maps the 1st component of this tuple to a new value. * * @param new type of the 1st component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 1st component */ public Tuple2 map1(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_1); return Tuple.of(u, _2); } /** * Maps the 2nd component of this tuple to a new value. * * @param new type of the 2nd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 2nd component */ public Tuple2 map2(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_2); return Tuple.of(_1, u); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(BiFunction f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1, _2); } @Override public Seq toSeq() { return List.of(_1, _2); } /** * Append a value to this tuple. * * @param type of the value to append * @param t3 the value to append * @return a new Tuple with the value appended */ public Tuple3 append(T3 t3) { return Tuple.of(_1, _2, t3); } /** * Concat a tuple's values to this tuple. * * @param the type of the 3rd value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple3 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, tuple._1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple4 concat(Tuple2 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, tuple._1, tuple._2); } /** * Concat a tuple's values to this tuple. * * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple5 concat(Tuple3 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, tuple._1, tuple._2, tuple._3); } /** * Concat a tuple's values to this tuple. * * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple6 concat(Tuple4 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, tuple._1, tuple._2, tuple._3, tuple._4); } /** * Concat a tuple's values to this tuple. * * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple7 concat(Tuple5 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, tuple._1, tuple._2, tuple._3, tuple._4, tuple._5); } /** * Concat a tuple's values to this tuple. * * @param the type of the 3rd value in the tuple * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple6 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple2)) { return false; } else { final Tuple2 that = (Tuple2) o; return Objects.equals(this._1, that._1) && Objects.equals(this._2, that._2); } } @Override public int hashCode() { return Tuple.hash(_1, _2); } @Override public String toString() { return "(" + _1 + ", " + _2 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple3.java000066400000000000000000000305731342074374400223530ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; /** * A tuple of three elements which can be seen as cartesian product of three components. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @author Daniel Dietrich */ public final class Tuple3 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * The 2nd element of this tuple. */ public final T2 _2; /** * The 3rd element of this tuple. */ public final T3 _3; /** * Constructs a tuple of three elements. * * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element */ public Tuple3(T1 t1, T2 t2, T3 t3) { this._1 = t1; this._2 = t2; this._3 = t3; } public static Comparator> comparator(Comparator t1Comp, Comparator t2Comp, Comparator t3Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } final int check2 = t2Comp.compare(t1._2, t2._2); if (check2 != 0) { return check2; } final int check3 = t3Comp.compare(t1._3, t2._3); if (check3 != 0) { return check3; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static , U2 extends Comparable, U3 extends Comparable> int compareTo(Tuple3 o1, Tuple3 o2) { final Tuple3 t1 = (Tuple3) o1; final Tuple3 t2 = (Tuple3) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } final int check2 = t1._2.compareTo(t2._2); if (check2 != 0) { return check2; } final int check3 = t1._3.compareTo(t2._3); if (check3 != 0) { return check3; } // all components are equal return 0; } @Override public int arity() { return 3; } @Override public int compareTo(Tuple3 that) { return Tuple3.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple3 update1(T1 value) { return new Tuple3<>(value, _2, _3); } /** * Getter of the 2nd element of this tuple. * * @return the 2nd element of this Tuple. */ public T2 _2() { return _2; } /** * Sets the 2nd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 2nd element of this Tuple. */ public Tuple3 update2(T2 value) { return new Tuple3<>(_1, value, _3); } /** * Getter of the 3rd element of this tuple. * * @return the 3rd element of this Tuple. */ public T3 _3() { return _3; } /** * Sets the 3rd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 3rd element of this Tuple. */ public Tuple3 update3(T3 value) { return new Tuple3<>(_1, _2, value); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple3 map(Function3> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapper.apply(_1, _2, _3); } /** * Maps the components of this tuple using a mapper function for each component. * * @param f1 the mapper function of the 1st component * @param f2 the mapper function of the 2nd component * @param f3 the mapper function of the 3rd component * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public Tuple3 map(Function f1, Function f2, Function f3) { Objects.requireNonNull(f1, "f1 is null"); Objects.requireNonNull(f2, "f2 is null"); Objects.requireNonNull(f3, "f3 is null"); return Tuple.of(f1.apply(_1), f2.apply(_2), f3.apply(_3)); } /** * Maps the 1st component of this tuple to a new value. * * @param new type of the 1st component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 1st component */ public Tuple3 map1(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_1); return Tuple.of(u, _2, _3); } /** * Maps the 2nd component of this tuple to a new value. * * @param new type of the 2nd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 2nd component */ public Tuple3 map2(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_2); return Tuple.of(_1, u, _3); } /** * Maps the 3rd component of this tuple to a new value. * * @param new type of the 3rd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 3rd component */ public Tuple3 map3(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_3); return Tuple.of(_1, _2, u); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Function3 f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1, _2, _3); } @Override public Seq toSeq() { return List.of(_1, _2, _3); } /** * Append a value to this tuple. * * @param type of the value to append * @param t4 the value to append * @return a new Tuple with the value appended */ public Tuple4 append(T4 t4) { return Tuple.of(_1, _2, _3, t4); } /** * Concat a tuple's values to this tuple. * * @param the type of the 4th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple4 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, tuple._1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple5 concat(Tuple2 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, tuple._1, tuple._2); } /** * Concat a tuple's values to this tuple. * * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple6 concat(Tuple3 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, tuple._1, tuple._2, tuple._3); } /** * Concat a tuple's values to this tuple. * * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple7 concat(Tuple4 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, tuple._1, tuple._2, tuple._3, tuple._4); } /** * Concat a tuple's values to this tuple. * * @param the type of the 4th value in the tuple * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple5 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, tuple._1, tuple._2, tuple._3, tuple._4, tuple._5); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple3)) { return false; } else { final Tuple3 that = (Tuple3) o; return Objects.equals(this._1, that._1) && Objects.equals(this._2, that._2) && Objects.equals(this._3, that._3); } } @Override public int hashCode() { return Tuple.hash(_1, _2, _3); } @Override public String toString() { return "(" + _1 + ", " + _2 + ", " + _3 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple4.java000066400000000000000000000330471342074374400223530ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; /** * A tuple of 4 elements which can be seen as cartesian product of 4 components. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @author Daniel Dietrich */ public final class Tuple4 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * The 2nd element of this tuple. */ public final T2 _2; /** * The 3rd element of this tuple. */ public final T3 _3; /** * The 4th element of this tuple. */ public final T4 _4; /** * Constructs a tuple of 4 elements. * * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element */ public Tuple4(T1 t1, T2 t2, T3 t3, T4 t4) { this._1 = t1; this._2 = t2; this._3 = t3; this._4 = t4; } public static Comparator> comparator(Comparator t1Comp, Comparator t2Comp, Comparator t3Comp, Comparator t4Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } final int check2 = t2Comp.compare(t1._2, t2._2); if (check2 != 0) { return check2; } final int check3 = t3Comp.compare(t1._3, t2._3); if (check3 != 0) { return check3; } final int check4 = t4Comp.compare(t1._4, t2._4); if (check4 != 0) { return check4; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static , U2 extends Comparable, U3 extends Comparable, U4 extends Comparable> int compareTo(Tuple4 o1, Tuple4 o2) { final Tuple4 t1 = (Tuple4) o1; final Tuple4 t2 = (Tuple4) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } final int check2 = t1._2.compareTo(t2._2); if (check2 != 0) { return check2; } final int check3 = t1._3.compareTo(t2._3); if (check3 != 0) { return check3; } final int check4 = t1._4.compareTo(t2._4); if (check4 != 0) { return check4; } // all components are equal return 0; } @Override public int arity() { return 4; } @Override public int compareTo(Tuple4 that) { return Tuple4.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple4 update1(T1 value) { return new Tuple4<>(value, _2, _3, _4); } /** * Getter of the 2nd element of this tuple. * * @return the 2nd element of this Tuple. */ public T2 _2() { return _2; } /** * Sets the 2nd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 2nd element of this Tuple. */ public Tuple4 update2(T2 value) { return new Tuple4<>(_1, value, _3, _4); } /** * Getter of the 3rd element of this tuple. * * @return the 3rd element of this Tuple. */ public T3 _3() { return _3; } /** * Sets the 3rd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 3rd element of this Tuple. */ public Tuple4 update3(T3 value) { return new Tuple4<>(_1, _2, value, _4); } /** * Getter of the 4th element of this tuple. * * @return the 4th element of this Tuple. */ public T4 _4() { return _4; } /** * Sets the 4th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 4th element of this Tuple. */ public Tuple4 update4(T4 value) { return new Tuple4<>(_1, _2, _3, value); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple4 map(Function4> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapper.apply(_1, _2, _3, _4); } /** * Maps the components of this tuple using a mapper function for each component. * * @param f1 the mapper function of the 1st component * @param f2 the mapper function of the 2nd component * @param f3 the mapper function of the 3rd component * @param f4 the mapper function of the 4th component * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public Tuple4 map(Function f1, Function f2, Function f3, Function f4) { Objects.requireNonNull(f1, "f1 is null"); Objects.requireNonNull(f2, "f2 is null"); Objects.requireNonNull(f3, "f3 is null"); Objects.requireNonNull(f4, "f4 is null"); return Tuple.of(f1.apply(_1), f2.apply(_2), f3.apply(_3), f4.apply(_4)); } /** * Maps the 1st component of this tuple to a new value. * * @param new type of the 1st component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 1st component */ public Tuple4 map1(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_1); return Tuple.of(u, _2, _3, _4); } /** * Maps the 2nd component of this tuple to a new value. * * @param new type of the 2nd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 2nd component */ public Tuple4 map2(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_2); return Tuple.of(_1, u, _3, _4); } /** * Maps the 3rd component of this tuple to a new value. * * @param new type of the 3rd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 3rd component */ public Tuple4 map3(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_3); return Tuple.of(_1, _2, u, _4); } /** * Maps the 4th component of this tuple to a new value. * * @param new type of the 4th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 4th component */ public Tuple4 map4(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_4); return Tuple.of(_1, _2, _3, u); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Function4 f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1, _2, _3, _4); } @Override public Seq toSeq() { return List.of(_1, _2, _3, _4); } /** * Append a value to this tuple. * * @param type of the value to append * @param t5 the value to append * @return a new Tuple with the value appended */ public Tuple5 append(T5 t5) { return Tuple.of(_1, _2, _3, _4, t5); } /** * Concat a tuple's values to this tuple. * * @param the type of the 5th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple5 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, tuple._1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple6 concat(Tuple2 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, tuple._1, tuple._2); } /** * Concat a tuple's values to this tuple. * * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple7 concat(Tuple3 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, tuple._1, tuple._2, tuple._3); } /** * Concat a tuple's values to this tuple. * * @param the type of the 5th value in the tuple * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple4 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, tuple._1, tuple._2, tuple._3, tuple._4); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple4)) { return false; } else { final Tuple4 that = (Tuple4) o; return Objects.equals(this._1, that._1) && Objects.equals(this._2, that._2) && Objects.equals(this._3, that._3) && Objects.equals(this._4, that._4); } } @Override public int hashCode() { return Tuple.hash(_1, _2, _3, _4); } @Override public String toString() { return "(" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple5.java000066400000000000000000000354771342074374400223650ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; /** * A tuple of 5 elements which can be seen as cartesian product of 5 components. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @author Daniel Dietrich */ public final class Tuple5 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * The 2nd element of this tuple. */ public final T2 _2; /** * The 3rd element of this tuple. */ public final T3 _3; /** * The 4th element of this tuple. */ public final T4 _4; /** * The 5th element of this tuple. */ public final T5 _5; /** * Constructs a tuple of 5 elements. * * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element */ public Tuple5(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { this._1 = t1; this._2 = t2; this._3 = t3; this._4 = t4; this._5 = t5; } public static Comparator> comparator(Comparator t1Comp, Comparator t2Comp, Comparator t3Comp, Comparator t4Comp, Comparator t5Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } final int check2 = t2Comp.compare(t1._2, t2._2); if (check2 != 0) { return check2; } final int check3 = t3Comp.compare(t1._3, t2._3); if (check3 != 0) { return check3; } final int check4 = t4Comp.compare(t1._4, t2._4); if (check4 != 0) { return check4; } final int check5 = t5Comp.compare(t1._5, t2._5); if (check5 != 0) { return check5; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static , U2 extends Comparable, U3 extends Comparable, U4 extends Comparable, U5 extends Comparable> int compareTo(Tuple5 o1, Tuple5 o2) { final Tuple5 t1 = (Tuple5) o1; final Tuple5 t2 = (Tuple5) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } final int check2 = t1._2.compareTo(t2._2); if (check2 != 0) { return check2; } final int check3 = t1._3.compareTo(t2._3); if (check3 != 0) { return check3; } final int check4 = t1._4.compareTo(t2._4); if (check4 != 0) { return check4; } final int check5 = t1._5.compareTo(t2._5); if (check5 != 0) { return check5; } // all components are equal return 0; } @Override public int arity() { return 5; } @Override public int compareTo(Tuple5 that) { return Tuple5.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple5 update1(T1 value) { return new Tuple5<>(value, _2, _3, _4, _5); } /** * Getter of the 2nd element of this tuple. * * @return the 2nd element of this Tuple. */ public T2 _2() { return _2; } /** * Sets the 2nd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 2nd element of this Tuple. */ public Tuple5 update2(T2 value) { return new Tuple5<>(_1, value, _3, _4, _5); } /** * Getter of the 3rd element of this tuple. * * @return the 3rd element of this Tuple. */ public T3 _3() { return _3; } /** * Sets the 3rd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 3rd element of this Tuple. */ public Tuple5 update3(T3 value) { return new Tuple5<>(_1, _2, value, _4, _5); } /** * Getter of the 4th element of this tuple. * * @return the 4th element of this Tuple. */ public T4 _4() { return _4; } /** * Sets the 4th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 4th element of this Tuple. */ public Tuple5 update4(T4 value) { return new Tuple5<>(_1, _2, _3, value, _5); } /** * Getter of the 5th element of this tuple. * * @return the 5th element of this Tuple. */ public T5 _5() { return _5; } /** * Sets the 5th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 5th element of this Tuple. */ public Tuple5 update5(T5 value) { return new Tuple5<>(_1, _2, _3, _4, value); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple5 map(Function5> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapper.apply(_1, _2, _3, _4, _5); } /** * Maps the components of this tuple using a mapper function for each component. * * @param f1 the mapper function of the 1st component * @param f2 the mapper function of the 2nd component * @param f3 the mapper function of the 3rd component * @param f4 the mapper function of the 4th component * @param f5 the mapper function of the 5th component * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public Tuple5 map(Function f1, Function f2, Function f3, Function f4, Function f5) { Objects.requireNonNull(f1, "f1 is null"); Objects.requireNonNull(f2, "f2 is null"); Objects.requireNonNull(f3, "f3 is null"); Objects.requireNonNull(f4, "f4 is null"); Objects.requireNonNull(f5, "f5 is null"); return Tuple.of(f1.apply(_1), f2.apply(_2), f3.apply(_3), f4.apply(_4), f5.apply(_5)); } /** * Maps the 1st component of this tuple to a new value. * * @param new type of the 1st component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 1st component */ public Tuple5 map1(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_1); return Tuple.of(u, _2, _3, _4, _5); } /** * Maps the 2nd component of this tuple to a new value. * * @param new type of the 2nd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 2nd component */ public Tuple5 map2(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_2); return Tuple.of(_1, u, _3, _4, _5); } /** * Maps the 3rd component of this tuple to a new value. * * @param new type of the 3rd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 3rd component */ public Tuple5 map3(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_3); return Tuple.of(_1, _2, u, _4, _5); } /** * Maps the 4th component of this tuple to a new value. * * @param new type of the 4th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 4th component */ public Tuple5 map4(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_4); return Tuple.of(_1, _2, _3, u, _5); } /** * Maps the 5th component of this tuple to a new value. * * @param new type of the 5th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 5th component */ public Tuple5 map5(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_5); return Tuple.of(_1, _2, _3, _4, u); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Function5 f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1, _2, _3, _4, _5); } @Override public Seq toSeq() { return List.of(_1, _2, _3, _4, _5); } /** * Append a value to this tuple. * * @param type of the value to append * @param t6 the value to append * @return a new Tuple with the value appended */ public Tuple6 append(T6 t6) { return Tuple.of(_1, _2, _3, _4, _5, t6); } /** * Concat a tuple's values to this tuple. * * @param the type of the 6th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple6 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, _5, tuple._1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple7 concat(Tuple2 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, _5, tuple._1, tuple._2); } /** * Concat a tuple's values to this tuple. * * @param the type of the 6th value in the tuple * @param the type of the 7th value in the tuple * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple3 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, _5, tuple._1, tuple._2, tuple._3); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple5)) { return false; } else { final Tuple5 that = (Tuple5) o; return Objects.equals(this._1, that._1) && Objects.equals(this._2, that._2) && Objects.equals(this._3, that._3) && Objects.equals(this._4, that._4) && Objects.equals(this._5, that._5); } } @Override public int hashCode() { return Tuple.hash(_1, _2, _3, _4, _5); } @Override public String toString() { return "(" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple6.java000066400000000000000000000402671342074374400223570ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; /** * A tuple of 6 elements which can be seen as cartesian product of 6 components. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @author Daniel Dietrich */ public final class Tuple6 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * The 2nd element of this tuple. */ public final T2 _2; /** * The 3rd element of this tuple. */ public final T3 _3; /** * The 4th element of this tuple. */ public final T4 _4; /** * The 5th element of this tuple. */ public final T5 _5; /** * The 6th element of this tuple. */ public final T6 _6; /** * Constructs a tuple of 6 elements. * * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element */ public Tuple6(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { this._1 = t1; this._2 = t2; this._3 = t3; this._4 = t4; this._5 = t5; this._6 = t6; } public static Comparator> comparator(Comparator t1Comp, Comparator t2Comp, Comparator t3Comp, Comparator t4Comp, Comparator t5Comp, Comparator t6Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } final int check2 = t2Comp.compare(t1._2, t2._2); if (check2 != 0) { return check2; } final int check3 = t3Comp.compare(t1._3, t2._3); if (check3 != 0) { return check3; } final int check4 = t4Comp.compare(t1._4, t2._4); if (check4 != 0) { return check4; } final int check5 = t5Comp.compare(t1._5, t2._5); if (check5 != 0) { return check5; } final int check6 = t6Comp.compare(t1._6, t2._6); if (check6 != 0) { return check6; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static , U2 extends Comparable, U3 extends Comparable, U4 extends Comparable, U5 extends Comparable, U6 extends Comparable> int compareTo(Tuple6 o1, Tuple6 o2) { final Tuple6 t1 = (Tuple6) o1; final Tuple6 t2 = (Tuple6) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } final int check2 = t1._2.compareTo(t2._2); if (check2 != 0) { return check2; } final int check3 = t1._3.compareTo(t2._3); if (check3 != 0) { return check3; } final int check4 = t1._4.compareTo(t2._4); if (check4 != 0) { return check4; } final int check5 = t1._5.compareTo(t2._5); if (check5 != 0) { return check5; } final int check6 = t1._6.compareTo(t2._6); if (check6 != 0) { return check6; } // all components are equal return 0; } @Override public int arity() { return 6; } @Override public int compareTo(Tuple6 that) { return Tuple6.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple6 update1(T1 value) { return new Tuple6<>(value, _2, _3, _4, _5, _6); } /** * Getter of the 2nd element of this tuple. * * @return the 2nd element of this Tuple. */ public T2 _2() { return _2; } /** * Sets the 2nd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 2nd element of this Tuple. */ public Tuple6 update2(T2 value) { return new Tuple6<>(_1, value, _3, _4, _5, _6); } /** * Getter of the 3rd element of this tuple. * * @return the 3rd element of this Tuple. */ public T3 _3() { return _3; } /** * Sets the 3rd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 3rd element of this Tuple. */ public Tuple6 update3(T3 value) { return new Tuple6<>(_1, _2, value, _4, _5, _6); } /** * Getter of the 4th element of this tuple. * * @return the 4th element of this Tuple. */ public T4 _4() { return _4; } /** * Sets the 4th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 4th element of this Tuple. */ public Tuple6 update4(T4 value) { return new Tuple6<>(_1, _2, _3, value, _5, _6); } /** * Getter of the 5th element of this tuple. * * @return the 5th element of this Tuple. */ public T5 _5() { return _5; } /** * Sets the 5th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 5th element of this Tuple. */ public Tuple6 update5(T5 value) { return new Tuple6<>(_1, _2, _3, _4, value, _6); } /** * Getter of the 6th element of this tuple. * * @return the 6th element of this Tuple. */ public T6 _6() { return _6; } /** * Sets the 6th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 6th element of this Tuple. */ public Tuple6 update6(T6 value) { return new Tuple6<>(_1, _2, _3, _4, _5, value); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @param new type of the 6th component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple6 map(Function6> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapper.apply(_1, _2, _3, _4, _5, _6); } /** * Maps the components of this tuple using a mapper function for each component. * * @param f1 the mapper function of the 1st component * @param f2 the mapper function of the 2nd component * @param f3 the mapper function of the 3rd component * @param f4 the mapper function of the 4th component * @param f5 the mapper function of the 5th component * @param f6 the mapper function of the 6th component * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @param new type of the 6th component * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public Tuple6 map(Function f1, Function f2, Function f3, Function f4, Function f5, Function f6) { Objects.requireNonNull(f1, "f1 is null"); Objects.requireNonNull(f2, "f2 is null"); Objects.requireNonNull(f3, "f3 is null"); Objects.requireNonNull(f4, "f4 is null"); Objects.requireNonNull(f5, "f5 is null"); Objects.requireNonNull(f6, "f6 is null"); return Tuple.of(f1.apply(_1), f2.apply(_2), f3.apply(_3), f4.apply(_4), f5.apply(_5), f6.apply(_6)); } /** * Maps the 1st component of this tuple to a new value. * * @param new type of the 1st component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 1st component */ public Tuple6 map1(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_1); return Tuple.of(u, _2, _3, _4, _5, _6); } /** * Maps the 2nd component of this tuple to a new value. * * @param new type of the 2nd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 2nd component */ public Tuple6 map2(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_2); return Tuple.of(_1, u, _3, _4, _5, _6); } /** * Maps the 3rd component of this tuple to a new value. * * @param new type of the 3rd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 3rd component */ public Tuple6 map3(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_3); return Tuple.of(_1, _2, u, _4, _5, _6); } /** * Maps the 4th component of this tuple to a new value. * * @param new type of the 4th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 4th component */ public Tuple6 map4(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_4); return Tuple.of(_1, _2, _3, u, _5, _6); } /** * Maps the 5th component of this tuple to a new value. * * @param new type of the 5th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 5th component */ public Tuple6 map5(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_5); return Tuple.of(_1, _2, _3, _4, u, _6); } /** * Maps the 6th component of this tuple to a new value. * * @param new type of the 6th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 6th component */ public Tuple6 map6(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_6); return Tuple.of(_1, _2, _3, _4, _5, u); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Function6 f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1, _2, _3, _4, _5, _6); } @Override public Seq toSeq() { return List.of(_1, _2, _3, _4, _5, _6); } /** * Append a value to this tuple. * * @param type of the value to append * @param t7 the value to append * @return a new Tuple with the value appended */ public Tuple7 append(T7 t7) { return Tuple.of(_1, _2, _3, _4, _5, _6, t7); } /** * Concat a tuple's values to this tuple. * * @param the type of the 7th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple7 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, _5, _6, tuple._1); } /** * Concat a tuple's values to this tuple. * * @param the type of the 7th value in the tuple * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple2 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, _5, _6, tuple._1, tuple._2); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple6)) { return false; } else { final Tuple6 that = (Tuple6) o; return Objects.equals(this._1, that._1) && Objects.equals(this._2, that._2) && Objects.equals(this._3, that._3) && Objects.equals(this._4, that._4) && Objects.equals(this._5, that._5) && Objects.equals(this._6, that._6); } } @Override public int hashCode() { return Tuple.hash(_1, _2, _3, _4, _5, _6); } @Override public String toString() { return "(" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple7.java000066400000000000000000000432171342074374400223560ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; /** * A tuple of 7 elements which can be seen as cartesian product of 7 components. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param type of the 7th element * @author Daniel Dietrich */ public final class Tuple7 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * The 2nd element of this tuple. */ public final T2 _2; /** * The 3rd element of this tuple. */ public final T3 _3; /** * The 4th element of this tuple. */ public final T4 _4; /** * The 5th element of this tuple. */ public final T5 _5; /** * The 6th element of this tuple. */ public final T6 _6; /** * The 7th element of this tuple. */ public final T7 _7; /** * Constructs a tuple of 7 elements. * * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @param t7 the 7th element */ public Tuple7(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { this._1 = t1; this._2 = t2; this._3 = t3; this._4 = t4; this._5 = t5; this._6 = t6; this._7 = t7; } public static Comparator> comparator(Comparator t1Comp, Comparator t2Comp, Comparator t3Comp, Comparator t4Comp, Comparator t5Comp, Comparator t6Comp, Comparator t7Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } final int check2 = t2Comp.compare(t1._2, t2._2); if (check2 != 0) { return check2; } final int check3 = t3Comp.compare(t1._3, t2._3); if (check3 != 0) { return check3; } final int check4 = t4Comp.compare(t1._4, t2._4); if (check4 != 0) { return check4; } final int check5 = t5Comp.compare(t1._5, t2._5); if (check5 != 0) { return check5; } final int check6 = t6Comp.compare(t1._6, t2._6); if (check6 != 0) { return check6; } final int check7 = t7Comp.compare(t1._7, t2._7); if (check7 != 0) { return check7; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static , U2 extends Comparable, U3 extends Comparable, U4 extends Comparable, U5 extends Comparable, U6 extends Comparable, U7 extends Comparable> int compareTo(Tuple7 o1, Tuple7 o2) { final Tuple7 t1 = (Tuple7) o1; final Tuple7 t2 = (Tuple7) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } final int check2 = t1._2.compareTo(t2._2); if (check2 != 0) { return check2; } final int check3 = t1._3.compareTo(t2._3); if (check3 != 0) { return check3; } final int check4 = t1._4.compareTo(t2._4); if (check4 != 0) { return check4; } final int check5 = t1._5.compareTo(t2._5); if (check5 != 0) { return check5; } final int check6 = t1._6.compareTo(t2._6); if (check6 != 0) { return check6; } final int check7 = t1._7.compareTo(t2._7); if (check7 != 0) { return check7; } // all components are equal return 0; } @Override public int arity() { return 7; } @Override public int compareTo(Tuple7 that) { return Tuple7.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple7 update1(T1 value) { return new Tuple7<>(value, _2, _3, _4, _5, _6, _7); } /** * Getter of the 2nd element of this tuple. * * @return the 2nd element of this Tuple. */ public T2 _2() { return _2; } /** * Sets the 2nd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 2nd element of this Tuple. */ public Tuple7 update2(T2 value) { return new Tuple7<>(_1, value, _3, _4, _5, _6, _7); } /** * Getter of the 3rd element of this tuple. * * @return the 3rd element of this Tuple. */ public T3 _3() { return _3; } /** * Sets the 3rd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 3rd element of this Tuple. */ public Tuple7 update3(T3 value) { return new Tuple7<>(_1, _2, value, _4, _5, _6, _7); } /** * Getter of the 4th element of this tuple. * * @return the 4th element of this Tuple. */ public T4 _4() { return _4; } /** * Sets the 4th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 4th element of this Tuple. */ public Tuple7 update4(T4 value) { return new Tuple7<>(_1, _2, _3, value, _5, _6, _7); } /** * Getter of the 5th element of this tuple. * * @return the 5th element of this Tuple. */ public T5 _5() { return _5; } /** * Sets the 5th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 5th element of this Tuple. */ public Tuple7 update5(T5 value) { return new Tuple7<>(_1, _2, _3, _4, value, _6, _7); } /** * Getter of the 6th element of this tuple. * * @return the 6th element of this Tuple. */ public T6 _6() { return _6; } /** * Sets the 6th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 6th element of this Tuple. */ public Tuple7 update6(T6 value) { return new Tuple7<>(_1, _2, _3, _4, _5, value, _7); } /** * Getter of the 7th element of this tuple. * * @return the 7th element of this Tuple. */ public T7 _7() { return _7; } /** * Sets the 7th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 7th element of this Tuple. */ public Tuple7 update7(T7 value) { return new Tuple7<>(_1, _2, _3, _4, _5, _6, value); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @param new type of the 6th component * @param new type of the 7th component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple7 map(Function7> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapper.apply(_1, _2, _3, _4, _5, _6, _7); } /** * Maps the components of this tuple using a mapper function for each component. * * @param f1 the mapper function of the 1st component * @param f2 the mapper function of the 2nd component * @param f3 the mapper function of the 3rd component * @param f4 the mapper function of the 4th component * @param f5 the mapper function of the 5th component * @param f6 the mapper function of the 6th component * @param f7 the mapper function of the 7th component * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @param new type of the 6th component * @param new type of the 7th component * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public Tuple7 map(Function f1, Function f2, Function f3, Function f4, Function f5, Function f6, Function f7) { Objects.requireNonNull(f1, "f1 is null"); Objects.requireNonNull(f2, "f2 is null"); Objects.requireNonNull(f3, "f3 is null"); Objects.requireNonNull(f4, "f4 is null"); Objects.requireNonNull(f5, "f5 is null"); Objects.requireNonNull(f6, "f6 is null"); Objects.requireNonNull(f7, "f7 is null"); return Tuple.of(f1.apply(_1), f2.apply(_2), f3.apply(_3), f4.apply(_4), f5.apply(_5), f6.apply(_6), f7.apply(_7)); } /** * Maps the 1st component of this tuple to a new value. * * @param new type of the 1st component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 1st component */ public Tuple7 map1(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_1); return Tuple.of(u, _2, _3, _4, _5, _6, _7); } /** * Maps the 2nd component of this tuple to a new value. * * @param new type of the 2nd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 2nd component */ public Tuple7 map2(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_2); return Tuple.of(_1, u, _3, _4, _5, _6, _7); } /** * Maps the 3rd component of this tuple to a new value. * * @param new type of the 3rd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 3rd component */ public Tuple7 map3(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_3); return Tuple.of(_1, _2, u, _4, _5, _6, _7); } /** * Maps the 4th component of this tuple to a new value. * * @param new type of the 4th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 4th component */ public Tuple7 map4(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_4); return Tuple.of(_1, _2, _3, u, _5, _6, _7); } /** * Maps the 5th component of this tuple to a new value. * * @param new type of the 5th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 5th component */ public Tuple7 map5(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_5); return Tuple.of(_1, _2, _3, _4, u, _6, _7); } /** * Maps the 6th component of this tuple to a new value. * * @param new type of the 6th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 6th component */ public Tuple7 map6(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_6); return Tuple.of(_1, _2, _3, _4, _5, u, _7); } /** * Maps the 7th component of this tuple to a new value. * * @param new type of the 7th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 7th component */ public Tuple7 map7(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_7); return Tuple.of(_1, _2, _3, _4, _5, _6, u); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Function7 f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1, _2, _3, _4, _5, _6, _7); } @Override public Seq toSeq() { return List.of(_1, _2, _3, _4, _5, _6, _7); } /** * Append a value to this tuple. * * @param type of the value to append * @param t8 the value to append * @return a new Tuple with the value appended */ public Tuple8 append(T8 t8) { return Tuple.of(_1, _2, _3, _4, _5, _6, _7, t8); } /** * Concat a tuple's values to this tuple. * * @param the type of the 8th value in the tuple * @param tuple the tuple to concat * @return a new Tuple with the tuple values appended * @throws NullPointerException if {@code tuple} is null */ public Tuple8 concat(Tuple1 tuple) { Objects.requireNonNull(tuple, "tuple is null"); return Tuple.of(_1, _2, _3, _4, _5, _6, _7, tuple._1); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple7)) { return false; } else { final Tuple7 that = (Tuple7) o; return Objects.equals(this._1, that._1) && Objects.equals(this._2, that._2) && Objects.equals(this._3, that._3) && Objects.equals(this._4, that._4) && Objects.equals(this._5, that._5) && Objects.equals(this._6, that._6) && Objects.equals(this._7, that._7); } } @Override public int hashCode() { return Tuple.hash(_1, _2, _3, _4, _5, _6, _7); } @Override public String toString() { return "(" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/Tuple8.java000066400000000000000000000455651342074374400223670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import io.vavr.collection.List; import io.vavr.collection.Seq; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; /** * A tuple of 8 elements which can be seen as cartesian product of 8 components. * * @param type of the 1st element * @param type of the 2nd element * @param type of the 3rd element * @param type of the 4th element * @param type of the 5th element * @param type of the 6th element * @param type of the 7th element * @param type of the 8th element * @author Daniel Dietrich */ public final class Tuple8 implements Tuple, Comparable>, Serializable { private static final long serialVersionUID = 1L; /** * The 1st element of this tuple. */ public final T1 _1; /** * The 2nd element of this tuple. */ public final T2 _2; /** * The 3rd element of this tuple. */ public final T3 _3; /** * The 4th element of this tuple. */ public final T4 _4; /** * The 5th element of this tuple. */ public final T5 _5; /** * The 6th element of this tuple. */ public final T6 _6; /** * The 7th element of this tuple. */ public final T7 _7; /** * The 8th element of this tuple. */ public final T8 _8; /** * Constructs a tuple of 8 elements. * * @param t1 the 1st element * @param t2 the 2nd element * @param t3 the 3rd element * @param t4 the 4th element * @param t5 the 5th element * @param t6 the 6th element * @param t7 the 7th element * @param t8 the 8th element */ public Tuple8(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { this._1 = t1; this._2 = t2; this._3 = t3; this._4 = t4; this._5 = t5; this._6 = t6; this._7 = t7; this._8 = t8; } public static Comparator> comparator(Comparator t1Comp, Comparator t2Comp, Comparator t3Comp, Comparator t4Comp, Comparator t5Comp, Comparator t6Comp, Comparator t7Comp, Comparator t8Comp) { return (Comparator> & Serializable) (t1, t2) -> { final int check1 = t1Comp.compare(t1._1, t2._1); if (check1 != 0) { return check1; } final int check2 = t2Comp.compare(t1._2, t2._2); if (check2 != 0) { return check2; } final int check3 = t3Comp.compare(t1._3, t2._3); if (check3 != 0) { return check3; } final int check4 = t4Comp.compare(t1._4, t2._4); if (check4 != 0) { return check4; } final int check5 = t5Comp.compare(t1._5, t2._5); if (check5 != 0) { return check5; } final int check6 = t6Comp.compare(t1._6, t2._6); if (check6 != 0) { return check6; } final int check7 = t7Comp.compare(t1._7, t2._7); if (check7 != 0) { return check7; } final int check8 = t8Comp.compare(t1._8, t2._8); if (check8 != 0) { return check8; } // all components are equal return 0; }; } @SuppressWarnings("unchecked") private static , U2 extends Comparable, U3 extends Comparable, U4 extends Comparable, U5 extends Comparable, U6 extends Comparable, U7 extends Comparable, U8 extends Comparable> int compareTo(Tuple8 o1, Tuple8 o2) { final Tuple8 t1 = (Tuple8) o1; final Tuple8 t2 = (Tuple8) o2; final int check1 = t1._1.compareTo(t2._1); if (check1 != 0) { return check1; } final int check2 = t1._2.compareTo(t2._2); if (check2 != 0) { return check2; } final int check3 = t1._3.compareTo(t2._3); if (check3 != 0) { return check3; } final int check4 = t1._4.compareTo(t2._4); if (check4 != 0) { return check4; } final int check5 = t1._5.compareTo(t2._5); if (check5 != 0) { return check5; } final int check6 = t1._6.compareTo(t2._6); if (check6 != 0) { return check6; } final int check7 = t1._7.compareTo(t2._7); if (check7 != 0) { return check7; } final int check8 = t1._8.compareTo(t2._8); if (check8 != 0) { return check8; } // all components are equal return 0; } @Override public int arity() { return 8; } @Override public int compareTo(Tuple8 that) { return Tuple8.compareTo(this, that); } /** * Getter of the 1st element of this tuple. * * @return the 1st element of this Tuple. */ public T1 _1() { return _1; } /** * Sets the 1st element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 1st element of this Tuple. */ public Tuple8 update1(T1 value) { return new Tuple8<>(value, _2, _3, _4, _5, _6, _7, _8); } /** * Getter of the 2nd element of this tuple. * * @return the 2nd element of this Tuple. */ public T2 _2() { return _2; } /** * Sets the 2nd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 2nd element of this Tuple. */ public Tuple8 update2(T2 value) { return new Tuple8<>(_1, value, _3, _4, _5, _6, _7, _8); } /** * Getter of the 3rd element of this tuple. * * @return the 3rd element of this Tuple. */ public T3 _3() { return _3; } /** * Sets the 3rd element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 3rd element of this Tuple. */ public Tuple8 update3(T3 value) { return new Tuple8<>(_1, _2, value, _4, _5, _6, _7, _8); } /** * Getter of the 4th element of this tuple. * * @return the 4th element of this Tuple. */ public T4 _4() { return _4; } /** * Sets the 4th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 4th element of this Tuple. */ public Tuple8 update4(T4 value) { return new Tuple8<>(_1, _2, _3, value, _5, _6, _7, _8); } /** * Getter of the 5th element of this tuple. * * @return the 5th element of this Tuple. */ public T5 _5() { return _5; } /** * Sets the 5th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 5th element of this Tuple. */ public Tuple8 update5(T5 value) { return new Tuple8<>(_1, _2, _3, _4, value, _6, _7, _8); } /** * Getter of the 6th element of this tuple. * * @return the 6th element of this Tuple. */ public T6 _6() { return _6; } /** * Sets the 6th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 6th element of this Tuple. */ public Tuple8 update6(T6 value) { return new Tuple8<>(_1, _2, _3, _4, _5, value, _7, _8); } /** * Getter of the 7th element of this tuple. * * @return the 7th element of this Tuple. */ public T7 _7() { return _7; } /** * Sets the 7th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 7th element of this Tuple. */ public Tuple8 update7(T7 value) { return new Tuple8<>(_1, _2, _3, _4, _5, _6, value, _8); } /** * Getter of the 8th element of this tuple. * * @return the 8th element of this Tuple. */ public T8 _8() { return _8; } /** * Sets the 8th element of this tuple to the given {@code value}. * * @param value the new value * @return a copy of this tuple with a new value for the 8th element of this Tuple. */ public Tuple8 update8(T8 value) { return new Tuple8<>(_1, _2, _3, _4, _5, _6, _7, value); } /** * Maps the components of this tuple using a mapper function. * * @param mapper the mapper function * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @param new type of the 6th component * @param new type of the 7th component * @param new type of the 8th component * @return A new Tuple of same arity. * @throws NullPointerException if {@code mapper} is null */ public Tuple8 map(Function8> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapper.apply(_1, _2, _3, _4, _5, _6, _7, _8); } /** * Maps the components of this tuple using a mapper function for each component. * * @param f1 the mapper function of the 1st component * @param f2 the mapper function of the 2nd component * @param f3 the mapper function of the 3rd component * @param f4 the mapper function of the 4th component * @param f5 the mapper function of the 5th component * @param f6 the mapper function of the 6th component * @param f7 the mapper function of the 7th component * @param f8 the mapper function of the 8th component * @param new type of the 1st component * @param new type of the 2nd component * @param new type of the 3rd component * @param new type of the 4th component * @param new type of the 5th component * @param new type of the 6th component * @param new type of the 7th component * @param new type of the 8th component * @return A new Tuple of same arity. * @throws NullPointerException if one of the arguments is null */ public Tuple8 map(Function f1, Function f2, Function f3, Function f4, Function f5, Function f6, Function f7, Function f8) { Objects.requireNonNull(f1, "f1 is null"); Objects.requireNonNull(f2, "f2 is null"); Objects.requireNonNull(f3, "f3 is null"); Objects.requireNonNull(f4, "f4 is null"); Objects.requireNonNull(f5, "f5 is null"); Objects.requireNonNull(f6, "f6 is null"); Objects.requireNonNull(f7, "f7 is null"); Objects.requireNonNull(f8, "f8 is null"); return Tuple.of(f1.apply(_1), f2.apply(_2), f3.apply(_3), f4.apply(_4), f5.apply(_5), f6.apply(_6), f7.apply(_7), f8.apply(_8)); } /** * Maps the 1st component of this tuple to a new value. * * @param new type of the 1st component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 1st component */ public Tuple8 map1(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_1); return Tuple.of(u, _2, _3, _4, _5, _6, _7, _8); } /** * Maps the 2nd component of this tuple to a new value. * * @param new type of the 2nd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 2nd component */ public Tuple8 map2(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_2); return Tuple.of(_1, u, _3, _4, _5, _6, _7, _8); } /** * Maps the 3rd component of this tuple to a new value. * * @param new type of the 3rd component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 3rd component */ public Tuple8 map3(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_3); return Tuple.of(_1, _2, u, _4, _5, _6, _7, _8); } /** * Maps the 4th component of this tuple to a new value. * * @param new type of the 4th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 4th component */ public Tuple8 map4(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_4); return Tuple.of(_1, _2, _3, u, _5, _6, _7, _8); } /** * Maps the 5th component of this tuple to a new value. * * @param new type of the 5th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 5th component */ public Tuple8 map5(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_5); return Tuple.of(_1, _2, _3, _4, u, _6, _7, _8); } /** * Maps the 6th component of this tuple to a new value. * * @param new type of the 6th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 6th component */ public Tuple8 map6(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_6); return Tuple.of(_1, _2, _3, _4, _5, u, _7, _8); } /** * Maps the 7th component of this tuple to a new value. * * @param new type of the 7th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 7th component */ public Tuple8 map7(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_7); return Tuple.of(_1, _2, _3, _4, _5, _6, u, _8); } /** * Maps the 8th component of this tuple to a new value. * * @param new type of the 8th component * @param mapper A mapping function * @return a new tuple based on this tuple and substituted 8th component */ public Tuple8 map8(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final U u = mapper.apply(_8); return Tuple.of(_1, _2, _3, _4, _5, _6, _7, u); } /** * Transforms this tuple to an object of type U. * * @param f Transformation which creates a new object of type U based on this tuple's contents. * @param type of the transformation result * @return An object of type U * @throws NullPointerException if {@code f} is null */ public U apply(Function8 f) { Objects.requireNonNull(f, "f is null"); return f.apply(_1, _2, _3, _4, _5, _6, _7, _8); } @Override public Seq toSeq() { return List.of(_1, _2, _3, _4, _5, _6, _7, _8); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Tuple8)) { return false; } else { final Tuple8 that = (Tuple8) o; return Objects.equals(this._1, that._1) && Objects.equals(this._2, that._2) && Objects.equals(this._3, that._3) && Objects.equals(this._4, that._4) && Objects.equals(this._5, that._5) && Objects.equals(this._6, that._6) && Objects.equals(this._7, that._7) && Objects.equals(this._8, that._8); } } @Override public int hashCode() { return Tuple.hash(_1, _2, _3, _4, _5, _6, _7, _8); } @Override public String toString() { return "(" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + ", " + _8 + ")"; } }vavr-0.10.0/vavr/src-gen/main/java/io/vavr/collection/000077500000000000000000000000001342074374400224575ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/main/java/io/vavr/collection/ArrayType.java000066400000000000000000000473471342074374400252610ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import java.io.Serializable; import java.util.Collection; /** * Helper to replace reflective array access. * * @author Pap Lőrinc */ interface ArrayType { @SuppressWarnings("unchecked") static ArrayType obj() { return (ArrayType) ObjectArrayType.INSTANCE; } Class type(); int lengthOf(Object array); T getAt(Object array, int index); Object empty(); void setAt(Object array, int index, T value) throws ClassCastException; Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size); @SuppressWarnings("unchecked") static ArrayType of(Object array) { return of((Class) array.getClass().getComponentType()); } static ArrayType of(Class type) { return !type.isPrimitive() ? obj() : ofPrimitive(type); } @SuppressWarnings("unchecked") static ArrayType ofPrimitive(Class type) { if (boolean.class == type) { return (ArrayType) BooleanArrayType.INSTANCE; } else if (byte.class == type) { return (ArrayType) ByteArrayType.INSTANCE; } else if (char.class == type) { return (ArrayType) CharArrayType.INSTANCE; } else if (double.class == type) { return (ArrayType) DoubleArrayType.INSTANCE; } else if (float.class == type) { return (ArrayType) FloatArrayType.INSTANCE; } else if (int.class == type) { return (ArrayType) IntArrayType.INSTANCE; } else if (long.class == type) { return (ArrayType) LongArrayType.INSTANCE; } else if (short.class == type) { return (ArrayType) ShortArrayType.INSTANCE; } else { throw new IllegalArgumentException(String.valueOf(type)); } } default Object newInstance(int length) { return copy(empty(), length); } /** System.arrayCopy with same source and destination */ default Object copyRange(Object array, int from, int to) { final int length = to - from; return copy(array, length, from, 0, length); } /** Repeatedly group an array into equal sized sub-trees */ default Object grouped(Object array, int groupSize) { final int arrayLength = lengthOf(array); final Object results = obj().newInstance(1 + ((arrayLength - 1) / groupSize)); obj().setAt(results, 0, copyRange(array, 0, groupSize)); for (int start = groupSize, i = 1; start < arrayLength; i++) { final int nextLength = Math.min(groupSize, arrayLength - (i * groupSize)); obj().setAt(results, i, copyRange(array, start, start + nextLength)); start += nextLength; } return results; } /** clone the source and set the value at the given position */ default Object copyUpdate(Object array, int index, T element) { final Object copy = copy(array, index + 1); setAt(copy, index, element); return copy; } default Object copy(Object array, int minLength) { final int arrayLength = lengthOf(array); final int length = Math.max(arrayLength, minLength); return copy(array, length, 0, 0, arrayLength); } /** clone the source and keep everything after the index (pre-padding the values with null) */ default Object copyDrop(Object array, int index) { final int length = lengthOf(array); return copy(array, length, index, index, length - index); } /** clone the source and keep everything before and including the index */ default Object copyTake(Object array, int lastIndex) { return copyRange(array, 0, lastIndex + 1); } /** Create a single element array */ default Object asArray(T element) { final Object result = newInstance(1); setAt(result, 0, element); return result; } /** Store the content of an iterable in an array */ static Object[] asArray(java.util.Iterator it, int length) { final Object[] array = new Object[length]; for (int i = 0; i < length; i++) { array[i] = it.next(); } return array; } @SuppressWarnings("unchecked") static T asPrimitives(Class primitiveClass, Iterable values) { final Object[] array = Array.ofAll(values).toJavaArray(); final ArrayType type = of((Class) primitiveClass); final Object results = type.newInstance(array.length); for (int i = 0; i < array.length; i++) { type.setAt(results, i, (T) array[i]); } return (T) results; } final class BooleanArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final BooleanArrayType INSTANCE = new BooleanArrayType(); static final boolean[] EMPTY = new boolean[0]; private static boolean[] cast(Object array) { return (boolean[]) array; } @Override public Class type() { return boolean.class; } @Override public boolean[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Boolean getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Boolean value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new boolean[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final boolean[] result = new boolean[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class ByteArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final ByteArrayType INSTANCE = new ByteArrayType(); static final byte[] EMPTY = new byte[0]; private static byte[] cast(Object array) { return (byte[]) array; } @Override public Class type() { return byte.class; } @Override public byte[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Byte getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Byte value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new byte[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final byte[] result = new byte[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class CharArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final CharArrayType INSTANCE = new CharArrayType(); static final char[] EMPTY = new char[0]; private static char[] cast(Object array) { return (char[]) array; } @Override public Class type() { return char.class; } @Override public char[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Character getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Character value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new char[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final char[] result = new char[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class DoubleArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final DoubleArrayType INSTANCE = new DoubleArrayType(); static final double[] EMPTY = new double[0]; private static double[] cast(Object array) { return (double[]) array; } @Override public Class type() { return double.class; } @Override public double[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Double getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Double value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new double[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final double[] result = new double[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class FloatArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final FloatArrayType INSTANCE = new FloatArrayType(); static final float[] EMPTY = new float[0]; private static float[] cast(Object array) { return (float[]) array; } @Override public Class type() { return float.class; } @Override public float[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Float getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Float value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new float[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final float[] result = new float[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class IntArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final IntArrayType INSTANCE = new IntArrayType(); static final int[] EMPTY = new int[0]; private static int[] cast(Object array) { return (int[]) array; } @Override public Class type() { return int.class; } @Override public int[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Integer getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Integer value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new int[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final int[] result = new int[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class LongArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final LongArrayType INSTANCE = new LongArrayType(); static final long[] EMPTY = new long[0]; private static long[] cast(Object array) { return (long[]) array; } @Override public Class type() { return long.class; } @Override public long[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Long getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Long value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new long[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final long[] result = new long[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class ShortArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final ShortArrayType INSTANCE = new ShortArrayType(); static final short[] EMPTY = new short[0]; private static short[] cast(Object array) { return (short[]) array; } @Override public Class type() { return short.class; } @Override public short[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Short getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Short value) throws ClassCastException { if (value != null) { cast(array)[index] = value; } else { throw new ClassCastException(); } } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new short[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final short[] result = new short[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } final class ObjectArrayType implements ArrayType, Serializable { private static final long serialVersionUID = 1L; static final ObjectArrayType INSTANCE = new ObjectArrayType(); static final Object[] EMPTY = new Object[0]; private static Object[] cast(Object array) { return (Object[]) array; } @Override public Class type() { return Object.class; } @Override public Object[] empty() { return EMPTY; } @Override public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; } @Override public Object getAt(Object array, int index) { return cast(array)[index]; } @Override public void setAt(Object array, int index, Object value) { cast(array)[index] = value; } @Override public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { return (size > 0) ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size) : new Object[arraySize]; } private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) { final Object[] result = new Object[arraySize]; System.arraycopy(array, sourceFrom, result, destinationFrom, size); /* has to be near the object allocation to avoid zeroing out the array */ return result; } } }vavr-0.10.0/vavr/src-gen/test/000077500000000000000000000000001342074374400160515ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/test/java/000077500000000000000000000000001342074374400167725ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/test/java/io/000077500000000000000000000000001342074374400174015ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/test/java/io/vavr/000077500000000000000000000000001342074374400203575ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/test/java/io/vavr/APITest.java000066400000000000000000001512051342074374400224770ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.API.*; import static io.vavr.OutputTester.captureStdOut; import static io.vavr.Patterns.*; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import io.vavr.collection.List; import io.vavr.collection.Map; import io.vavr.concurrent.Future; import io.vavr.control.Option; import io.vavr.control.Try; import java.util.Arrays; import java.util.Comparator; import java.util.concurrent.Executors; import org.junit.Test; @SuppressWarnings("deprecation") public class APITest { @Test public void shouldNotBeInstantiable() { AssertionsExtensions.assertThat(API.class).isNotInstantiable(); } // -- shortcuts @Test public void shouldCompileTODOAndThrowDefaultMessageAtRuntime() { try { final String s = TODO(); fail("TODO() should throw. s: " + s); } catch(NotImplementedError err) { assertThat(err.getMessage()).isEqualTo("An implementation is missing."); } } @Test public void shouldCompileTODOAndThrowGivenMessageAtRuntime() { final String msg = "Don't try this in production!"; try { final String s = TODO(msg); fail("TODO(String) should throw. s: " + s); } catch(NotImplementedError err) { assertThat(err.getMessage()).isEqualTo(msg); } } @Test public void shouldCallprint_Object() { assertThat(captureStdOut(()->print("ok"))).isEqualTo("ok"); } @Test public void shouldCallprintf() { assertThat(captureStdOut(()->printf("%s", "ok"))).isEqualTo("ok"); } @Test public void shouldCallprintln_Object() { assertThat(captureStdOut(()->println("ok"))).isEqualTo("ok\n"); } @Test public void shouldCallprintln() { assertThat(captureStdOut(()->println())).isEqualTo("\n"); } // // Alias should return not null. // More specific test for each aliased class implemented in separate test class // @Test public void shouldFunction0ReturnNotNull() { assertThat(Function(() -> null)).isNotNull(); } @Test public void shouldCheckedFunction0ReturnNotNull() { assertThat(CheckedFunction(() -> null)).isNotNull(); } @Test public void shouldFunction1ReturnNotNull() { assertThat(Function((v1) -> null)).isNotNull(); } @Test public void shouldCheckedFunction1ReturnNotNull() { assertThat(CheckedFunction((v1) -> null)).isNotNull(); } @Test public void shouldFunction2ReturnNotNull() { assertThat(Function((v1, v2) -> null)).isNotNull(); } @Test public void shouldCheckedFunction2ReturnNotNull() { assertThat(CheckedFunction((v1, v2) -> null)).isNotNull(); } @Test public void shouldFunction3ReturnNotNull() { assertThat(Function((v1, v2, v3) -> null)).isNotNull(); } @Test public void shouldCheckedFunction3ReturnNotNull() { assertThat(CheckedFunction((v1, v2, v3) -> null)).isNotNull(); } @Test public void shouldFunction4ReturnNotNull() { assertThat(Function((v1, v2, v3, v4) -> null)).isNotNull(); } @Test public void shouldCheckedFunction4ReturnNotNull() { assertThat(CheckedFunction((v1, v2, v3, v4) -> null)).isNotNull(); } @Test public void shouldFunction5ReturnNotNull() { assertThat(Function((v1, v2, v3, v4, v5) -> null)).isNotNull(); } @Test public void shouldCheckedFunction5ReturnNotNull() { assertThat(CheckedFunction((v1, v2, v3, v4, v5) -> null)).isNotNull(); } @Test public void shouldFunction6ReturnNotNull() { assertThat(Function((v1, v2, v3, v4, v5, v6) -> null)).isNotNull(); } @Test public void shouldCheckedFunction6ReturnNotNull() { assertThat(CheckedFunction((v1, v2, v3, v4, v5, v6) -> null)).isNotNull(); } @Test public void shouldFunction7ReturnNotNull() { assertThat(Function((v1, v2, v3, v4, v5, v6, v7) -> null)).isNotNull(); } @Test public void shouldCheckedFunction7ReturnNotNull() { assertThat(CheckedFunction((v1, v2, v3, v4, v5, v6, v7) -> null)).isNotNull(); } @Test public void shouldFunction8ReturnNotNull() { assertThat(Function((v1, v2, v3, v4, v5, v6, v7, v8) -> null)).isNotNull(); } @Test public void shouldCheckedFunction8ReturnNotNull() { assertThat(CheckedFunction((v1, v2, v3, v4, v5, v6, v7, v8) -> null)).isNotNull(); } @Test public void shouldUnchecked0ReturnNonCheckedFunction() { assertThat(unchecked(() -> null)).isInstanceOf(Function0.class); } @Test public void shouldUnchecked1ReturnNonCheckedFunction() { assertThat(unchecked((v1) -> null)).isInstanceOf(Function1.class); } @Test public void shouldUnchecked2ReturnNonCheckedFunction() { assertThat(unchecked((v1, v2) -> null)).isInstanceOf(Function2.class); } @Test public void shouldUnchecked3ReturnNonCheckedFunction() { assertThat(unchecked((v1, v2, v3) -> null)).isInstanceOf(Function3.class); } @Test public void shouldUnchecked4ReturnNonCheckedFunction() { assertThat(unchecked((v1, v2, v3, v4) -> null)).isInstanceOf(Function4.class); } @Test public void shouldUnchecked5ReturnNonCheckedFunction() { assertThat(unchecked((v1, v2, v3, v4, v5) -> null)).isInstanceOf(Function5.class); } @Test public void shouldUnchecked6ReturnNonCheckedFunction() { assertThat(unchecked((v1, v2, v3, v4, v5, v6) -> null)).isInstanceOf(Function6.class); } @Test public void shouldUnchecked7ReturnNonCheckedFunction() { assertThat(unchecked((v1, v2, v3, v4, v5, v6, v7) -> null)).isInstanceOf(Function7.class); } @Test public void shouldUnchecked8ReturnNonCheckedFunction() { assertThat(unchecked((v1, v2, v3, v4, v5, v6, v7, v8) -> null)).isInstanceOf(Function8.class); } @Test public void shouldTuple0ReturnNotNull() { assertThat(Tuple()).isNotNull(); } @Test public void shouldTuple1ReturnNotNull() { assertThat(Tuple(1)).isNotNull(); } @Test public void shouldTuple2ReturnNotNull() { assertThat(Tuple(1, 2)).isNotNull(); } @Test public void shouldTuple3ReturnNotNull() { assertThat(Tuple(1, 2, 3)).isNotNull(); } @Test public void shouldTuple4ReturnNotNull() { assertThat(Tuple(1, 2, 3, 4)).isNotNull(); } @Test public void shouldTuple5ReturnNotNull() { assertThat(Tuple(1, 2, 3, 4, 5)).isNotNull(); } @Test public void shouldTuple6ReturnNotNull() { assertThat(Tuple(1, 2, 3, 4, 5, 6)).isNotNull(); } @Test public void shouldTuple7ReturnNotNull() { assertThat(Tuple(1, 2, 3, 4, 5, 6, 7)).isNotNull(); } @Test public void shouldTuple8ReturnNotNull() { assertThat(Tuple(1, 2, 3, 4, 5, 6, 7, 8)).isNotNull(); } @Test public void shouldRightReturnNotNull() { assertThat(Right(null)).isNotNull(); } @Test public void shouldLeftReturnNotNull() { assertThat(Left(null)).isNotNull(); } @Test public void shouldFutureWithSupplierReturnNotNull() { final Future future = Future(() -> 1).await(); assertThat(future).isNotNull(); assertThat(future.isSuccess()).isTrue(); } @Test public void shouldFutureWithinExecutorWithSupplierReturnNotNull() { final Future future = Future(Executors.newSingleThreadExecutor(), () -> 1).await(); assertThat(future).isNotNull(); assertThat(future.isSuccess()).isTrue(); } @Test public void shouldFutureWithValueReturnNotNull() { final Future future = Future(1).await(); assertThat(future).isNotNull(); assertThat(future.isSuccess()).isTrue(); } @Test public void shouldFutureWithinExecutorWithValueReturnNotNull() { final Future future = Future(Executors.newSingleThreadExecutor(), 1).await(); assertThat(future).isNotNull(); assertThat(future.isSuccess()).isTrue(); } @Test public void shouldLazyReturnNotNull() { assertThat(Lazy(() -> 1)).isNotNull(); } @Test public void shouldOptionReturnNotNull() { assertThat(Option(1)).isNotNull(); } @Test public void shouldSomeReturnNotNull() { assertThat(Some(1)).isNotNull(); } @Test public void shouldNoneReturnNotNull() { assertThat(None()).isNotNull(); } @Test public void shouldTryReturnNotNull() { final Try t = Try(() -> 1); assertThat(t).isNotNull(); assertThat(t.isSuccess()).isTrue(); } @Test public void shouldSuccessReturnNotNull() { final Try t = Success(1); assertThat(t).isNotNull(); assertThat(t.isSuccess()).isTrue(); } @Test public void shouldFailureReturnNotNull() { final Try t = Failure(new Error()); assertThat(t).isNotNull(); assertThat(t.isFailure()).isTrue(); } @Test public void shouldValidReturnNotNull() { assertThat(Valid(1)).isNotNull(); } @Test public void shouldInvalidReturnNotNull() { assertThat(Invalid(new Error())).isNotNull(); } @Test public void shouldCharReturnNotNull() { assertThat((Iterable) CharSeq('1')).isNotNull(); } @Test public void shouldCharArrayReturnNotNull() { assertThat((Iterable) CharSeq('1', '2', '3')).isNotNull(); } @Test public void shouldCharSeqReturnNotNull() { assertThat((Iterable) CharSeq("123")).isNotNull(); } @Test public void shouldEmptyArrayReturnNotNull() { assertThat(Array()).isNotNull(); } @Test public void shouldArrayWithSingleReturnNotNull() { assertThat(Array('1')).isNotNull(); } @Test public void shouldArrayWithVarArgReturnNotNull() { assertThat(Array('1', '2', '3')).isNotNull(); } @Test public void shouldEmptyVectorReturnNotNull() { assertThat(Vector()).isNotNull(); } @Test public void shouldVectorWithSingleReturnNotNull() { assertThat(Vector('1')).isNotNull(); } @Test public void shouldVectorWithVarArgReturnNotNull() { assertThat(Vector('1', '2', '3')).isNotNull(); } @Test public void shouldEmptyListReturnNotNull() { assertThat(List()).isNotNull(); } @Test public void shouldListWithSingleReturnNotNull() { assertThat(List('1')).isNotNull(); } @Test public void shouldListWithVarArgReturnNotNull() { assertThat(List('1', '2', '3')).isNotNull(); } @Test public void shouldEmptyStreamReturnNotNull() { assertThat(Stream()).isNotNull(); } @Test public void shouldStreamWithSingleReturnNotNull() { assertThat(Stream('1')).isNotNull(); } @Test public void shouldStreamWithVarArgReturnNotNull() { assertThat(Stream('1', '2', '3')).isNotNull(); } @Test public void shouldEmptyQueueReturnNotNull() { assertThat(Queue()).isNotNull(); } @Test public void shouldQueueWithSingleReturnNotNull() { assertThat(Queue('1')).isNotNull(); } @Test public void shouldQueueWithVarArgReturnNotNull() { assertThat(Queue('1', '2', '3')).isNotNull(); } @Test public void shouldEmptyLinkedSetReturnNotNull() { assertThat(LinkedSet()).isNotNull(); } @Test public void shouldLinkedSetWithSingleReturnNotNull() { assertThat(LinkedSet('1')).isNotNull(); } @Test public void shouldLinkedSetWithVarArgReturnNotNull() { assertThat(LinkedSet('1', '2', '3')).isNotNull(); } @Test public void shouldEmptySetReturnNotNull() { assertThat(Set()).isNotNull(); } @Test public void shouldSetWithSingleReturnNotNull() { assertThat(Set('1')).isNotNull(); } @Test public void shouldSetWithVarArgReturnNotNull() { assertThat(Set('1', '2', '3')).isNotNull(); } @Test public void shouldEmptySeqReturnNotNull() { assertThat(Seq()).isNotNull(); } @Test public void shouldSeqWithSingleReturnNotNull() { assertThat(Seq('1')).isNotNull(); } @Test public void shouldSeqWithVarArgReturnNotNull() { assertThat(Seq('1', '2', '3')).isNotNull(); } @Test public void shouldEmptyIndexedSeqReturnNotNull() { assertThat(IndexedSeq()).isNotNull(); } @Test public void shouldIndexedSeqWithSingleReturnNotNull() { assertThat(IndexedSeq('1')).isNotNull(); } @Test public void shouldIndexedSeqWithVarArgReturnNotNull() { assertThat(IndexedSeq('1', '2', '3')).isNotNull(); } @Test public void shouldEmptySortedSetReturnNotNull() { assertThat(SortedSet()).isNotNull(); } @Test public void shouldEmptySortedSetWithComparatorReturnNotNull() { assertThat(SortedSet((Comparator) Character::compareTo)).isNotNull(); } @Test public void shouldSortedSetWithSingleReturnNotNull() { assertThat(SortedSet('1')).isNotNull(); } @Test public void shouldSortedSetWithSingleAndComparatorReturnNotNull() { assertThat(SortedSet(Character::compareTo, '1')).isNotNull(); } @Test public void shouldSortedSetWithVarArgReturnNotNull() { assertThat(SortedSet('1', '2', '3')).isNotNull(); } @Test public void shouldSortedSetWithVarArgAndComparatorReturnNotNull() { assertThat(SortedSet((Comparator) Character::compareTo, '1', '2', '3')).isNotNull(); } @Test public void shouldEmptyPriorityQueueReturnNotNull() { assertThat(PriorityQueue()).isNotNull(); } @Test public void shouldEmptyPriorityQueueWithComparatorReturnNotNull() { assertThat(PriorityQueue((Comparator) Character::compareTo)).isNotNull(); } @Test public void shouldPriorityQueueWithSingleReturnNotNull() { assertThat(PriorityQueue('1')).isNotNull(); } @Test public void shouldPriorityQueueWithSingleAndComparatorReturnNotNull() { assertThat(PriorityQueue(Character::compareTo, '1')).isNotNull(); } @Test public void shouldPriorityQueueWithVarArgReturnNotNull() { assertThat(PriorityQueue('1', '2', '3')).isNotNull(); } @Test public void shouldPriorityQueueWithVarArgAndComparatorReturnNotNull() { assertThat(PriorityQueue((Comparator) Character::compareTo, '1', '2', '3')).isNotNull(); } @Test public void shouldEmptyLinkedMapReturnNotNull() { assertThat(LinkedMap()).isNotNull(); } @Test public void shouldLinkedMapFromSingleReturnNotNull() { assertThat(LinkedMap(1, '1')).isNotNull(); } @Test public void shouldLinkedMapFromTuplesReturnNotNull() { assertThat(LinkedMap(Tuple(1, '1'), Tuple(2, '2'), Tuple(3, '3'))).isNotNull(); } @Test public void shouldLinkedMapFromPairsReturnNotNull() { assertThat(LinkedMap(1, '1', 2, '2', 3, '3')).isNotNull(); } @Test public void shouldCreateLinkedMapFrom1Pairs() { Map map = LinkedMap(1, 2); assertThat(map.apply(1)).isEqualTo(2); } @Test public void shouldCreateLinkedMapFrom2Pairs() { Map map = LinkedMap(1, 2, 2, 4); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); } @Test public void shouldCreateLinkedMapFrom3Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); } @Test public void shouldCreateLinkedMapFrom4Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6, 4, 8); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); } @Test public void shouldCreateLinkedMapFrom5Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); } @Test public void shouldCreateLinkedMapFrom6Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); } @Test public void shouldCreateLinkedMapFrom7Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); } @Test public void shouldCreateLinkedMapFrom8Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); } @Test public void shouldCreateLinkedMapFrom9Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); assertThat(map.apply(9)).isEqualTo(18); } @Test public void shouldCreateLinkedMapFrom10Pairs() { Map map = LinkedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18, 10, 20); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); assertThat(map.apply(9)).isEqualTo(18); assertThat(map.apply(10)).isEqualTo(20); } @Test public void shouldEmptyMapReturnNotNull() { assertThat(Map()).isNotNull(); } @Test public void shouldMapFromSingleReturnNotNull() { assertThat(Map(1, '1')).isNotNull(); } @Test public void shouldMapFromTuplesReturnNotNull() { assertThat(Map(Tuple(1, '1'), Tuple(2, '2'), Tuple(3, '3'))).isNotNull(); } @Test public void shouldMapFromPairsReturnNotNull() { assertThat(Map(1, '1', 2, '2', 3, '3')).isNotNull(); } @Test public void shouldCreateMapFrom1Pairs() { Map map = Map(1, 2); assertThat(map.apply(1)).isEqualTo(2); } @Test public void shouldCreateMapFrom2Pairs() { Map map = Map(1, 2, 2, 4); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); } @Test public void shouldCreateMapFrom3Pairs() { Map map = Map(1, 2, 2, 4, 3, 6); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); } @Test public void shouldCreateMapFrom4Pairs() { Map map = Map(1, 2, 2, 4, 3, 6, 4, 8); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); } @Test public void shouldCreateMapFrom5Pairs() { Map map = Map(1, 2, 2, 4, 3, 6, 4, 8, 5, 10); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); } @Test public void shouldCreateMapFrom6Pairs() { Map map = Map(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); } @Test public void shouldCreateMapFrom7Pairs() { Map map = Map(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); } @Test public void shouldCreateMapFrom8Pairs() { Map map = Map(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); } @Test public void shouldCreateMapFrom9Pairs() { Map map = Map(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); assertThat(map.apply(9)).isEqualTo(18); } @Test public void shouldCreateMapFrom10Pairs() { Map map = Map(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18, 10, 20); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); assertThat(map.apply(9)).isEqualTo(18); assertThat(map.apply(10)).isEqualTo(20); } @Test public void shouldEmptySortedMapReturnNotNull() { assertThat(SortedMap()).isNotNull(); } @Test public void shouldSortedMapFromSingleReturnNotNull() { assertThat(SortedMap(1, '1')).isNotNull(); } @Test public void shouldSortedMapFromTuplesReturnNotNull() { assertThat(SortedMap(Tuple(1, '1'), Tuple(2, '2'), Tuple(3, '3'))).isNotNull(); } @Test public void shouldSortedMapFromPairsReturnNotNull() { assertThat(SortedMap(1, '1', 2, '2', 3, '3')).isNotNull(); } @Test public void shouldCreateSortedMapFrom1Pairs() { Map map = SortedMap(1, 2); assertThat(map.apply(1)).isEqualTo(2); } @Test public void shouldCreateSortedMapFrom2Pairs() { Map map = SortedMap(1, 2, 2, 4); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); } @Test public void shouldCreateSortedMapFrom3Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); } @Test public void shouldCreateSortedMapFrom4Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6, 4, 8); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); } @Test public void shouldCreateSortedMapFrom5Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); } @Test public void shouldCreateSortedMapFrom6Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); } @Test public void shouldCreateSortedMapFrom7Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); } @Test public void shouldCreateSortedMapFrom8Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); } @Test public void shouldCreateSortedMapFrom9Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); assertThat(map.apply(9)).isEqualTo(18); } @Test public void shouldCreateSortedMapFrom10Pairs() { Map map = SortedMap(1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18, 10, 20); assertThat(map.apply(1)).isEqualTo(2); assertThat(map.apply(2)).isEqualTo(4); assertThat(map.apply(3)).isEqualTo(6); assertThat(map.apply(4)).isEqualTo(8); assertThat(map.apply(5)).isEqualTo(10); assertThat(map.apply(6)).isEqualTo(12); assertThat(map.apply(7)).isEqualTo(14); assertThat(map.apply(8)).isEqualTo(16); assertThat(map.apply(9)).isEqualTo(18); assertThat(map.apply(10)).isEqualTo(20); } @Test public void shouldEmptySortedMapFromComparatorReturnNotNull() { assertThat(SortedMap(Integer::compareTo)).isNotNull(); } @Test public void shouldSortedMapFromSingleAndComparatorReturnNotNull() { assertThat(SortedMap(Integer::compareTo, 1, '1')).isNotNull(); } @Test public void shouldSortedMapFromTuplesAndComparatorReturnNotNull() { assertThat(SortedMap((Comparator)Integer::compareTo, Tuple(1, '1'), Tuple(2, '2'), Tuple(3, '3'))).isNotNull(); } // -- run @Test public void shouldRunUnitAndReturnVoid() { int[] i = { 0 }; Void nothing = run(() -> i[0]++); assertThat(nothing).isNull(); assertThat(i[0]).isEqualTo(1); } // -- For @Test public void shouldIterateFor1UsingSimpleYield() { final List list = List.of(1, 2, 3); final List actual = For(list).yield().toList(); assertThat(actual).isEqualTo(list); } @Test public void shouldIterateForList1() { final List result = For( List.of(1, 2, 3) ).yield(i1 -> i1).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 1)); assertThat(result.head()).isEqualTo(1); assertThat(result.last()).isEqualTo(3 * 1); } @Test public void shouldIterateForList2() { final List result = For( List.of(1, 2, 3), List.of(1, 2, 3) ).yield((i1, i2) -> i1 + i2).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 2)); assertThat(result.head()).isEqualTo(2); assertThat(result.last()).isEqualTo(3 * 2); } @Test public void shouldIterateForList3() { final List result = For( List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3) ).yield((i1, i2, i3) -> i1 + i2 + i3).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 3)); assertThat(result.head()).isEqualTo(3); assertThat(result.last()).isEqualTo(3 * 3); } @Test public void shouldIterateForList4() { final List result = For( List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3) ).yield((i1, i2, i3, i4) -> i1 + i2 + i3 + i4).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 4)); assertThat(result.head()).isEqualTo(4); assertThat(result.last()).isEqualTo(3 * 4); } @Test public void shouldIterateForList5() { final List result = For( List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3) ).yield((i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 5)); assertThat(result.head()).isEqualTo(5); assertThat(result.last()).isEqualTo(3 * 5); } @Test public void shouldIterateForList6() { final List result = For( List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3) ).yield((i1, i2, i3, i4, i5, i6) -> i1 + i2 + i3 + i4 + i5 + i6).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 6)); assertThat(result.head()).isEqualTo(6); assertThat(result.last()).isEqualTo(3 * 6); } @Test public void shouldIterateForList7() { final List result = For( List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3) ).yield((i1, i2, i3, i4, i5, i6, i7) -> i1 + i2 + i3 + i4 + i5 + i6 + i7).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 7)); assertThat(result.head()).isEqualTo(7); assertThat(result.last()).isEqualTo(3 * 7); } @Test public void shouldIterateForList8() { final List result = For( List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3), List.of(1, 2, 3) ).yield((i1, i2, i3, i4, i5, i6, i7, i8) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8).toList(); assertThat(result.length()).isEqualTo((int) Math.pow(3, 8)); assertThat(result.head()).isEqualTo(8); assertThat(result.last()).isEqualTo(3 * 8); } @Test public void shouldIterateForOption1() { final Option result = For( Option.of(1) ).yield(i1 -> i1); assertThat(result.get()).isEqualTo(1); } @Test public void shouldIterateForOption2() { final Option result = For( Option.of(1), Option.of(2) ).yield((i1, i2) -> i1 + i2); assertThat(result.get()).isEqualTo(3); } @Test public void shouldIterateForOption3() { final Option result = For( Option.of(1), Option.of(2), Option.of(3) ).yield((i1, i2, i3) -> i1 + i2 + i3); assertThat(result.get()).isEqualTo(6); } @Test public void shouldIterateForOption4() { final Option result = For( Option.of(1), Option.of(2), Option.of(3), Option.of(4) ).yield((i1, i2, i3, i4) -> i1 + i2 + i3 + i4); assertThat(result.get()).isEqualTo(10); } @Test public void shouldIterateForOption5() { final Option result = For( Option.of(1), Option.of(2), Option.of(3), Option.of(4), Option.of(5) ).yield((i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5); assertThat(result.get()).isEqualTo(15); } @Test public void shouldIterateForOption6() { final Option result = For( Option.of(1), Option.of(2), Option.of(3), Option.of(4), Option.of(5), Option.of(6) ).yield((i1, i2, i3, i4, i5, i6) -> i1 + i2 + i3 + i4 + i5 + i6); assertThat(result.get()).isEqualTo(21); } @Test public void shouldIterateForOption7() { final Option result = For( Option.of(1), Option.of(2), Option.of(3), Option.of(4), Option.of(5), Option.of(6), Option.of(7) ).yield((i1, i2, i3, i4, i5, i6, i7) -> i1 + i2 + i3 + i4 + i5 + i6 + i7); assertThat(result.get()).isEqualTo(28); } @Test public void shouldIterateForOption8() { final Option result = For( Option.of(1), Option.of(2), Option.of(3), Option.of(4), Option.of(5), Option.of(6), Option.of(7), Option.of(8) ).yield((i1, i2, i3, i4, i5, i6, i7, i8) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8); assertThat(result.get()).isEqualTo(36); } @Test public void shouldIterateForFuture1() { final Future result = For( Future.of(() -> 1) ).yield(i1 -> i1); assertThat(result.get()).isEqualTo(1); } @Test public void shouldIterateForFuture2() { final Future result = For( Future.of(() -> 1), Future.of(() -> 2) ).yield((i1, i2) -> i1 + i2); assertThat(result.get()).isEqualTo(3); } @Test public void shouldIterateForFuture3() { final Future result = For( Future.of(() -> 1), Future.of(() -> 2), Future.of(() -> 3) ).yield((i1, i2, i3) -> i1 + i2 + i3); assertThat(result.get()).isEqualTo(6); } @Test public void shouldIterateForFuture4() { final Future result = For( Future.of(() -> 1), Future.of(() -> 2), Future.of(() -> 3), Future.of(() -> 4) ).yield((i1, i2, i3, i4) -> i1 + i2 + i3 + i4); assertThat(result.get()).isEqualTo(10); } @Test public void shouldIterateForFuture5() { final Future result = For( Future.of(() -> 1), Future.of(() -> 2), Future.of(() -> 3), Future.of(() -> 4), Future.of(() -> 5) ).yield((i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5); assertThat(result.get()).isEqualTo(15); } @Test public void shouldIterateForFuture6() { final Future result = For( Future.of(() -> 1), Future.of(() -> 2), Future.of(() -> 3), Future.of(() -> 4), Future.of(() -> 5), Future.of(() -> 6) ).yield((i1, i2, i3, i4, i5, i6) -> i1 + i2 + i3 + i4 + i5 + i6); assertThat(result.get()).isEqualTo(21); } @Test public void shouldIterateForFuture7() { final Future result = For( Future.of(() -> 1), Future.of(() -> 2), Future.of(() -> 3), Future.of(() -> 4), Future.of(() -> 5), Future.of(() -> 6), Future.of(() -> 7) ).yield((i1, i2, i3, i4, i5, i6, i7) -> i1 + i2 + i3 + i4 + i5 + i6 + i7); assertThat(result.get()).isEqualTo(28); } @Test public void shouldIterateForFuture8() { final Future result = For( Future.of(() -> 1), Future.of(() -> 2), Future.of(() -> 3), Future.of(() -> 4), Future.of(() -> 5), Future.of(() -> 6), Future.of(() -> 7), Future.of(() -> 8) ).yield((i1, i2, i3, i4, i5, i6, i7, i8) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8); assertThat(result.get()).isEqualTo(36); } @Test public void shouldIterateForTry1() { final Try result = For( Try.of(() -> 1) ).yield(i1 -> i1); assertThat(result.get()).isEqualTo(1); } @Test public void shouldIterateForTry2() { final Try result = For( Try.of(() -> 1), Try.of(() -> 2) ).yield((i1, i2) -> i1 + i2); assertThat(result.get()).isEqualTo(3); } @Test public void shouldIterateForTry3() { final Try result = For( Try.of(() -> 1), Try.of(() -> 2), Try.of(() -> 3) ).yield((i1, i2, i3) -> i1 + i2 + i3); assertThat(result.get()).isEqualTo(6); } @Test public void shouldIterateForTry4() { final Try result = For( Try.of(() -> 1), Try.of(() -> 2), Try.of(() -> 3), Try.of(() -> 4) ).yield((i1, i2, i3, i4) -> i1 + i2 + i3 + i4); assertThat(result.get()).isEqualTo(10); } @Test public void shouldIterateForTry5() { final Try result = For( Try.of(() -> 1), Try.of(() -> 2), Try.of(() -> 3), Try.of(() -> 4), Try.of(() -> 5) ).yield((i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5); assertThat(result.get()).isEqualTo(15); } @Test public void shouldIterateForTry6() { final Try result = For( Try.of(() -> 1), Try.of(() -> 2), Try.of(() -> 3), Try.of(() -> 4), Try.of(() -> 5), Try.of(() -> 6) ).yield((i1, i2, i3, i4, i5, i6) -> i1 + i2 + i3 + i4 + i5 + i6); assertThat(result.get()).isEqualTo(21); } @Test public void shouldIterateForTry7() { final Try result = For( Try.of(() -> 1), Try.of(() -> 2), Try.of(() -> 3), Try.of(() -> 4), Try.of(() -> 5), Try.of(() -> 6), Try.of(() -> 7) ).yield((i1, i2, i3, i4, i5, i6, i7) -> i1 + i2 + i3 + i4 + i5 + i6 + i7); assertThat(result.get()).isEqualTo(28); } @Test public void shouldIterateForTry8() { final Try result = For( Try.of(() -> 1), Try.of(() -> 2), Try.of(() -> 3), Try.of(() -> 4), Try.of(() -> 5), Try.of(() -> 6), Try.of(() -> 7), Try.of(() -> 8) ).yield((i1, i2, i3, i4, i5, i6, i7, i8) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8); assertThat(result.get()).isEqualTo(36); } @Test public void shouldIterateNestedFor() { final List result = For(Arrays.asList(1, 2), i -> For(List.of('a', 'b')).yield(c -> i + ":" + c)).toList(); assertThat(result).isEqualTo(List.of("1:a", "1:b", "2:a", "2:b")); } // -- Match @Test public void shouldReturnSomeWhenApplyingCaseGivenPredicateAndSupplier() { final Match.Case _case = Case($(ignored -> true), ignored -> 1); assertThat(_case.isDefinedAt(null)).isTrue(); assertThat(_case.apply(null)).isEqualTo(1); } @Test public void shouldReturnNoneWhenApplyingCaseGivenPredicateAndSupplier() { assertThat(Case($(ignored -> false), ignored -> 1).isDefinedAt(null)).isFalse(); } @Test public void shouldReturnSomeWhenApplyingCaseGivenPredicateAndValue() { final Match.Case _case = Case($(ignored -> true), 1); assertThat(_case.isDefinedAt(null)).isTrue(); assertThat(_case.apply(null)).isEqualTo(1); } @Test public void shouldReturnNoneWhenApplyingCaseGivenPredicateAndValue() { assertThat(Case($(ignored -> false), 1).isDefinedAt(null)).isFalse(); } // -- Match patterns static class ClzMatch {} static class ClzMatch1 extends ClzMatch {} static class ClzMatch2 extends ClzMatch {} @Test public void shouldMatchPattern1() { final Tuple1 tuple = Tuple.of(1); final String func = Match(tuple).of( Case($Tuple1($(0)), (m1) -> "fail"), Case($Tuple1($()), (m1) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple1($(0)), () -> "fail"), Case($Tuple1($()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple1($(0)), "fail"), Case($Tuple1($()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern1.of(ClzMatch1.class, $(), t -> Tuple.of(null)), "fail"), Case(Match.Pattern1.of(ClzMatch2.class, $(), t -> Tuple.of(null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } @Test public void shouldMatchPattern2() { final Tuple2 tuple = Tuple.of(1, 1); final String func = Match(tuple).of( Case($Tuple2($(0), $()), (m1, m2) -> "fail"), Case($Tuple2($(), $()), (m1, m2) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple2($(0), $()), () -> "fail"), Case($Tuple2($(), $()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple2($(0), $()), "fail"), Case($Tuple2($(), $()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern2.of(ClzMatch1.class, $(), $(), t -> Tuple.of(null, null)), "fail"), Case(Match.Pattern2.of(ClzMatch2.class, $(), $(), t -> Tuple.of(null, null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } @Test public void shouldMatchPattern3() { final Tuple3 tuple = Tuple.of(1, 1, 1); final String func = Match(tuple).of( Case($Tuple3($(0), $(), $()), (m1, m2, m3) -> "fail"), Case($Tuple3($(), $(), $()), (m1, m2, m3) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple3($(0), $(), $()), () -> "fail"), Case($Tuple3($(), $(), $()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple3($(0), $(), $()), "fail"), Case($Tuple3($(), $(), $()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern3.of(ClzMatch1.class, $(), $(), $(), t -> Tuple.of(null, null, null)), "fail"), Case(Match.Pattern3.of(ClzMatch2.class, $(), $(), $(), t -> Tuple.of(null, null, null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } @Test public void shouldMatchPattern4() { final Tuple4 tuple = Tuple.of(1, 1, 1, 1); final String func = Match(tuple).of( Case($Tuple4($(0), $(), $(), $()), (m1, m2, m3, m4) -> "fail"), Case($Tuple4($(), $(), $(), $()), (m1, m2, m3, m4) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple4($(0), $(), $(), $()), () -> "fail"), Case($Tuple4($(), $(), $(), $()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple4($(0), $(), $(), $()), "fail"), Case($Tuple4($(), $(), $(), $()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern4.of(ClzMatch1.class, $(), $(), $(), $(), t -> Tuple.of(null, null, null, null)), "fail"), Case(Match.Pattern4.of(ClzMatch2.class, $(), $(), $(), $(), t -> Tuple.of(null, null, null, null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } @Test public void shouldMatchPattern5() { final Tuple5 tuple = Tuple.of(1, 1, 1, 1, 1); final String func = Match(tuple).of( Case($Tuple5($(0), $(), $(), $(), $()), (m1, m2, m3, m4, m5) -> "fail"), Case($Tuple5($(), $(), $(), $(), $()), (m1, m2, m3, m4, m5) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple5($(0), $(), $(), $(), $()), () -> "fail"), Case($Tuple5($(), $(), $(), $(), $()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple5($(0), $(), $(), $(), $()), "fail"), Case($Tuple5($(), $(), $(), $(), $()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern5.of(ClzMatch1.class, $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null)), "fail"), Case(Match.Pattern5.of(ClzMatch2.class, $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } @Test public void shouldMatchPattern6() { final Tuple6 tuple = Tuple.of(1, 1, 1, 1, 1, 1); final String func = Match(tuple).of( Case($Tuple6($(0), $(), $(), $(), $(), $()), (m1, m2, m3, m4, m5, m6) -> "fail"), Case($Tuple6($(), $(), $(), $(), $(), $()), (m1, m2, m3, m4, m5, m6) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple6($(0), $(), $(), $(), $(), $()), () -> "fail"), Case($Tuple6($(), $(), $(), $(), $(), $()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple6($(0), $(), $(), $(), $(), $()), "fail"), Case($Tuple6($(), $(), $(), $(), $(), $()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern6.of(ClzMatch1.class, $(), $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null, null)), "fail"), Case(Match.Pattern6.of(ClzMatch2.class, $(), $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null, null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } @Test public void shouldMatchPattern7() { final Tuple7 tuple = Tuple.of(1, 1, 1, 1, 1, 1, 1); final String func = Match(tuple).of( Case($Tuple7($(0), $(), $(), $(), $(), $(), $()), (m1, m2, m3, m4, m5, m6, m7) -> "fail"), Case($Tuple7($(), $(), $(), $(), $(), $(), $()), (m1, m2, m3, m4, m5, m6, m7) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple7($(0), $(), $(), $(), $(), $(), $()), () -> "fail"), Case($Tuple7($(), $(), $(), $(), $(), $(), $()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple7($(0), $(), $(), $(), $(), $(), $()), "fail"), Case($Tuple7($(), $(), $(), $(), $(), $(), $()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern7.of(ClzMatch1.class, $(), $(), $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null, null, null)), "fail"), Case(Match.Pattern7.of(ClzMatch2.class, $(), $(), $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null, null, null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } @Test public void shouldMatchPattern8() { final Tuple8 tuple = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1); final String func = Match(tuple).of( Case($Tuple8($(0), $(), $(), $(), $(), $(), $(), $()), (m1, m2, m3, m4, m5, m6, m7, m8) -> "fail"), Case($Tuple8($(), $(), $(), $(), $(), $(), $(), $()), (m1, m2, m3, m4, m5, m6, m7, m8) -> "okFunc") ); assertThat(func).isEqualTo("okFunc"); final String supp = Match(tuple).of( Case($Tuple8($(0), $(), $(), $(), $(), $(), $(), $()), () -> "fail"), Case($Tuple8($(), $(), $(), $(), $(), $(), $(), $()), () -> "okSupp") ); assertThat(supp).isEqualTo("okSupp"); final String val = Match(tuple).of( Case($Tuple8($(0), $(), $(), $(), $(), $(), $(), $()), "fail"), Case($Tuple8($(), $(), $(), $(), $(), $(), $(), $()), "okVal") ); assertThat(val).isEqualTo("okVal"); final ClzMatch c = new ClzMatch2(); final String match = Match(c).of( Case(Match.Pattern8.of(ClzMatch1.class, $(), $(), $(), $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null, null, null, null)), "fail"), Case(Match.Pattern8.of(ClzMatch2.class, $(), $(), $(), $(), $(), $(), $(), $(), t -> Tuple.of(null, null, null, null, null, null, null, null)), "okMatch") ); assertThat(match).isEqualTo("okMatch"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction0Test.java000066400000000000000000000167611342074374400252110ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction0Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference() { return null; } } final Type type = new Type(); assertThat(CheckedFunction0.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction0.lift(() -> { while(true); })).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction0 f = () -> null; assertThat(f.arity()).isEqualTo(0); } @Test public void shouldConstant() throws Throwable { final CheckedFunction0 f = CheckedFunction0.constant(6); assertThat(f.apply()).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction0 f = () -> null; final CheckedFunction0 curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction0 f = () -> null; final CheckedFunction1 tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction0 f = () -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction0 f = () -> integer.getAndIncrement(); final CheckedFunction0 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(); // should return memoized value of second apply() assertThat(memo.apply()).isEqualTo(expected); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction0 f = () -> null; final CheckedFunction0 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction0 f = () -> null; final CheckedFunction0 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldRecover() { final AtomicInteger integer = new AtomicInteger(); CheckedFunction0 digest = () -> MessageDigest.getInstance(integer.get() == 0 ? "MD5" : "Unknown"); Function0 recover = digest.recover(throwable -> () -> null); MessageDigest md5 = recover.apply(); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); integer.incrementAndGet(); assertThat(recover.apply()).isNull(); } @Test public void shouldRecoverNonNull() { final AtomicInteger integer = new AtomicInteger(); CheckedFunction0 digest = () -> MessageDigest.getInstance(integer.get() == 0 ? "MD5" : "Unknown"); Function0 recover = digest.recover(throwable -> null); MessageDigest md5 = recover.apply(); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); integer.incrementAndGet(); Try unknown = Function0.liftTry(recover).apply(); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { CheckedFunction0 digest = () -> MessageDigest.getInstance("MD5"); Function0 unchecked = digest.unchecked(); MessageDigest md5 = unchecked.apply(); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldThrowCheckedExceptionWhenUnchecked() { CheckedFunction0 digest = () -> MessageDigest.getInstance("Unknown"); Function0 unchecked = digest.unchecked(); unchecked.apply(); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final AtomicInteger integer = new AtomicInteger(); CheckedFunction0 digest = () -> MessageDigest.getInstance(integer.get() == 0 ? "MD5" : "Unknown"); Function0> liftTry = CheckedFunction0.liftTry(digest); Try md5 = liftTry.apply(); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); integer.incrementAndGet(); Try unknown = liftTry.apply(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction0 recurrent1 = () -> 11; @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply()).isEqualTo(11); } @Test public void shouldComposeWithAndThen() { final CheckedFunction0 f = () -> null; final CheckedFunction1 after = o -> null; final CheckedFunction0 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction0 wideFunction = () -> "Zero args"; final CheckedFunction0 narrowFunction = CheckedFunction0.narrow(wideFunction); assertThat(narrowFunction.apply()).isEqualTo("Zero args"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction1Test.java000066400000000000000000000207411342074374400252030ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction1Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1) { return null; } } final Type type = new Type(); assertThat(CheckedFunction1.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction1.lift((o1) -> { while(true); })).isNotNull(); } @Test public void shouldCreateIdentityFunction() throws Throwable { final CheckedFunction1 identity = CheckedFunction1.identity(); final String s = "test"; assertThat(identity.apply(s)).isEqualTo(s); } @Test public void shouldGetArity() { final CheckedFunction1 f = (o1) -> null; assertThat(f.arity()).isEqualTo(1); } @Test public void shouldConstant() throws Throwable { final CheckedFunction1 f = CheckedFunction1.constant(6); assertThat(f.apply(1)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction1 f = (o1) -> null; final CheckedFunction1 curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction1 f = (o1) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction1 f = (o1) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction1 f = (i1) -> i1 + integer.getAndIncrement(); final CheckedFunction1 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1); // should return memoized value of second apply() assertThat(memo.apply(1)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 )).isEqualTo(2 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 )).isEqualTo(2 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction1 f = (i1) -> null; final CheckedFunction1 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction1 f = (i1) -> null; final CheckedFunction1 memo = f.memoized(); assertThat(memo.apply(null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction1 f = (i1) -> null; final CheckedFunction1 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction1 digest = (s1) -> MessageDigest.getInstance(s1); @Test public void shouldRecover() { final Function1 recover = digest.recover(throwable -> (s1) -> null); final MessageDigest md5 = recover.apply("MD5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("Unknown")).isNull(); } @Test public void shouldRecoverNonNull() { final Function1 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("MD5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function1.liftTry(recover).apply("Unknown"); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function1 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("MD5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function1 unchecked = digest.unchecked(); unchecked.apply("Unknown"); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function1> liftTry = CheckedFunction1.liftTry(digest); final Try md5 = liftTry.apply("MD5"); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("Unknown"); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction1 recurrent1 = (i1) -> i1 <= 0 ? i1 : CheckedFunction1Test.recurrent2.apply(i1 - 1) + 1; private static final CheckedFunction1 recurrent2 = CheckedFunction1Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11)).isEqualTo(11); assertThat(recurrent1.apply(22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction1 f = (o1) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction1 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldComposeWithCompose() { final CheckedFunction1 f = (o1) -> null; final CheckedFunction1 before = o -> null; final CheckedFunction1 composed = f.compose(before); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction1 wideFunction = (o1) -> String.format("Numbers are: %s", o1); final CheckedFunction1 narrowFunction = CheckedFunction1.narrow(wideFunction); assertThat(narrowFunction.apply(1)).isEqualTo("Numbers are: 1"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction2Test.java000066400000000000000000000210061342074374400251770ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction2Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2) { return null; } } final Type type = new Type(); assertThat(CheckedFunction2.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction2.lift((o1, o2) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() throws Throwable { final CheckedFunction2 f = (o1, o2) -> null; assertThat(f.apply(null)).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction2 f = (o1, o2) -> null; assertThat(f.arity()).isEqualTo(2); } @Test public void shouldConstant() throws Throwable { final CheckedFunction2 f = CheckedFunction2.constant(6); assertThat(f.apply(1, 2)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction2 f = (o1, o2) -> null; final Function1> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction2 f = (o1, o2) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction2 f = (o1, o2) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction2 f = (i1, i2) -> i1 + i2 + integer.getAndIncrement(); final CheckedFunction2 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2); // should return memoized value of second apply() assertThat(memo.apply(1, 2)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 )).isEqualTo(2 + 3 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 )).isEqualTo(2 + 3 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction2 f = (i1, i2) -> null; final CheckedFunction2 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction2 f = (i1, i2) -> null; final CheckedFunction2 memo = f.memoized(); assertThat(memo.apply(null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction2 f = (i1, i2) -> null; final CheckedFunction2 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction2 digest = (s1, s2) -> MessageDigest.getInstance(s1 + s2); @Test public void shouldRecover() { final Function2 recover = digest.recover(throwable -> (s1, s2) -> null); final MessageDigest md5 = recover.apply("M", "D5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("U", "nknown")).isNull(); } @Test public void shouldRecoverNonNull() { final Function2 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("M", "D5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function2.liftTry(recover).apply("U", "nknown"); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function2 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("M", "D5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function2 unchecked = digest.unchecked(); unchecked.apply("U", "nknown"); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function2> liftTry = CheckedFunction2.liftTry(digest); final Try md5 = liftTry.apply("M", "D5"); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("U", "nknown"); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction2 recurrent1 = (i1, i2) -> i1 <= 0 ? i1 : CheckedFunction2Test.recurrent2.apply(i1 - 1, i2) + 1; private static final CheckedFunction2 recurrent2 = CheckedFunction2Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction2 f = (o1, o2) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction2 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction2 wideFunction = (o1, o2) -> String.format("Numbers are: %s, %s", o1, o2); final CheckedFunction2 narrowFunction = CheckedFunction2.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2)).isEqualTo("Numbers are: 1, 2"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction3Test.java000066400000000000000000000217351342074374400252110ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction3Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3) { return null; } } final Type type = new Type(); assertThat(CheckedFunction3.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction3.lift((o1, o2, o3) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() throws Throwable { final CheckedFunction3 f = (o1, o2, o3) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction3 f = (o1, o2, o3) -> null; assertThat(f.arity()).isEqualTo(3); } @Test public void shouldConstant() throws Throwable { final CheckedFunction3 f = CheckedFunction3.constant(6); assertThat(f.apply(1, 2, 3)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction3 f = (o1, o2, o3) -> null; final Function1>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction3 f = (o1, o2, o3) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction3 f = (o1, o2, o3) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction3 f = (i1, i2, i3) -> i1 + i2 + i3 + integer.getAndIncrement(); final CheckedFunction3 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 )).isEqualTo(2 + 3 + 4 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 )).isEqualTo(2 + 3 + 4 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction3 f = (i1, i2, i3) -> null; final CheckedFunction3 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction3 f = (i1, i2, i3) -> null; final CheckedFunction3 memo = f.memoized(); assertThat(memo.apply(null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction3 f = (i1, i2, i3) -> null; final CheckedFunction3 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction3 digest = (s1, s2, s3) -> MessageDigest.getInstance(s1 + s2 + s3); @Test public void shouldRecover() { final Function3 recover = digest.recover(throwable -> (s1, s2, s3) -> null); final MessageDigest md5 = recover.apply("M", "D", "5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("U", "n", "known")).isNull(); } @Test public void shouldRecoverNonNull() { final Function3 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("M", "D", "5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function3.liftTry(recover).apply("U", "n", "known"); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function3 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("M", "D", "5"); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function3 unchecked = digest.unchecked(); unchecked.apply("U", "n", "known"); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function3> liftTry = CheckedFunction3.liftTry(digest); final Try md5 = liftTry.apply("M", "D", "5"); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("U", "n", "known"); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction3 recurrent1 = (i1, i2, i3) -> i1 <= 0 ? i1 : CheckedFunction3Test.recurrent2.apply(i1 - 1, i2, i3) + 1; private static final CheckedFunction3 recurrent2 = CheckedFunction3Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction3 f = (o1, o2, o3) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction3 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction3 wideFunction = (o1, o2, o3) -> String.format("Numbers are: %s, %s, %s", o1, o2, o3); final CheckedFunction3 narrowFunction = CheckedFunction3.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3)).isEqualTo("Numbers are: 1, 2, 3"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction4Test.java000066400000000000000000000226721342074374400252130ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction4Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4) { return null; } } final Type type = new Type(); assertThat(CheckedFunction4.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction4.lift((o1, o2, o3, o4) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() throws Throwable { final CheckedFunction4 f = (o1, o2, o3, o4) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction4 f = (o1, o2, o3, o4) -> null; assertThat(f.arity()).isEqualTo(4); } @Test public void shouldConstant() throws Throwable { final CheckedFunction4 f = CheckedFunction4.constant(6); assertThat(f.apply(1, 2, 3, 4)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction4 f = (o1, o2, o3, o4) -> null; final Function1>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction4 f = (o1, o2, o3, o4) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction4 f = (o1, o2, o3, o4) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction4 f = (i1, i2, i3, i4) -> i1 + i2 + i3 + i4 + integer.getAndIncrement(); final CheckedFunction4 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 )).isEqualTo(2 + 3 + 4 + 5 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 )).isEqualTo(2 + 3 + 4 + 5 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction4 f = (i1, i2, i3, i4) -> null; final CheckedFunction4 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction4 f = (i1, i2, i3, i4) -> null; final CheckedFunction4 memo = f.memoized(); assertThat(memo.apply(null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction4 f = (i1, i2, i3, i4) -> null; final CheckedFunction4 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction4 digest = (s1, s2, s3, s4) -> MessageDigest.getInstance(s1 + s2 + s3 + s4); @Test public void shouldRecover() { final Function4 recover = digest.recover(throwable -> (s1, s2, s3, s4) -> null); final MessageDigest md5 = recover.apply("M", "D", "5", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("U", "n", "k", "nown")).isNull(); } @Test public void shouldRecoverNonNull() { final Function4 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("M", "D", "5", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function4.liftTry(recover).apply("U", "n", "k", "nown"); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function4 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("M", "D", "5", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function4 unchecked = digest.unchecked(); unchecked.apply("U", "n", "k", "nown"); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function4> liftTry = CheckedFunction4.liftTry(digest); final Try md5 = liftTry.apply("M", "D", "5", ""); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("U", "n", "k", "nown"); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction4 recurrent1 = (i1, i2, i3, i4) -> i1 <= 0 ? i1 : CheckedFunction4Test.recurrent2.apply(i1 - 1, i2, i3, i4) + 1; private static final CheckedFunction4 recurrent2 = CheckedFunction4Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction4 f = (o1, o2, o3, o4) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction4 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction4 wideFunction = (o1, o2, o3, o4) -> String.format("Numbers are: %s, %s, %s, %s", o1, o2, o3, o4); final CheckedFunction4 narrowFunction = CheckedFunction4.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4)).isEqualTo("Numbers are: 1, 2, 3, 4"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction5Test.java000066400000000000000000000236351342074374400252140ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction5Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5) { return null; } } final Type type = new Type(); assertThat(CheckedFunction5.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction5.lift((o1, o2, o3, o4, o5) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() throws Throwable { final CheckedFunction5 f = (o1, o2, o3, o4, o5) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction5 f = (o1, o2, o3, o4, o5) -> null; assertThat(f.arity()).isEqualTo(5); } @Test public void shouldConstant() throws Throwable { final CheckedFunction5 f = CheckedFunction5.constant(6); assertThat(f.apply(1, 2, 3, 4, 5)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction5 f = (o1, o2, o3, o4, o5) -> null; final Function1>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction5 f = (o1, o2, o3, o4, o5) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction5 f = (o1, o2, o3, o4, o5) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction5 f = (i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5 + integer.getAndIncrement(); final CheckedFunction5 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction5 f = (i1, i2, i3, i4, i5) -> null; final CheckedFunction5 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction5 f = (i1, i2, i3, i4, i5) -> null; final CheckedFunction5 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction5 f = (i1, i2, i3, i4, i5) -> null; final CheckedFunction5 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction5 digest = (s1, s2, s3, s4, s5) -> MessageDigest.getInstance(s1 + s2 + s3 + s4 + s5); @Test public void shouldRecover() { final Function5 recover = digest.recover(throwable -> (s1, s2, s3, s4, s5) -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("U", "n", "k", "n", "own")).isNull(); } @Test public void shouldRecoverNonNull() { final Function5 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function5.liftTry(recover).apply("U", "n", "k", "n", "own"); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function5 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("M", "D", "5", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function5 unchecked = digest.unchecked(); unchecked.apply("U", "n", "k", "n", "own"); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function5> liftTry = CheckedFunction5.liftTry(digest); final Try md5 = liftTry.apply("M", "D", "5", "", ""); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("U", "n", "k", "n", "own"); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction5 recurrent1 = (i1, i2, i3, i4, i5) -> i1 <= 0 ? i1 : CheckedFunction5Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5) + 1; private static final CheckedFunction5 recurrent2 = CheckedFunction5Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction5 f = (o1, o2, o3, o4, o5) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction5 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction5 wideFunction = (o1, o2, o3, o4, o5) -> String.format("Numbers are: %s, %s, %s, %s, %s", o1, o2, o3, o4, o5); final CheckedFunction5 narrowFunction = CheckedFunction5.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5)).isEqualTo("Numbers are: 1, 2, 3, 4, 5"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction6Test.java000066400000000000000000000246061342074374400252140ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction6Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) { return null; } } final Type type = new Type(); assertThat(CheckedFunction6.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction6.lift((o1, o2, o3, o4, o5, o6) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() throws Throwable { final CheckedFunction6 f = (o1, o2, o3, o4, o5, o6) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction6 f = (o1, o2, o3, o4, o5, o6) -> null; assertThat(f.arity()).isEqualTo(6); } @Test public void shouldConstant() throws Throwable { final CheckedFunction6 f = CheckedFunction6.constant(6); assertThat(f.apply(1, 2, 3, 4, 5, 6)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction6 f = (o1, o2, o3, o4, o5, o6) -> null; final Function1>>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction6 f = (o1, o2, o3, o4, o5, o6) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction6 f = (o1, o2, o3, o4, o5, o6) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction6 f = (i1, i2, i3, i4, i5, i6) -> i1 + i2 + i3 + i4 + i5 + i6 + integer.getAndIncrement(); final CheckedFunction6 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5, 6); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5, 6)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction6 f = (i1, i2, i3, i4, i5, i6) -> null; final CheckedFunction6 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction6 f = (i1, i2, i3, i4, i5, i6) -> null; final CheckedFunction6 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction6 f = (i1, i2, i3, i4, i5, i6) -> null; final CheckedFunction6 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction6 digest = (s1, s2, s3, s4, s5, s6) -> MessageDigest.getInstance(s1 + s2 + s3 + s4 + s5 + s6); @Test public void shouldRecover() { final Function6 recover = digest.recover(throwable -> (s1, s2, s3, s4, s5, s6) -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("U", "n", "k", "n", "o", "wn")).isNull(); } @Test public void shouldRecoverNonNull() { final Function6 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function6.liftTry(recover).apply("U", "n", "k", "n", "o", "wn"); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function6 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("M", "D", "5", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function6 unchecked = digest.unchecked(); unchecked.apply("U", "n", "k", "n", "o", "wn"); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function6> liftTry = CheckedFunction6.liftTry(digest); final Try md5 = liftTry.apply("M", "D", "5", "", "", ""); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("U", "n", "k", "n", "o", "wn"); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction6 recurrent1 = (i1, i2, i3, i4, i5, i6) -> i1 <= 0 ? i1 : CheckedFunction6Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5, i6) + 1; private static final CheckedFunction6 recurrent2 = CheckedFunction6Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11, 11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction6 f = (o1, o2, o3, o4, o5, o6) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction6 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction6 wideFunction = (o1, o2, o3, o4, o5, o6) -> String.format("Numbers are: %s, %s, %s, %s, %s, %s", o1, o2, o3, o4, o5, o6); final CheckedFunction6 narrowFunction = CheckedFunction6.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5, 6)).isEqualTo("Numbers are: 1, 2, 3, 4, 5, 6"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction7Test.java000066400000000000000000000255651342074374400252220ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction7Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7) { return null; } } final Type type = new Type(); assertThat(CheckedFunction7.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction7.lift((o1, o2, o3, o4, o5, o6, o7) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() throws Throwable { final CheckedFunction7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; assertThat(f.arity()).isEqualTo(7); } @Test public void shouldConstant() throws Throwable { final CheckedFunction7 f = CheckedFunction7.constant(6); assertThat(f.apply(1, 2, 3, 4, 5, 6, 7)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; final Function1>>>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction7 f = (i1, i2, i3, i4, i5, i6, i7) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + integer.getAndIncrement(); final CheckedFunction7 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5, 6, 7); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5, 6, 7)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction7 f = (i1, i2, i3, i4, i5, i6, i7) -> null; final CheckedFunction7 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction7 f = (i1, i2, i3, i4, i5, i6, i7) -> null; final CheckedFunction7 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction7 f = (i1, i2, i3, i4, i5, i6, i7) -> null; final CheckedFunction7 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction7 digest = (s1, s2, s3, s4, s5, s6, s7) -> MessageDigest.getInstance(s1 + s2 + s3 + s4 + s5 + s6 + s7); @Test public void shouldRecover() { final Function7 recover = digest.recover(throwable -> (s1, s2, s3, s4, s5, s6, s7) -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("U", "n", "k", "n", "o", "w", "n")).isNull(); } @Test public void shouldRecoverNonNull() { final Function7 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function7.liftTry(recover).apply("U", "n", "k", "n", "o", "w", "n"); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function7 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("M", "D", "5", "", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function7 unchecked = digest.unchecked(); unchecked.apply("U", "n", "k", "n", "o", "w", "n"); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function7> liftTry = CheckedFunction7.liftTry(digest); final Try md5 = liftTry.apply("M", "D", "5", "", "", "", ""); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("U", "n", "k", "n", "o", "w", "n"); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction7 recurrent1 = (i1, i2, i3, i4, i5, i6, i7) -> i1 <= 0 ? i1 : CheckedFunction7Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5, i6, i7) + 1; private static final CheckedFunction7 recurrent2 = CheckedFunction7Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11, 11, 11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction7 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction7 wideFunction = (o1, o2, o3, o4, o5, o6, o7) -> String.format("Numbers are: %s, %s, %s, %s, %s, %s, %s", o1, o2, o3, o4, o5, o6, o7); final CheckedFunction7 narrowFunction = CheckedFunction7.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5, 6, 7)).isEqualTo("Numbers are: 1, 2, 3, 4, 5, 6, 7"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/CheckedFunction8Test.java000066400000000000000000000265521342074374400252200ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class CheckedFunction8Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8) { return null; } } final Type type = new Type(); assertThat(CheckedFunction8.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(CheckedFunction8.lift((o1, o2, o3, o4, o5, o6, o7, o8) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() throws Throwable { final CheckedFunction8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final CheckedFunction8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; assertThat(f.arity()).isEqualTo(8); } @Test public void shouldConstant() throws Throwable { final CheckedFunction8 f = CheckedFunction8.constant(6); assertThat(f.apply(1, 2, 3, 4, 5, 6, 7, 8)).isEqualTo(6); } @Test public void shouldCurry() { final CheckedFunction8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; final Function1>>>>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final CheckedFunction8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; final CheckedFunction1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final CheckedFunction8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() throws Throwable { final AtomicInteger integer = new AtomicInteger(); final CheckedFunction8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + integer.getAndIncrement(); final CheckedFunction8 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5, 6, 7, 8); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5, 6, 7, 8)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() throws Throwable { final CheckedFunction8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> null; final CheckedFunction8 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() throws Throwable { final CheckedFunction8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> null; final CheckedFunction8 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final CheckedFunction8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> null; final CheckedFunction8 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } private static final CheckedFunction8 digest = (s1, s2, s3, s4, s5, s6, s7, s8) -> MessageDigest.getInstance(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8); @Test public void shouldRecover() { final Function8 recover = digest.recover(throwable -> (s1, s2, s3, s4, s5, s6, s7, s8) -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", "", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); assertThat(recover.apply("U", "n", "k", "n", "o", "w", "n", "")).isNull(); } @Test public void shouldRecoverNonNull() { final Function8 recover = digest.recover(throwable -> null); final MessageDigest md5 = recover.apply("M", "D", "5", "", "", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); final Try unknown = Function8.liftTry(recover).apply("U", "n", "k", "n", "o", "w", "n", ""); assertThat(unknown).isNotNull(); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull().isInstanceOf(NullPointerException.class); assertThat(unknown.getCause().getMessage()).isNotEmpty().isEqualToIgnoringCase("recover return null for class java.security.NoSuchAlgorithmException: Unknown MessageDigest not available"); } @Test public void shouldUncheckedWork() { final Function8 unchecked = digest.unchecked(); final MessageDigest md5 = unchecked.apply("M", "D", "5", "", "", "", "", ""); assertThat(md5).isNotNull(); assertThat(md5.getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.getDigestLength()).isEqualTo(16); } @Test(expected = NoSuchAlgorithmException.class) public void shouldUncheckedThrowIllegalState() { final Function8 unchecked = digest.unchecked(); unchecked.apply("U", "n", "k", "n", "o", "w", "n", ""); // Look ma, we throw an undeclared checked exception! } @Test public void shouldLiftTryPartialFunction() { final Function8> liftTry = CheckedFunction8.liftTry(digest); final Try md5 = liftTry.apply("M", "D", "5", "", "", "", "", ""); assertThat(md5.isSuccess()).isTrue(); assertThat(md5.get()).isNotNull(); assertThat(md5.get().getAlgorithm()).isEqualToIgnoringCase("MD5"); assertThat(md5.get().getDigestLength()).isEqualTo(16); final Try unknown = liftTry.apply("U", "n", "k", "n", "o", "w", "n", ""); assertThat(unknown.isFailure()).isTrue(); assertThat(unknown.getCause()).isNotNull(); assertThat(unknown.getCause().getMessage()).isEqualToIgnoringCase("Unknown MessageDigest not available"); } private static final CheckedFunction8 recurrent1 = (i1, i2, i3, i4, i5, i6, i7, i8) -> i1 <= 0 ? i1 : CheckedFunction8Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5, i6, i7, i8) + 1; private static final CheckedFunction8 recurrent2 = CheckedFunction8Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() throws Throwable { assertThat(recurrent1.apply(11, 11, 11, 11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final CheckedFunction8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; final CheckedFunction1 after = o -> null; final CheckedFunction8 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow() throws Throwable{ final CheckedFunction8 wideFunction = (o1, o2, o3, o4, o5, o6, o7, o8) -> String.format("Numbers are: %s, %s, %s, %s, %s, %s, %s, %s", o1, o2, o3, o4, o5, o6, o7, o8); final CheckedFunction8 narrowFunction = CheckedFunction8.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5, 6, 7, 8)).isEqualTo("Numbers are: 1, 2, 3, 4, 5, 6, 7, 8"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function0Test.java000066400000000000000000000113651342074374400237350ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function0Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference() { return null; } } final Type type = new Type(); assertThat(Function0.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function0.lift(() -> { while(true); })).isNotNull(); } @Test public void shouldGetValue() { final String s = "test"; final Function0 supplier = () -> s; assertThat(supplier.get()).isEqualTo(s); } @Test public void shouldGetArity() { final Function0 f = () -> null; assertThat(f.arity()).isEqualTo(0); } @Test public void shouldConstant() { final Function0 f = Function0.constant(6); assertThat(f.apply()).isEqualTo(6); } @Test public void shouldCurry() { final Function0 f = () -> null; final Function0 curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function0 f = () -> null; final Function1 tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function0 f = () -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function0 f = () -> integer.getAndIncrement(); final Function0 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(); // should return memoized value of second apply() assertThat(memo.apply()).isEqualTo(expected); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function0 f = () -> null; final Function0 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function0 f = () -> null; final Function0 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function0 divByZero = () -> 10 / integer.get(); Function0> divByZeroTry = Function0.liftTry(divByZero); Try res = divByZeroTry.apply(); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function0 recurrent1 = () -> 11; @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply()).isEqualTo(11); } @Test public void shouldComposeWithAndThen() { final Function0 f = () -> null; final Function1 after = o -> null; final Function0 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function0 wideFunction = () -> "Zero args"; final Function0 narrowFunction = Function0.narrow(wideFunction); assertThat(narrowFunction.apply()).isEqualTo("Zero args"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function1Test.java000066400000000000000000000155131342074374400237350ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function1Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1) { return null; } } final Type type = new Type(); assertThat(Function1.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function1.lift((o1) -> { while(true); })).isNotNull(); } @Test public void shouldCreateIdentityFunction() { final Function1 identity = Function1.identity(); final String s = "test"; assertThat(identity.apply(s)).isEqualTo(s); } @Test public void shouldGetArity() { final Function1 f = (o1) -> null; assertThat(f.arity()).isEqualTo(1); } @Test public void shouldConstant() { final Function1 f = Function1.constant(6); assertThat(f.apply(1)).isEqualTo(6); } @Test public void shouldCurry() { final Function1 f = (o1) -> null; final Function1 curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function1 f = (o1) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function1 f = (o1) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function1 f = (i1) -> i1 + integer.getAndIncrement(); final Function1 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1); // should return memoized value of second apply() assertThat(memo.apply(1)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 )).isEqualTo(2 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 )).isEqualTo(2 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function1 f = (i1) -> null; final Function1 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function1 f = (i1) -> null; final Function1 memo = f.memoized(); assertThat(memo.apply(null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function1 f = (i1) -> null; final Function1 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldThrowOnPartialWithNullPredicate() { final Function1 f = String::valueOf; assertThatThrownBy(() -> f.partial(null)) .isInstanceOf(NullPointerException.class) .hasMessage("isDefinedAt is null"); } @Test public void shouldCreatePartialFunction() { final Function1 f = String::valueOf; final PartialFunction pf = f.partial(i -> i % 2 == 0); assertThat(pf.isDefinedAt(0)).isTrue(); assertThat(pf.isDefinedAt(1)).isFalse(); assertThat(pf.apply(0)).isEqualTo("0"); assertThat(pf.apply(1)).isEqualTo("1"); // it is valid to return a value, even if isDefinedAt returns false } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function1 divByZero = (i1) -> 10 / integer.get(); Function1> divByZeroTry = Function1.liftTry(divByZero); Try res = divByZeroTry.apply(0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function1 recurrent1 = (i1) -> i1 <= 0 ? i1 : Function1Test.recurrent2.apply(i1 - 1) + 1; private static final Function1 recurrent2 = Function1Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11)).isEqualTo(11); assertThat(recurrent1.apply(22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function1 f = (o1) -> null; final Function1 after = o -> null; final Function1 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldComposeWithCompose() { final Function1 f = (o1) -> null; final Function1 before = o -> null; final Function1 composed = f.compose(before); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function1 wideFunction = (o1) -> String.format("Numbers are: %s", o1); final Function1 narrowFunction = Function1.narrow(wideFunction); assertThat(narrowFunction.apply(1)).isEqualTo("Numbers are: 1"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function2Test.java000066400000000000000000000140141342074374400237310ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function2Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2) { return null; } } final Type type = new Type(); assertThat(Function2.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function2.lift((o1, o2) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() { final Function2 f = (o1, o2) -> null; assertThat(f.apply(null)).isNotNull(); } @Test public void shouldGetArity() { final Function2 f = (o1, o2) -> null; assertThat(f.arity()).isEqualTo(2); } @Test public void shouldConstant() { final Function2 f = Function2.constant(6); assertThat(f.apply(1, 2)).isEqualTo(6); } @Test public void shouldCurry() { final Function2 f = (o1, o2) -> null; final Function1> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function2 f = (o1, o2) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function2 f = (o1, o2) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function2 f = (i1, i2) -> i1 + i2 + integer.getAndIncrement(); final Function2 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2); // should return memoized value of second apply() assertThat(memo.apply(1, 2)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 )).isEqualTo(2 + 3 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 )).isEqualTo(2 + 3 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function2 f = (i1, i2) -> null; final Function2 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function2 f = (i1, i2) -> null; final Function2 memo = f.memoized(); assertThat(memo.apply(null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function2 f = (i1, i2) -> null; final Function2 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function2 divByZero = (i1, i2) -> 10 / integer.get(); Function2> divByZeroTry = Function2.liftTry(divByZero); Try res = divByZeroTry.apply(0, 0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1, 2); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function2 recurrent1 = (i1, i2) -> i1 <= 0 ? i1 : Function2Test.recurrent2.apply(i1 - 1, i2) + 1; private static final Function2 recurrent2 = Function2Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function2 f = (o1, o2) -> null; final Function1 after = o -> null; final Function2 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function2 wideFunction = (o1, o2) -> String.format("Numbers are: %s, %s", o1, o2); final Function2 narrowFunction = Function2.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2)).isEqualTo("Numbers are: 1, 2"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function3Test.java000066400000000000000000000146421342074374400237410ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function3Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3) { return null; } } final Type type = new Type(); assertThat(Function3.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function3.lift((o1, o2, o3) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() { final Function3 f = (o1, o2, o3) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); } @Test public void shouldGetArity() { final Function3 f = (o1, o2, o3) -> null; assertThat(f.arity()).isEqualTo(3); } @Test public void shouldConstant() { final Function3 f = Function3.constant(6); assertThat(f.apply(1, 2, 3)).isEqualTo(6); } @Test public void shouldCurry() { final Function3 f = (o1, o2, o3) -> null; final Function1>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function3 f = (o1, o2, o3) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function3 f = (o1, o2, o3) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function3 f = (i1, i2, i3) -> i1 + i2 + i3 + integer.getAndIncrement(); final Function3 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 )).isEqualTo(2 + 3 + 4 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 )).isEqualTo(2 + 3 + 4 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function3 f = (i1, i2, i3) -> null; final Function3 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function3 f = (i1, i2, i3) -> null; final Function3 memo = f.memoized(); assertThat(memo.apply(null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function3 f = (i1, i2, i3) -> null; final Function3 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function3 divByZero = (i1, i2, i3) -> 10 / integer.get(); Function3> divByZeroTry = Function3.liftTry(divByZero); Try res = divByZeroTry.apply(0, 0, 0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1, 2, 3); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function3 recurrent1 = (i1, i2, i3) -> i1 <= 0 ? i1 : Function3Test.recurrent2.apply(i1 - 1, i2, i3) + 1; private static final Function3 recurrent2 = Function3Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function3 f = (o1, o2, o3) -> null; final Function1 after = o -> null; final Function3 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function3 wideFunction = (o1, o2, o3) -> String.format("Numbers are: %s, %s, %s", o1, o2, o3); final Function3 narrowFunction = Function3.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3)).isEqualTo("Numbers are: 1, 2, 3"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function4Test.java000066400000000000000000000154761342074374400237500ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function4Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4) { return null; } } final Type type = new Type(); assertThat(Function4.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function4.lift((o1, o2, o3, o4) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() { final Function4 f = (o1, o2, o3, o4) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final Function4 f = (o1, o2, o3, o4) -> null; assertThat(f.arity()).isEqualTo(4); } @Test public void shouldConstant() { final Function4 f = Function4.constant(6); assertThat(f.apply(1, 2, 3, 4)).isEqualTo(6); } @Test public void shouldCurry() { final Function4 f = (o1, o2, o3, o4) -> null; final Function1>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function4 f = (o1, o2, o3, o4) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function4 f = (o1, o2, o3, o4) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function4 f = (i1, i2, i3, i4) -> i1 + i2 + i3 + i4 + integer.getAndIncrement(); final Function4 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 )).isEqualTo(2 + 3 + 4 + 5 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 )).isEqualTo(2 + 3 + 4 + 5 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function4 f = (i1, i2, i3, i4) -> null; final Function4 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function4 f = (i1, i2, i3, i4) -> null; final Function4 memo = f.memoized(); assertThat(memo.apply(null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function4 f = (i1, i2, i3, i4) -> null; final Function4 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function4 divByZero = (i1, i2, i3, i4) -> 10 / integer.get(); Function4> divByZeroTry = Function4.liftTry(divByZero); Try res = divByZeroTry.apply(0, 0, 0, 0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1, 2, 3, 4); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function4 recurrent1 = (i1, i2, i3, i4) -> i1 <= 0 ? i1 : Function4Test.recurrent2.apply(i1 - 1, i2, i3, i4) + 1; private static final Function4 recurrent2 = Function4Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function4 f = (o1, o2, o3, o4) -> null; final Function1 after = o -> null; final Function4 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function4 wideFunction = (o1, o2, o3, o4) -> String.format("Numbers are: %s, %s, %s, %s", o1, o2, o3, o4); final Function4 narrowFunction = Function4.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4)).isEqualTo("Numbers are: 1, 2, 3, 4"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function5Test.java000066400000000000000000000163401342074374400237400ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function5Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5) { return null; } } final Type type = new Type(); assertThat(Function5.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function5.lift((o1, o2, o3, o4, o5) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() { final Function5 f = (o1, o2, o3, o4, o5) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final Function5 f = (o1, o2, o3, o4, o5) -> null; assertThat(f.arity()).isEqualTo(5); } @Test public void shouldConstant() { final Function5 f = Function5.constant(6); assertThat(f.apply(1, 2, 3, 4, 5)).isEqualTo(6); } @Test public void shouldCurry() { final Function5 f = (o1, o2, o3, o4, o5) -> null; final Function1>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function5 f = (o1, o2, o3, o4, o5) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function5 f = (o1, o2, o3, o4, o5) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function5 f = (i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5 + integer.getAndIncrement(); final Function5 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function5 f = (i1, i2, i3, i4, i5) -> null; final Function5 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function5 f = (i1, i2, i3, i4, i5) -> null; final Function5 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function5 f = (i1, i2, i3, i4, i5) -> null; final Function5 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function5 divByZero = (i1, i2, i3, i4, i5) -> 10 / integer.get(); Function5> divByZeroTry = Function5.liftTry(divByZero); Try res = divByZeroTry.apply(0, 0, 0, 0, 0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1, 2, 3, 4, 5); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function5 recurrent1 = (i1, i2, i3, i4, i5) -> i1 <= 0 ? i1 : Function5Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5) + 1; private static final Function5 recurrent2 = Function5Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function5 f = (o1, o2, o3, o4, o5) -> null; final Function1 after = o -> null; final Function5 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function5 wideFunction = (o1, o2, o3, o4, o5) -> String.format("Numbers are: %s, %s, %s, %s, %s", o1, o2, o3, o4, o5); final Function5 narrowFunction = Function5.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5)).isEqualTo("Numbers are: 1, 2, 3, 4, 5"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function6Test.java000066400000000000000000000172101342074374400237360ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function6Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) { return null; } } final Type type = new Type(); assertThat(Function6.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function6.lift((o1, o2, o3, o4, o5, o6) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() { final Function6 f = (o1, o2, o3, o4, o5, o6) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final Function6 f = (o1, o2, o3, o4, o5, o6) -> null; assertThat(f.arity()).isEqualTo(6); } @Test public void shouldConstant() { final Function6 f = Function6.constant(6); assertThat(f.apply(1, 2, 3, 4, 5, 6)).isEqualTo(6); } @Test public void shouldCurry() { final Function6 f = (o1, o2, o3, o4, o5, o6) -> null; final Function1>>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function6 f = (o1, o2, o3, o4, o5, o6) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function6 f = (o1, o2, o3, o4, o5, o6) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function6 f = (i1, i2, i3, i4, i5, i6) -> i1 + i2 + i3 + i4 + i5 + i6 + integer.getAndIncrement(); final Function6 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5, 6); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5, 6)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function6 f = (i1, i2, i3, i4, i5, i6) -> null; final Function6 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function6 f = (i1, i2, i3, i4, i5, i6) -> null; final Function6 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function6 f = (i1, i2, i3, i4, i5, i6) -> null; final Function6 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function6 divByZero = (i1, i2, i3, i4, i5, i6) -> 10 / integer.get(); Function6> divByZeroTry = Function6.liftTry(divByZero); Try res = divByZeroTry.apply(0, 0, 0, 0, 0, 0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1, 2, 3, 4, 5, 6); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function6 recurrent1 = (i1, i2, i3, i4, i5, i6) -> i1 <= 0 ? i1 : Function6Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5, i6) + 1; private static final Function6 recurrent2 = Function6Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11, 11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function6 f = (o1, o2, o3, o4, o5, o6) -> null; final Function1 after = o -> null; final Function6 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function6 wideFunction = (o1, o2, o3, o4, o5, o6) -> String.format("Numbers are: %s, %s, %s, %s, %s, %s", o1, o2, o3, o4, o5, o6); final Function6 narrowFunction = Function6.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5, 6)).isEqualTo("Numbers are: 1, 2, 3, 4, 5, 6"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function7Test.java000066400000000000000000000200661342074374400237420ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function7Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7) { return null; } } final Type type = new Type(); assertThat(Function7.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function7.lift((o1, o2, o3, o4, o5, o6, o7) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() { final Function7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final Function7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; assertThat(f.arity()).isEqualTo(7); } @Test public void shouldConstant() { final Function7 f = Function7.constant(6); assertThat(f.apply(1, 2, 3, 4, 5, 6, 7)).isEqualTo(6); } @Test public void shouldCurry() { final Function7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; final Function1>>>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function7 f = (i1, i2, i3, i4, i5, i6, i7) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + integer.getAndIncrement(); final Function7 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5, 6, 7); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5, 6, 7)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function7 f = (i1, i2, i3, i4, i5, i6, i7) -> null; final Function7 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function7 f = (i1, i2, i3, i4, i5, i6, i7) -> null; final Function7 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function7 f = (i1, i2, i3, i4, i5, i6, i7) -> null; final Function7 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function7 divByZero = (i1, i2, i3, i4, i5, i6, i7) -> 10 / integer.get(); Function7> divByZeroTry = Function7.liftTry(divByZero); Try res = divByZeroTry.apply(0, 0, 0, 0, 0, 0, 0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1, 2, 3, 4, 5, 6, 7); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function7 recurrent1 = (i1, i2, i3, i4, i5, i6, i7) -> i1 <= 0 ? i1 : Function7Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5, i6, i7) + 1; private static final Function7 recurrent2 = Function7Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11, 11, 11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function7 f = (o1, o2, o3, o4, o5, o6, o7) -> null; final Function1 after = o -> null; final Function7 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function7 wideFunction = (o1, o2, o3, o4, o5, o6, o7) -> String.format("Numbers are: %s, %s, %s, %s, %s, %s, %s", o1, o2, o3, o4, o5, o6, o7); final Function7 narrowFunction = Function7.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5, 6, 7)).isEqualTo("Numbers are: 1, 2, 3, 4, 5, 6, 7"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Function8Test.java000066400000000000000000000207521342074374400237450ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.control.Try; import java.lang.CharSequence; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; public class Function8Test { @Test public void shouldCreateFromMethodReference() { class Type { Object methodReference(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8) { return null; } } final Type type = new Type(); assertThat(Function8.of(type::methodReference)).isNotNull(); } @Test public void shouldLiftPartialFunction() { assertThat(Function8.lift((o1, o2, o3, o4, o5, o6, o7, o8) -> { while(true); })).isNotNull(); } @Test public void shouldPartiallyApply() { final Function8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; assertThat(f.apply(null)).isNotNull(); assertThat(f.apply(null, null)).isNotNull(); assertThat(f.apply(null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null, null)).isNotNull(); assertThat(f.apply(null, null, null, null, null, null, null)).isNotNull(); } @Test public void shouldGetArity() { final Function8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; assertThat(f.arity()).isEqualTo(8); } @Test public void shouldConstant() { final Function8 f = Function8.constant(6); assertThat(f.apply(1, 2, 3, 4, 5, 6, 7, 8)).isEqualTo(6); } @Test public void shouldCurry() { final Function8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; final Function1>>>>>>> curried = f.curried(); assertThat(curried).isNotNull(); } @Test public void shouldTuple() { final Function8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; final Function1, Object> tupled = f.tupled(); assertThat(tupled).isNotNull(); } @Test public void shouldReverse() { final Function8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; assertThat(f.reversed()).isNotNull(); } @Test public void shouldMemoize() { final AtomicInteger integer = new AtomicInteger(); final Function8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + integer.getAndIncrement(); final Function8 memo = f.memoized(); // should apply f on first apply() final int expected = memo.apply(1, 2, 3, 4, 5, 6, 7, 8); // should return memoized value of second apply() assertThat(memo.apply(1, 2, 3, 4, 5, 6, 7, 8)).isEqualTo(expected); // should calculate new values when called subsequently with different parameters assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 1); // should return memoized value of second apply() (for new value) assertThat(memo.apply(2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )).isEqualTo(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 1); } @Test public void shouldNotMemoizeAlreadyMemoizedFunction() { final Function8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> null; final Function8 memo = f.memoized(); assertThat(memo.memoized() == memo).isTrue(); } @Test public void shouldMemoizeValueGivenNullArguments() { final Function8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> null; final Function8 memo = f.memoized(); assertThat(memo.apply(null, null, null, null, null, null, null, null)).isNull(); } @Test public void shouldRecognizeMemoizedFunctions() { final Function8 f = (i1, i2, i3, i4, i5, i6, i7, i8) -> null; final Function8 memo = f.memoized(); assertThat(f.isMemoized()).isFalse(); assertThat(memo.isMemoized()).isTrue(); } @Test public void shouldLiftTryPartialFunction() { AtomicInteger integer = new AtomicInteger(); Function8 divByZero = (i1, i2, i3, i4, i5, i6, i7, i8) -> 10 / integer.get(); Function8> divByZeroTry = Function8.liftTry(divByZero); Try res = divByZeroTry.apply(0, 0, 0, 0, 0, 0, 0, 0); assertThat(res.isFailure()).isTrue(); assertThat(res.getCause()).isNotNull(); assertThat(res.getCause().getMessage()).isEqualToIgnoringCase("/ by zero"); integer.incrementAndGet(); res = divByZeroTry.apply(1, 2, 3, 4, 5, 6, 7, 8); assertThat(res.isSuccess()).isTrue(); assertThat(res.get()).isEqualTo(10); } private static final Function8 recurrent1 = (i1, i2, i3, i4, i5, i6, i7, i8) -> i1 <= 0 ? i1 : Function8Test.recurrent2.apply(i1 - 1, i2, i3, i4, i5, i6, i7, i8) + 1; private static final Function8 recurrent2 = Function8Test.recurrent1.memoized(); @Test public void shouldCalculatedRecursively() { assertThat(recurrent1.apply(11, 11, 11, 11, 11, 11, 11, 11)).isEqualTo(11); assertThat(recurrent1.apply(22, 22, 22, 22, 22, 22, 22, 22)).isEqualTo(22); } @Test public void shouldComposeWithAndThen() { final Function8 f = (o1, o2, o3, o4, o5, o6, o7, o8) -> null; final Function1 after = o -> null; final Function8 composed = f.andThen(after); assertThat(composed).isNotNull(); } @Test public void shouldNarrow(){ final Function8 wideFunction = (o1, o2, o3, o4, o5, o6, o7, o8) -> String.format("Numbers are: %s, %s, %s, %s, %s, %s, %s, %s", o1, o2, o3, o4, o5, o6, o7, o8); final Function8 narrowFunction = Function8.narrow(wideFunction); assertThat(narrowFunction.apply(1, 2, 3, 4, 5, 6, 7, 8)).isEqualTo("Numbers are: 1, 2, 3, 4, 5, 6, 7, 8"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple0Test.java000066400000000000000000000132601342074374400232350ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple0Test { @Test public void shouldCreateTuple() { final Tuple0 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple0 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(0); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple().toSeq(); assertThat(actual).isEqualTo(List.of()); } @Test public void shouldCompareEqual() { final Tuple0 t0 = createIntTuple(); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldApplyTuple() { final Tuple0 tuple = createTuple(); final Tuple0 actual = tuple.apply(() -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple1 actual = Tuple0.instance().append(1); final Tuple1 expected = Tuple.of(1); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple1 actual = Tuple0.instance().concat(Tuple.of(1)); final Tuple1 expected = Tuple.of(1); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple2() { final Tuple2 actual = Tuple0.instance().concat(Tuple.of(1, 2)); final Tuple2 expected = Tuple.of(1, 2); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple3() { final Tuple3 actual = Tuple0.instance().concat(Tuple.of(1, 2, 3)); final Tuple3 expected = Tuple.of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple4() { final Tuple4 actual = Tuple0.instance().concat(Tuple.of(1, 2, 3, 4)); final Tuple4 expected = Tuple.of(1, 2, 3, 4); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple5() { final Tuple5 actual = Tuple0.instance().concat(Tuple.of(1, 2, 3, 4, 5)); final Tuple5 expected = Tuple.of(1, 2, 3, 4, 5); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple6() { final Tuple6 actual = Tuple0.instance().concat(Tuple.of(1, 2, 3, 4, 5, 6)); final Tuple6 expected = Tuple.of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple7() { final Tuple7 actual = Tuple0.instance().concat(Tuple.of(1, 2, 3, 4, 5, 6, 7)); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple8() { final Tuple8 actual = Tuple0.instance().concat(Tuple.of(1, 2, 3, 4, 5, 6, 7, 8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple0 tuple1 = createTuple(); final Tuple0 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple0 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "()"; assertThat(actual).isEqualTo(expected); } private Comparator intTupleComparator = Tuple0.comparator(); private Tuple0 createTuple() { return Tuple0.instance(); } private Tuple0 createIntTuple() { return Tuple0.instance(); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple1Test.java000066400000000000000000000162351342074374400232430ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple1Test { @Test public void shouldCreateTuple() { final Tuple1 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple1 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(1); } @Test public void shouldReturnElements() { final Tuple1 tuple = createIntTuple(1); assertThat(tuple._1).isEqualTo(1); } @Test public void shouldUpdate1() { final Tuple1 tuple = createIntTuple(1).update1(42); assertThat(tuple._1).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1).toSeq(); assertThat(actual).isEqualTo(List.of(1)); } @Test public void shouldCompareEqual() { final Tuple1 t0 = createIntTuple(0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple1 t0 = createIntTuple(0); final Tuple1 t1 = createIntTuple(1); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldMap() { final Tuple1 tuple = createTuple(); final Tuple1 actual = tuple.map(o -> o); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple1 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Tuple1 actual = tuple.map(f1); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple1OfSequence1() { final Seq> iterable = List.of(Tuple.of(2)); final Tuple1> expected = Tuple.of(Stream.of(2)); assertThat(Tuple.sequence1(iterable)).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple1 tuple = createTuple(); final Tuple0 actual = tuple.apply(o1 -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple2 actual = Tuple.of(1).append(2); final Tuple2 expected = Tuple.of(1, 2); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple2 actual = Tuple.of(1).concat(Tuple.of(2)); final Tuple2 expected = Tuple.of(1, 2); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple2() { final Tuple3 actual = Tuple.of(1).concat(Tuple.of(2, 3)); final Tuple3 expected = Tuple.of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple3() { final Tuple4 actual = Tuple.of(1).concat(Tuple.of(2, 3, 4)); final Tuple4 expected = Tuple.of(1, 2, 3, 4); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple4() { final Tuple5 actual = Tuple.of(1).concat(Tuple.of(2, 3, 4, 5)); final Tuple5 expected = Tuple.of(1, 2, 3, 4, 5); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple5() { final Tuple6 actual = Tuple.of(1).concat(Tuple.of(2, 3, 4, 5, 6)); final Tuple6 expected = Tuple.of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple6() { final Tuple7 actual = Tuple.of(1).concat(Tuple.of(2, 3, 4, 5, 6, 7)); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple7() { final Tuple8 actual = Tuple.of(1).concat(Tuple.of(2, 3, 4, 5, 6, 7, 8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple1 tuple1 = createTuple(); final Tuple1 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple1 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple1 tuple = Tuple.of("1"); assertThat(tuple.equals(Tuple.of("X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hashCode(null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple1.comparator(Integer::compare); private Tuple1 createTuple() { return new Tuple1<>(null); } private Tuple1 createIntTuple(Integer i1) { return new Tuple1<>(i1); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple2Test.java000066400000000000000000000224411342074374400232400ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.AbstractMap; import java.util.Comparator; import java.util.Map; import java.util.Objects; import org.junit.Test; public class Tuple2Test { @Test public void shouldCreateTuple() { final Tuple2 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple2 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(2); } @Test public void shouldReturnElements() { final Tuple2 tuple = createIntTuple(1, 2); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); } @Test public void shouldUpdate1() { final Tuple2 tuple = createIntTuple(1, 2).update1(42); assertThat(tuple._1).isEqualTo(42); assertThat(tuple._2).isEqualTo(2); } @Test public void shouldUpdate2() { final Tuple2 tuple = createIntTuple(1, 2).update2(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1, 0).toSeq(); assertThat(actual).isEqualTo(List.of(1, 0)); } @Test public void shouldCompareEqual() { final Tuple2 t0 = createIntTuple(0, 0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple2 t0 = createIntTuple(0, 0); final Tuple2 t1 = createIntTuple(1, 0); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldCompare2ndArg() { final Tuple2 t0 = createIntTuple(0, 0); final Tuple2 t2 = createIntTuple(0, 1); assertThat(t0.compareTo(t2)).isNegative(); assertThat(t2.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t2)).isNegative(); assertThat(intTupleComparator.compare(t2, t0)).isPositive(); } @Test public void shouldSwap() { assertThat(createIntTuple(1, 2).swap()).isEqualTo(createIntTuple(2, 1)); } @Test public void shouldConvertToEntry() { Tuple2 tuple = createIntTuple(1,2); Map.Entry entry = new AbstractMap.SimpleEntry<>(1, 2); assertThat(tuple.toEntry().equals(entry)); } @Test public void shouldMap() { final Tuple2 tuple = createTuple(); final Tuple2 actual = tuple.map((o1, o2) -> tuple); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple2 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Function1 f2 = Function1.identity(); final Tuple2 actual = tuple.map(f1, f2); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple2OfSequence2() { final Seq> iterable = List.of(Tuple.of(2, 3), Tuple.of(4, 5)); final Tuple2, Seq> expected = Tuple.of(Stream.of(2, 4), Stream.of(3, 5)); assertThat(Tuple.sequence2(iterable)).isEqualTo(expected); } @Test public void shouldReturnTuple2OfSequence1() { final Seq> iterable = List.of(Tuple.of(1, 2)); final Tuple2, Seq> expected = Tuple.of(Stream.of(1), Stream.of(2)); assertThat(Tuple.sequence2(iterable)).isEqualTo(expected); } @Test public void shouldMap1stComponent() { final Tuple2 actual = Tuple.of(1, 1).map1(i -> "X"); final Tuple2 expected = Tuple.of("X", 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap2ndComponent() { final Tuple2 actual = Tuple.of(1, 1).map2(i -> "X"); final Tuple2 expected = Tuple.of(1, "X"); assertThat(actual).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple2 tuple = createTuple(); final Tuple0 actual = tuple.apply((o1, o2) -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple3 actual = Tuple.of(1, 2).append(3); final Tuple3 expected = Tuple.of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple3 actual = Tuple.of(1, 2).concat(Tuple.of(3)); final Tuple3 expected = Tuple.of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple2() { final Tuple4 actual = Tuple.of(1, 2).concat(Tuple.of(3, 4)); final Tuple4 expected = Tuple.of(1, 2, 3, 4); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple3() { final Tuple5 actual = Tuple.of(1, 2).concat(Tuple.of(3, 4, 5)); final Tuple5 expected = Tuple.of(1, 2, 3, 4, 5); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple4() { final Tuple6 actual = Tuple.of(1, 2).concat(Tuple.of(3, 4, 5, 6)); final Tuple6 expected = Tuple.of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple5() { final Tuple7 actual = Tuple.of(1, 2).concat(Tuple.of(3, 4, 5, 6, 7)); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple6() { final Tuple8 actual = Tuple.of(1, 2).concat(Tuple.of(3, 4, 5, 6, 7, 8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple2 tuple1 = createTuple(); final Tuple2 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple2 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple2 tuple = Tuple.of("1", "2"); assertThat(tuple.equals(Tuple.of("X", "2"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(null, null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null, null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple2.comparator(Integer::compare, Integer::compare); private Tuple2 createTuple() { return new Tuple2<>(null, null); } private Tuple2 createIntTuple(Integer i1, Integer i2) { return new Tuple2<>(i1, i2); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple3Test.java000066400000000000000000000244361342074374400232470ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple3Test { @Test public void shouldCreateTuple() { final Tuple3 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple3 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(3); } @Test public void shouldReturnElements() { final Tuple3 tuple = createIntTuple(1, 2, 3); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); } @Test public void shouldUpdate1() { final Tuple3 tuple = createIntTuple(1, 2, 3).update1(42); assertThat(tuple._1).isEqualTo(42); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); } @Test public void shouldUpdate2() { final Tuple3 tuple = createIntTuple(1, 2, 3).update2(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(42); assertThat(tuple._3).isEqualTo(3); } @Test public void shouldUpdate3() { final Tuple3 tuple = createIntTuple(1, 2, 3).update3(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1, 0, 0).toSeq(); assertThat(actual).isEqualTo(List.of(1, 0, 0)); } @Test public void shouldCompareEqual() { final Tuple3 t0 = createIntTuple(0, 0, 0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple3 t0 = createIntTuple(0, 0, 0); final Tuple3 t1 = createIntTuple(1, 0, 0); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldCompare2ndArg() { final Tuple3 t0 = createIntTuple(0, 0, 0); final Tuple3 t2 = createIntTuple(0, 1, 0); assertThat(t0.compareTo(t2)).isNegative(); assertThat(t2.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t2)).isNegative(); assertThat(intTupleComparator.compare(t2, t0)).isPositive(); } @Test public void shouldCompare3rdArg() { final Tuple3 t0 = createIntTuple(0, 0, 0); final Tuple3 t3 = createIntTuple(0, 0, 1); assertThat(t0.compareTo(t3)).isNegative(); assertThat(t3.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t3)).isNegative(); assertThat(intTupleComparator.compare(t3, t0)).isPositive(); } @Test public void shouldMap() { final Tuple3 tuple = createTuple(); final Tuple3 actual = tuple.map((o1, o2, o3) -> tuple); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple3 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Function1 f2 = Function1.identity(); final Function1 f3 = Function1.identity(); final Tuple3 actual = tuple.map(f1, f2, f3); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple3OfSequence3() { final Seq> iterable = List.of(Tuple.of(2, 3, 4), Tuple.of(4, 5, 6), Tuple.of(6, 7, 8)); final Tuple3, Seq, Seq> expected = Tuple.of(Stream.of(2, 4, 6), Stream.of(3, 5, 7), Stream.of(4, 6, 8)); assertThat(Tuple.sequence3(iterable)).isEqualTo(expected); } @Test public void shouldReturnTuple3OfSequence1() { final Seq> iterable = List.of(Tuple.of(1, 2, 3)); final Tuple3, Seq, Seq> expected = Tuple.of(Stream.of(1), Stream.of(2), Stream.of(3)); assertThat(Tuple.sequence3(iterable)).isEqualTo(expected); } @Test public void shouldMap1stComponent() { final Tuple3 actual = Tuple.of(1, 1, 1).map1(i -> "X"); final Tuple3 expected = Tuple.of("X", 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap2ndComponent() { final Tuple3 actual = Tuple.of(1, 1, 1).map2(i -> "X"); final Tuple3 expected = Tuple.of(1, "X", 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap3rdComponent() { final Tuple3 actual = Tuple.of(1, 1, 1).map3(i -> "X"); final Tuple3 expected = Tuple.of(1, 1, "X"); assertThat(actual).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple3 tuple = createTuple(); final Tuple0 actual = tuple.apply((o1, o2, o3) -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple4 actual = Tuple.of(1, 2, 3).append(4); final Tuple4 expected = Tuple.of(1, 2, 3, 4); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple4 actual = Tuple.of(1, 2, 3).concat(Tuple.of(4)); final Tuple4 expected = Tuple.of(1, 2, 3, 4); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple2() { final Tuple5 actual = Tuple.of(1, 2, 3).concat(Tuple.of(4, 5)); final Tuple5 expected = Tuple.of(1, 2, 3, 4, 5); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple3() { final Tuple6 actual = Tuple.of(1, 2, 3).concat(Tuple.of(4, 5, 6)); final Tuple6 expected = Tuple.of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple4() { final Tuple7 actual = Tuple.of(1, 2, 3).concat(Tuple.of(4, 5, 6, 7)); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple5() { final Tuple8 actual = Tuple.of(1, 2, 3).concat(Tuple.of(4, 5, 6, 7, 8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple3 tuple1 = createTuple(); final Tuple3 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple3 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple3 tuple = Tuple.of("1", "2", "3"); assertThat(tuple.equals(Tuple.of("X", "2", "3"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "X", "3"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(null, null, null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null, null, null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple3.comparator(Integer::compare, Integer::compare, Integer::compare); private Tuple3 createTuple() { return new Tuple3<>(null, null, null); } private Tuple3 createIntTuple(Integer i1, Integer i2, Integer i3) { return new Tuple3<>(i1, i2, i3); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple4Test.java000066400000000000000000000276301342074374400232470ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple4Test { @Test public void shouldCreateTuple() { final Tuple4 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple4 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(4); } @Test public void shouldReturnElements() { final Tuple4 tuple = createIntTuple(1, 2, 3, 4); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); } @Test public void shouldUpdate1() { final Tuple4 tuple = createIntTuple(1, 2, 3, 4).update1(42); assertThat(tuple._1).isEqualTo(42); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); } @Test public void shouldUpdate2() { final Tuple4 tuple = createIntTuple(1, 2, 3, 4).update2(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(42); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); } @Test public void shouldUpdate3() { final Tuple4 tuple = createIntTuple(1, 2, 3, 4).update3(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(42); assertThat(tuple._4).isEqualTo(4); } @Test public void shouldUpdate4() { final Tuple4 tuple = createIntTuple(1, 2, 3, 4).update4(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1, 0, 0, 0).toSeq(); assertThat(actual).isEqualTo(List.of(1, 0, 0, 0)); } @Test public void shouldCompareEqual() { final Tuple4 t0 = createIntTuple(0, 0, 0, 0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple4 t0 = createIntTuple(0, 0, 0, 0); final Tuple4 t1 = createIntTuple(1, 0, 0, 0); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldCompare2ndArg() { final Tuple4 t0 = createIntTuple(0, 0, 0, 0); final Tuple4 t2 = createIntTuple(0, 1, 0, 0); assertThat(t0.compareTo(t2)).isNegative(); assertThat(t2.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t2)).isNegative(); assertThat(intTupleComparator.compare(t2, t0)).isPositive(); } @Test public void shouldCompare3rdArg() { final Tuple4 t0 = createIntTuple(0, 0, 0, 0); final Tuple4 t3 = createIntTuple(0, 0, 1, 0); assertThat(t0.compareTo(t3)).isNegative(); assertThat(t3.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t3)).isNegative(); assertThat(intTupleComparator.compare(t3, t0)).isPositive(); } @Test public void shouldCompare4thArg() { final Tuple4 t0 = createIntTuple(0, 0, 0, 0); final Tuple4 t4 = createIntTuple(0, 0, 0, 1); assertThat(t0.compareTo(t4)).isNegative(); assertThat(t4.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t4)).isNegative(); assertThat(intTupleComparator.compare(t4, t0)).isPositive(); } @Test public void shouldMap() { final Tuple4 tuple = createTuple(); final Tuple4 actual = tuple.map((o1, o2, o3, o4) -> tuple); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple4 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Function1 f2 = Function1.identity(); final Function1 f3 = Function1.identity(); final Function1 f4 = Function1.identity(); final Tuple4 actual = tuple.map(f1, f2, f3, f4); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple4OfSequence4() { final Seq> iterable = List.of(Tuple.of(2, 3, 4, 5), Tuple.of(4, 5, 6, 7), Tuple.of(6, 7, 8, 9), Tuple.of(8, 9, 10, 11)); final Tuple4, Seq, Seq, Seq> expected = Tuple.of(Stream.of(2, 4, 6, 8), Stream.of(3, 5, 7, 9), Stream.of(4, 6, 8, 10), Stream.of(5, 7, 9, 11)); assertThat(Tuple.sequence4(iterable)).isEqualTo(expected); } @Test public void shouldReturnTuple4OfSequence1() { final Seq> iterable = List.of(Tuple.of(1, 2, 3, 4)); final Tuple4, Seq, Seq, Seq> expected = Tuple.of(Stream.of(1), Stream.of(2), Stream.of(3), Stream.of(4)); assertThat(Tuple.sequence4(iterable)).isEqualTo(expected); } @Test public void shouldMap1stComponent() { final Tuple4 actual = Tuple.of(1, 1, 1, 1).map1(i -> "X"); final Tuple4 expected = Tuple.of("X", 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap2ndComponent() { final Tuple4 actual = Tuple.of(1, 1, 1, 1).map2(i -> "X"); final Tuple4 expected = Tuple.of(1, "X", 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap3rdComponent() { final Tuple4 actual = Tuple.of(1, 1, 1, 1).map3(i -> "X"); final Tuple4 expected = Tuple.of(1, 1, "X", 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap4thComponent() { final Tuple4 actual = Tuple.of(1, 1, 1, 1).map4(i -> "X"); final Tuple4 expected = Tuple.of(1, 1, 1, "X"); assertThat(actual).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple4 tuple = createTuple(); final Tuple0 actual = tuple.apply((o1, o2, o3, o4) -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple5 actual = Tuple.of(1, 2, 3, 4).append(5); final Tuple5 expected = Tuple.of(1, 2, 3, 4, 5); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple5 actual = Tuple.of(1, 2, 3, 4).concat(Tuple.of(5)); final Tuple5 expected = Tuple.of(1, 2, 3, 4, 5); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple2() { final Tuple6 actual = Tuple.of(1, 2, 3, 4).concat(Tuple.of(5, 6)); final Tuple6 expected = Tuple.of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple3() { final Tuple7 actual = Tuple.of(1, 2, 3, 4).concat(Tuple.of(5, 6, 7)); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple4() { final Tuple8 actual = Tuple.of(1, 2, 3, 4).concat(Tuple.of(5, 6, 7, 8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple4 tuple1 = createTuple(); final Tuple4 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple4 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple4 tuple = Tuple.of("1", "2", "3", "4"); assertThat(tuple.equals(Tuple.of("X", "2", "3", "4"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "X", "3", "4"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "X", "4"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(null, null, null, null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null, null, null, null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple4.comparator(Integer::compare, Integer::compare, Integer::compare, Integer::compare); private Tuple4 createTuple() { return new Tuple4<>(null, null, null, null); } private Tuple4 createIntTuple(Integer i1, Integer i2, Integer i3, Integer i4) { return new Tuple4<>(i1, i2, i3, i4); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple5Test.java000066400000000000000000000333441342074374400232470ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple5Test { @Test public void shouldCreateTuple() { final Tuple5 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple5 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(5); } @Test public void shouldReturnElements() { final Tuple5 tuple = createIntTuple(1, 2, 3, 4, 5); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); } @Test public void shouldUpdate1() { final Tuple5 tuple = createIntTuple(1, 2, 3, 4, 5).update1(42); assertThat(tuple._1).isEqualTo(42); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); } @Test public void shouldUpdate2() { final Tuple5 tuple = createIntTuple(1, 2, 3, 4, 5).update2(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(42); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); } @Test public void shouldUpdate3() { final Tuple5 tuple = createIntTuple(1, 2, 3, 4, 5).update3(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(42); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); } @Test public void shouldUpdate4() { final Tuple5 tuple = createIntTuple(1, 2, 3, 4, 5).update4(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(42); assertThat(tuple._5).isEqualTo(5); } @Test public void shouldUpdate5() { final Tuple5 tuple = createIntTuple(1, 2, 3, 4, 5).update5(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1, 0, 0, 0, 0).toSeq(); assertThat(actual).isEqualTo(List.of(1, 0, 0, 0, 0)); } @Test public void shouldCompareEqual() { final Tuple5 t0 = createIntTuple(0, 0, 0, 0, 0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple5 t0 = createIntTuple(0, 0, 0, 0, 0); final Tuple5 t1 = createIntTuple(1, 0, 0, 0, 0); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldCompare2ndArg() { final Tuple5 t0 = createIntTuple(0, 0, 0, 0, 0); final Tuple5 t2 = createIntTuple(0, 1, 0, 0, 0); assertThat(t0.compareTo(t2)).isNegative(); assertThat(t2.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t2)).isNegative(); assertThat(intTupleComparator.compare(t2, t0)).isPositive(); } @Test public void shouldCompare3rdArg() { final Tuple5 t0 = createIntTuple(0, 0, 0, 0, 0); final Tuple5 t3 = createIntTuple(0, 0, 1, 0, 0); assertThat(t0.compareTo(t3)).isNegative(); assertThat(t3.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t3)).isNegative(); assertThat(intTupleComparator.compare(t3, t0)).isPositive(); } @Test public void shouldCompare4thArg() { final Tuple5 t0 = createIntTuple(0, 0, 0, 0, 0); final Tuple5 t4 = createIntTuple(0, 0, 0, 1, 0); assertThat(t0.compareTo(t4)).isNegative(); assertThat(t4.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t4)).isNegative(); assertThat(intTupleComparator.compare(t4, t0)).isPositive(); } @Test public void shouldCompare5thArg() { final Tuple5 t0 = createIntTuple(0, 0, 0, 0, 0); final Tuple5 t5 = createIntTuple(0, 0, 0, 0, 1); assertThat(t0.compareTo(t5)).isNegative(); assertThat(t5.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t5)).isNegative(); assertThat(intTupleComparator.compare(t5, t0)).isPositive(); } @Test public void shouldMap() { final Tuple5 tuple = createTuple(); final Tuple5 actual = tuple.map((o1, o2, o3, o4, o5) -> tuple); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple5 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Function1 f2 = Function1.identity(); final Function1 f3 = Function1.identity(); final Function1 f4 = Function1.identity(); final Function1 f5 = Function1.identity(); final Tuple5 actual = tuple.map(f1, f2, f3, f4, f5); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple5OfSequence5() { final Seq> iterable = List.of(Tuple.of(2, 3, 4, 5, 6), Tuple.of(4, 5, 6, 7, 8), Tuple.of(6, 7, 8, 9, 10), Tuple.of(8, 9, 10, 11, 12), Tuple.of(10, 11, 12, 13, 14)); final Tuple5, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(2, 4, 6, 8, 10), Stream.of(3, 5, 7, 9, 11), Stream.of(4, 6, 8, 10, 12), Stream.of(5, 7, 9, 11, 13), Stream.of(6, 8, 10, 12, 14)); assertThat(Tuple.sequence5(iterable)).isEqualTo(expected); } @Test public void shouldReturnTuple5OfSequence1() { final Seq> iterable = List.of(Tuple.of(1, 2, 3, 4, 5)); final Tuple5, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(1), Stream.of(2), Stream.of(3), Stream.of(4), Stream.of(5)); assertThat(Tuple.sequence5(iterable)).isEqualTo(expected); } @Test public void shouldMap1stComponent() { final Tuple5 actual = Tuple.of(1, 1, 1, 1, 1).map1(i -> "X"); final Tuple5 expected = Tuple.of("X", 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap2ndComponent() { final Tuple5 actual = Tuple.of(1, 1, 1, 1, 1).map2(i -> "X"); final Tuple5 expected = Tuple.of(1, "X", 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap3rdComponent() { final Tuple5 actual = Tuple.of(1, 1, 1, 1, 1).map3(i -> "X"); final Tuple5 expected = Tuple.of(1, 1, "X", 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap4thComponent() { final Tuple5 actual = Tuple.of(1, 1, 1, 1, 1).map4(i -> "X"); final Tuple5 expected = Tuple.of(1, 1, 1, "X", 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap5thComponent() { final Tuple5 actual = Tuple.of(1, 1, 1, 1, 1).map5(i -> "X"); final Tuple5 expected = Tuple.of(1, 1, 1, 1, "X"); assertThat(actual).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple5 tuple = createTuple(); final Tuple0 actual = tuple.apply((o1, o2, o3, o4, o5) -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple6 actual = Tuple.of(1, 2, 3, 4, 5).append(6); final Tuple6 expected = Tuple.of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple6 actual = Tuple.of(1, 2, 3, 4, 5).concat(Tuple.of(6)); final Tuple6 expected = Tuple.of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple2() { final Tuple7 actual = Tuple.of(1, 2, 3, 4, 5).concat(Tuple.of(6, 7)); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple3() { final Tuple8 actual = Tuple.of(1, 2, 3, 4, 5).concat(Tuple.of(6, 7, 8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple5 tuple1 = createTuple(); final Tuple5 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple5 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple5 tuple = Tuple.of("1", "2", "3", "4", "5"); assertThat(tuple.equals(Tuple.of("X", "2", "3", "4", "5"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "X", "3", "4", "5"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "X", "4", "5"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "X", "5"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(null, null, null, null, null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null, null, null, null, null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple5.comparator(Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare); private Tuple5 createTuple() { return new Tuple5<>(null, null, null, null, null); } private Tuple5 createIntTuple(Integer i1, Integer i2, Integer i3, Integer i4, Integer i5) { return new Tuple5<>(i1, i2, i3, i4, i5); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple6Test.java000066400000000000000000000373741342074374400232570ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple6Test { @Test public void shouldCreateTuple() { final Tuple6 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple6 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(6); } @Test public void shouldReturnElements() { final Tuple6 tuple = createIntTuple(1, 2, 3, 4, 5, 6); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); } @Test public void shouldUpdate1() { final Tuple6 tuple = createIntTuple(1, 2, 3, 4, 5, 6).update1(42); assertThat(tuple._1).isEqualTo(42); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); } @Test public void shouldUpdate2() { final Tuple6 tuple = createIntTuple(1, 2, 3, 4, 5, 6).update2(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(42); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); } @Test public void shouldUpdate3() { final Tuple6 tuple = createIntTuple(1, 2, 3, 4, 5, 6).update3(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(42); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); } @Test public void shouldUpdate4() { final Tuple6 tuple = createIntTuple(1, 2, 3, 4, 5, 6).update4(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(42); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); } @Test public void shouldUpdate5() { final Tuple6 tuple = createIntTuple(1, 2, 3, 4, 5, 6).update5(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(42); assertThat(tuple._6).isEqualTo(6); } @Test public void shouldUpdate6() { final Tuple6 tuple = createIntTuple(1, 2, 3, 4, 5, 6).update6(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1, 0, 0, 0, 0, 0).toSeq(); assertThat(actual).isEqualTo(List.of(1, 0, 0, 0, 0, 0)); } @Test public void shouldCompareEqual() { final Tuple6 t0 = createIntTuple(0, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple6 t0 = createIntTuple(0, 0, 0, 0, 0, 0); final Tuple6 t1 = createIntTuple(1, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldCompare2ndArg() { final Tuple6 t0 = createIntTuple(0, 0, 0, 0, 0, 0); final Tuple6 t2 = createIntTuple(0, 1, 0, 0, 0, 0); assertThat(t0.compareTo(t2)).isNegative(); assertThat(t2.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t2)).isNegative(); assertThat(intTupleComparator.compare(t2, t0)).isPositive(); } @Test public void shouldCompare3rdArg() { final Tuple6 t0 = createIntTuple(0, 0, 0, 0, 0, 0); final Tuple6 t3 = createIntTuple(0, 0, 1, 0, 0, 0); assertThat(t0.compareTo(t3)).isNegative(); assertThat(t3.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t3)).isNegative(); assertThat(intTupleComparator.compare(t3, t0)).isPositive(); } @Test public void shouldCompare4thArg() { final Tuple6 t0 = createIntTuple(0, 0, 0, 0, 0, 0); final Tuple6 t4 = createIntTuple(0, 0, 0, 1, 0, 0); assertThat(t0.compareTo(t4)).isNegative(); assertThat(t4.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t4)).isNegative(); assertThat(intTupleComparator.compare(t4, t0)).isPositive(); } @Test public void shouldCompare5thArg() { final Tuple6 t0 = createIntTuple(0, 0, 0, 0, 0, 0); final Tuple6 t5 = createIntTuple(0, 0, 0, 0, 1, 0); assertThat(t0.compareTo(t5)).isNegative(); assertThat(t5.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t5)).isNegative(); assertThat(intTupleComparator.compare(t5, t0)).isPositive(); } @Test public void shouldCompare6thArg() { final Tuple6 t0 = createIntTuple(0, 0, 0, 0, 0, 0); final Tuple6 t6 = createIntTuple(0, 0, 0, 0, 0, 1); assertThat(t0.compareTo(t6)).isNegative(); assertThat(t6.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t6)).isNegative(); assertThat(intTupleComparator.compare(t6, t0)).isPositive(); } @Test public void shouldMap() { final Tuple6 tuple = createTuple(); final Tuple6 actual = tuple.map((o1, o2, o3, o4, o5, o6) -> tuple); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple6 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Function1 f2 = Function1.identity(); final Function1 f3 = Function1.identity(); final Function1 f4 = Function1.identity(); final Function1 f5 = Function1.identity(); final Function1 f6 = Function1.identity(); final Tuple6 actual = tuple.map(f1, f2, f3, f4, f5, f6); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple6OfSequence6() { final Seq> iterable = List.of(Tuple.of(2, 3, 4, 5, 6, 7), Tuple.of(4, 5, 6, 7, 8, 9), Tuple.of(6, 7, 8, 9, 10, 11), Tuple.of(8, 9, 10, 11, 12, 13), Tuple.of(10, 11, 12, 13, 14, 15), Tuple.of(12, 13, 14, 15, 16, 17)); final Tuple6, Seq, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(2, 4, 6, 8, 10, 12), Stream.of(3, 5, 7, 9, 11, 13), Stream.of(4, 6, 8, 10, 12, 14), Stream.of(5, 7, 9, 11, 13, 15), Stream.of(6, 8, 10, 12, 14, 16), Stream.of(7, 9, 11, 13, 15, 17)); assertThat(Tuple.sequence6(iterable)).isEqualTo(expected); } @Test public void shouldReturnTuple6OfSequence1() { final Seq> iterable = List.of(Tuple.of(1, 2, 3, 4, 5, 6)); final Tuple6, Seq, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(1), Stream.of(2), Stream.of(3), Stream.of(4), Stream.of(5), Stream.of(6)); assertThat(Tuple.sequence6(iterable)).isEqualTo(expected); } @Test public void shouldMap1stComponent() { final Tuple6 actual = Tuple.of(1, 1, 1, 1, 1, 1).map1(i -> "X"); final Tuple6 expected = Tuple.of("X", 1, 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap2ndComponent() { final Tuple6 actual = Tuple.of(1, 1, 1, 1, 1, 1).map2(i -> "X"); final Tuple6 expected = Tuple.of(1, "X", 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap3rdComponent() { final Tuple6 actual = Tuple.of(1, 1, 1, 1, 1, 1).map3(i -> "X"); final Tuple6 expected = Tuple.of(1, 1, "X", 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap4thComponent() { final Tuple6 actual = Tuple.of(1, 1, 1, 1, 1, 1).map4(i -> "X"); final Tuple6 expected = Tuple.of(1, 1, 1, "X", 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap5thComponent() { final Tuple6 actual = Tuple.of(1, 1, 1, 1, 1, 1).map5(i -> "X"); final Tuple6 expected = Tuple.of(1, 1, 1, 1, "X", 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap6thComponent() { final Tuple6 actual = Tuple.of(1, 1, 1, 1, 1, 1).map6(i -> "X"); final Tuple6 expected = Tuple.of(1, 1, 1, 1, 1, "X"); assertThat(actual).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple6 tuple = createTuple(); final Tuple0 actual = tuple.apply((o1, o2, o3, o4, o5, o6) -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple7 actual = Tuple.of(1, 2, 3, 4, 5, 6).append(7); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple7 actual = Tuple.of(1, 2, 3, 4, 5, 6).concat(Tuple.of(7)); final Tuple7 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple2() { final Tuple8 actual = Tuple.of(1, 2, 3, 4, 5, 6).concat(Tuple.of(7, 8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple6 tuple1 = createTuple(); final Tuple6 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple6 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple6 tuple = Tuple.of("1", "2", "3", "4", "5", "6"); assertThat(tuple.equals(Tuple.of("X", "2", "3", "4", "5", "6"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "X", "3", "4", "5", "6"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "X", "4", "5", "6"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "X", "5", "6"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "X", "6"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "5", "X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(null, null, null, null, null, null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null, null, null, null, null, null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple6.comparator(Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare); private Tuple6 createTuple() { return new Tuple6<>(null, null, null, null, null, null); } private Tuple6 createIntTuple(Integer i1, Integer i2, Integer i3, Integer i4, Integer i5, Integer i6) { return new Tuple6<>(i1, i2, i3, i4, i5, i6); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple7Test.java000066400000000000000000000437421342074374400232540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple7Test { @Test public void shouldCreateTuple() { final Tuple7 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple7 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(7); } @Test public void shouldReturnElements() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); } @Test public void shouldUpdate1() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7).update1(42); assertThat(tuple._1).isEqualTo(42); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); } @Test public void shouldUpdate2() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7).update2(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(42); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); } @Test public void shouldUpdate3() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7).update3(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(42); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); } @Test public void shouldUpdate4() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7).update4(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(42); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); } @Test public void shouldUpdate5() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7).update5(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(42); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); } @Test public void shouldUpdate6() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7).update6(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(42); assertThat(tuple._7).isEqualTo(7); } @Test public void shouldUpdate7() { final Tuple7 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7).update7(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1, 0, 0, 0, 0, 0, 0).toSeq(); assertThat(actual).isEqualTo(List.of(1, 0, 0, 0, 0, 0, 0)); } @Test public void shouldCompareEqual() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); final Tuple7 t1 = createIntTuple(1, 0, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldCompare2ndArg() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); final Tuple7 t2 = createIntTuple(0, 1, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t2)).isNegative(); assertThat(t2.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t2)).isNegative(); assertThat(intTupleComparator.compare(t2, t0)).isPositive(); } @Test public void shouldCompare3rdArg() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); final Tuple7 t3 = createIntTuple(0, 0, 1, 0, 0, 0, 0); assertThat(t0.compareTo(t3)).isNegative(); assertThat(t3.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t3)).isNegative(); assertThat(intTupleComparator.compare(t3, t0)).isPositive(); } @Test public void shouldCompare4thArg() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); final Tuple7 t4 = createIntTuple(0, 0, 0, 1, 0, 0, 0); assertThat(t0.compareTo(t4)).isNegative(); assertThat(t4.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t4)).isNegative(); assertThat(intTupleComparator.compare(t4, t0)).isPositive(); } @Test public void shouldCompare5thArg() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); final Tuple7 t5 = createIntTuple(0, 0, 0, 0, 1, 0, 0); assertThat(t0.compareTo(t5)).isNegative(); assertThat(t5.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t5)).isNegative(); assertThat(intTupleComparator.compare(t5, t0)).isPositive(); } @Test public void shouldCompare6thArg() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); final Tuple7 t6 = createIntTuple(0, 0, 0, 0, 0, 1, 0); assertThat(t0.compareTo(t6)).isNegative(); assertThat(t6.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t6)).isNegative(); assertThat(intTupleComparator.compare(t6, t0)).isPositive(); } @Test public void shouldCompare7thArg() { final Tuple7 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0); final Tuple7 t7 = createIntTuple(0, 0, 0, 0, 0, 0, 1); assertThat(t0.compareTo(t7)).isNegative(); assertThat(t7.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t7)).isNegative(); assertThat(intTupleComparator.compare(t7, t0)).isPositive(); } @Test public void shouldMap() { final Tuple7 tuple = createTuple(); final Tuple7 actual = tuple.map((o1, o2, o3, o4, o5, o6, o7) -> tuple); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple7 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Function1 f2 = Function1.identity(); final Function1 f3 = Function1.identity(); final Function1 f4 = Function1.identity(); final Function1 f5 = Function1.identity(); final Function1 f6 = Function1.identity(); final Function1 f7 = Function1.identity(); final Tuple7 actual = tuple.map(f1, f2, f3, f4, f5, f6, f7); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple7OfSequence7() { final Seq> iterable = List.of(Tuple.of(2, 3, 4, 5, 6, 7, 8), Tuple.of(4, 5, 6, 7, 8, 9, 10), Tuple.of(6, 7, 8, 9, 10, 11, 12), Tuple.of(8, 9, 10, 11, 12, 13, 14), Tuple.of(10, 11, 12, 13, 14, 15, 16), Tuple.of(12, 13, 14, 15, 16, 17, 18), Tuple.of(14, 15, 16, 17, 18, 19, 20)); final Tuple7, Seq, Seq, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(2, 4, 6, 8, 10, 12, 14), Stream.of(3, 5, 7, 9, 11, 13, 15), Stream.of(4, 6, 8, 10, 12, 14, 16), Stream.of(5, 7, 9, 11, 13, 15, 17), Stream.of(6, 8, 10, 12, 14, 16, 18), Stream.of(7, 9, 11, 13, 15, 17, 19), Stream.of(8, 10, 12, 14, 16, 18, 20)); assertThat(Tuple.sequence7(iterable)).isEqualTo(expected); } @Test public void shouldReturnTuple7OfSequence1() { final Seq> iterable = List.of(Tuple.of(1, 2, 3, 4, 5, 6, 7)); final Tuple7, Seq, Seq, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(1), Stream.of(2), Stream.of(3), Stream.of(4), Stream.of(5), Stream.of(6), Stream.of(7)); assertThat(Tuple.sequence7(iterable)).isEqualTo(expected); } @Test public void shouldMap1stComponent() { final Tuple7 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1).map1(i -> "X"); final Tuple7 expected = Tuple.of("X", 1, 1, 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap2ndComponent() { final Tuple7 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1).map2(i -> "X"); final Tuple7 expected = Tuple.of(1, "X", 1, 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap3rdComponent() { final Tuple7 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1).map3(i -> "X"); final Tuple7 expected = Tuple.of(1, 1, "X", 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap4thComponent() { final Tuple7 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1).map4(i -> "X"); final Tuple7 expected = Tuple.of(1, 1, 1, "X", 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap5thComponent() { final Tuple7 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1).map5(i -> "X"); final Tuple7 expected = Tuple.of(1, 1, 1, 1, "X", 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap6thComponent() { final Tuple7 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1).map6(i -> "X"); final Tuple7 expected = Tuple.of(1, 1, 1, 1, 1, "X", 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap7thComponent() { final Tuple7 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1).map7(i -> "X"); final Tuple7 expected = Tuple.of(1, 1, 1, 1, 1, 1, "X"); assertThat(actual).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple7 tuple = createTuple(); final Tuple0 actual = tuple.apply((o1, o2, o3, o4, o5, o6, o7) -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldAppendValue() { final Tuple8 actual = Tuple.of(1, 2, 3, 4, 5, 6, 7).append(8); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldConcatTuple1() { final Tuple8 actual = Tuple.of(1, 2, 3, 4, 5, 6, 7).concat(Tuple.of(8)); final Tuple8 expected = Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); assertThat(actual).isEqualTo(expected); } @Test public void shouldRecognizeEquality() { final Tuple7 tuple1 = createTuple(); final Tuple7 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple7 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple7 tuple = Tuple.of("1", "2", "3", "4", "5", "6", "7"); assertThat(tuple.equals(Tuple.of("X", "2", "3", "4", "5", "6", "7"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "X", "3", "4", "5", "6", "7"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "X", "4", "5", "6", "7"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "X", "5", "6", "7"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "X", "6", "7"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "5", "X", "7"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "5", "6", "X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(null, null, null, null, null, null, null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null, null, null, null, null, null, null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple7.comparator(Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare); private Tuple7 createTuple() { return new Tuple7<>(null, null, null, null, null, null, null); } private Tuple7 createIntTuple(Integer i1, Integer i2, Integer i3, Integer i4, Integer i5, Integer i6, Integer i7) { return new Tuple7<>(i1, i2, i3, i4, i5, i6, i7); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/Tuple8Test.java000066400000000000000000000477741342074374400232660ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import io.vavr.collection.List; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class Tuple8Test { @Test public void shouldCreateTuple() { final Tuple8 tuple = createTuple(); assertThat(tuple).isNotNull(); } @Test public void shouldGetArity() { final Tuple8 tuple = createTuple(); assertThat(tuple.arity()).isEqualTo(8); } @Test public void shouldReturnElements() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate1() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update1(42); assertThat(tuple._1).isEqualTo(42); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate2() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update2(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(42); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate3() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update3(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(42); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate4() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update4(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(42); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate5() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update5(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(42); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate6() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update6(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(42); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate7() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update7(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(42); assertThat(tuple._8).isEqualTo(8); } @Test public void shouldUpdate8() { final Tuple8 tuple = createIntTuple(1, 2, 3, 4, 5, 6, 7, 8).update8(42); assertThat(tuple._1).isEqualTo(1); assertThat(tuple._2).isEqualTo(2); assertThat(tuple._3).isEqualTo(3); assertThat(tuple._4).isEqualTo(4); assertThat(tuple._5).isEqualTo(5); assertThat(tuple._6).isEqualTo(6); assertThat(tuple._7).isEqualTo(7); assertThat(tuple._8).isEqualTo(42); } @Test public void shouldConvertToSeq() { final Seq actual = createIntTuple(1, 0, 0, 0, 0, 0, 0, 0).toSeq(); assertThat(actual).isEqualTo(List.of(1, 0, 0, 0, 0, 0, 0, 0)); } @Test public void shouldCompareEqual() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t0)).isZero(); assertThat(intTupleComparator.compare(t0, t0)).isZero(); } @Test public void shouldCompare1stArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t1 = createIntTuple(1, 0, 0, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t1)).isNegative(); assertThat(t1.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t1)).isNegative(); assertThat(intTupleComparator.compare(t1, t0)).isPositive(); } @Test public void shouldCompare2ndArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t2 = createIntTuple(0, 1, 0, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t2)).isNegative(); assertThat(t2.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t2)).isNegative(); assertThat(intTupleComparator.compare(t2, t0)).isPositive(); } @Test public void shouldCompare3rdArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t3 = createIntTuple(0, 0, 1, 0, 0, 0, 0, 0); assertThat(t0.compareTo(t3)).isNegative(); assertThat(t3.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t3)).isNegative(); assertThat(intTupleComparator.compare(t3, t0)).isPositive(); } @Test public void shouldCompare4thArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t4 = createIntTuple(0, 0, 0, 1, 0, 0, 0, 0); assertThat(t0.compareTo(t4)).isNegative(); assertThat(t4.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t4)).isNegative(); assertThat(intTupleComparator.compare(t4, t0)).isPositive(); } @Test public void shouldCompare5thArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t5 = createIntTuple(0, 0, 0, 0, 1, 0, 0, 0); assertThat(t0.compareTo(t5)).isNegative(); assertThat(t5.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t5)).isNegative(); assertThat(intTupleComparator.compare(t5, t0)).isPositive(); } @Test public void shouldCompare6thArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t6 = createIntTuple(0, 0, 0, 0, 0, 1, 0, 0); assertThat(t0.compareTo(t6)).isNegative(); assertThat(t6.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t6)).isNegative(); assertThat(intTupleComparator.compare(t6, t0)).isPositive(); } @Test public void shouldCompare7thArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t7 = createIntTuple(0, 0, 0, 0, 0, 0, 1, 0); assertThat(t0.compareTo(t7)).isNegative(); assertThat(t7.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t7)).isNegative(); assertThat(intTupleComparator.compare(t7, t0)).isPositive(); } @Test public void shouldCompare8thArg() { final Tuple8 t0 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 0); final Tuple8 t8 = createIntTuple(0, 0, 0, 0, 0, 0, 0, 1); assertThat(t0.compareTo(t8)).isNegative(); assertThat(t8.compareTo(t0)).isPositive(); assertThat(intTupleComparator.compare(t0, t8)).isNegative(); assertThat(intTupleComparator.compare(t8, t0)).isPositive(); } @Test public void shouldMap() { final Tuple8 tuple = createTuple(); final Tuple8 actual = tuple.map((o1, o2, o3, o4, o5, o6, o7, o8) -> tuple); assertThat(actual).isEqualTo(tuple); } @Test public void shouldMapComponents() { final Tuple8 tuple = createTuple(); final Function1 f1 = Function1.identity(); final Function1 f2 = Function1.identity(); final Function1 f3 = Function1.identity(); final Function1 f4 = Function1.identity(); final Function1 f5 = Function1.identity(); final Function1 f6 = Function1.identity(); final Function1 f7 = Function1.identity(); final Function1 f8 = Function1.identity(); final Tuple8 actual = tuple.map(f1, f2, f3, f4, f5, f6, f7, f8); assertThat(actual).isEqualTo(tuple); } @Test public void shouldReturnTuple8OfSequence8() { final Seq> iterable = List.of(Tuple.of(2, 3, 4, 5, 6, 7, 8, 9), Tuple.of(4, 5, 6, 7, 8, 9, 10, 11), Tuple.of(6, 7, 8, 9, 10, 11, 12, 13), Tuple.of(8, 9, 10, 11, 12, 13, 14, 15), Tuple.of(10, 11, 12, 13, 14, 15, 16, 17), Tuple.of(12, 13, 14, 15, 16, 17, 18, 19), Tuple.of(14, 15, 16, 17, 18, 19, 20, 21), Tuple.of(16, 17, 18, 19, 20, 21, 22, 23)); final Tuple8, Seq, Seq, Seq, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(2, 4, 6, 8, 10, 12, 14, 16), Stream.of(3, 5, 7, 9, 11, 13, 15, 17), Stream.of(4, 6, 8, 10, 12, 14, 16, 18), Stream.of(5, 7, 9, 11, 13, 15, 17, 19), Stream.of(6, 8, 10, 12, 14, 16, 18, 20), Stream.of(7, 9, 11, 13, 15, 17, 19, 21), Stream.of(8, 10, 12, 14, 16, 18, 20, 22), Stream.of(9, 11, 13, 15, 17, 19, 21, 23)); assertThat(Tuple.sequence8(iterable)).isEqualTo(expected); } @Test public void shouldReturnTuple8OfSequence1() { final Seq> iterable = List.of(Tuple.of(1, 2, 3, 4, 5, 6, 7, 8)); final Tuple8, Seq, Seq, Seq, Seq, Seq, Seq, Seq> expected = Tuple.of(Stream.of(1), Stream.of(2), Stream.of(3), Stream.of(4), Stream.of(5), Stream.of(6), Stream.of(7), Stream.of(8)); assertThat(Tuple.sequence8(iterable)).isEqualTo(expected); } @Test public void shouldMap1stComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map1(i -> "X"); final Tuple8 expected = Tuple.of("X", 1, 1, 1, 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap2ndComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map2(i -> "X"); final Tuple8 expected = Tuple.of(1, "X", 1, 1, 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap3rdComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map3(i -> "X"); final Tuple8 expected = Tuple.of(1, 1, "X", 1, 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap4thComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map4(i -> "X"); final Tuple8 expected = Tuple.of(1, 1, 1, "X", 1, 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap5thComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map5(i -> "X"); final Tuple8 expected = Tuple.of(1, 1, 1, 1, "X", 1, 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap6thComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map6(i -> "X"); final Tuple8 expected = Tuple.of(1, 1, 1, 1, 1, "X", 1, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap7thComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map7(i -> "X"); final Tuple8 expected = Tuple.of(1, 1, 1, 1, 1, 1, "X", 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMap8thComponent() { final Tuple8 actual = Tuple.of(1, 1, 1, 1, 1, 1, 1, 1).map8(i -> "X"); final Tuple8 expected = Tuple.of(1, 1, 1, 1, 1, 1, 1, "X"); assertThat(actual).isEqualTo(expected); } @Test public void shouldApplyTuple() { final Tuple8 tuple = createTuple(); final Tuple0 actual = tuple.apply((o1, o2, o3, o4, o5, o6, o7, o8) -> Tuple0.instance()); assertThat(actual).isEqualTo(Tuple0.instance()); } @Test public void shouldRecognizeEquality() { final Tuple8 tuple1 = createTuple(); final Tuple8 tuple2 = createTuple(); assertThat((Object) tuple1).isEqualTo(tuple2); } @Test public void shouldRecognizeNonEquality() { final Tuple8 tuple = createTuple(); final Object other = new Object(); assertThat(tuple).isNotEqualTo(other); } @Test public void shouldRecognizeNonEqualityPerComponent() { final Tuple8 tuple = Tuple.of("1", "2", "3", "4", "5", "6", "7", "8"); assertThat(tuple.equals(Tuple.of("X", "2", "3", "4", "5", "6", "7", "8"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "X", "3", "4", "5", "6", "7", "8"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "X", "4", "5", "6", "7", "8"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "X", "5", "6", "7", "8"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "X", "6", "7", "8"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "5", "X", "7", "8"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "5", "6", "X", "8"))).isFalse(); assertThat(tuple.equals(Tuple.of("1", "2", "3", "4", "5", "6", "7", "X"))).isFalse(); } @Test public void shouldComputeCorrectHashCode() { final int actual = createTuple().hashCode(); final int expected = Objects.hash(null, null, null, null, null, null, null, null); assertThat(actual).isEqualTo(expected); } @Test public void shouldImplementToString() { final String actual = createTuple().toString(); final String expected = "(null, null, null, null, null, null, null, null)"; assertThat(actual).isEqualTo(expected); } private Comparator> intTupleComparator = Tuple8.comparator(Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare, Integer::compare); private Tuple8 createTuple() { return new Tuple8<>(null, null, null, null, null, null, null, null); } private Tuple8 createIntTuple(Integer i1, Integer i2, Integer i3, Integer i4, Integer i5, Integer i6, Integer i7, Integer i8) { return new Tuple8<>(i1, i2, i3, i4, i5, i6, i7, i8); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/collection/000077500000000000000000000000001342074374400225125ustar00rootroot00000000000000vavr-0.10.0/vavr/src-gen/test/java/io/vavr/collection/HashMapOfEntriesTest.java000066400000000000000000000132501342074374400273560ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; public class HashMapOfEntriesTest { @Test public void shouldConstructFrom1Entries() { final HashMap map = HashMap .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get()).isEqualTo("1"); } @Test public void shouldConstructFrom2Entries() { final HashMap map = HashMap .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); } @Test public void shouldConstructFrom3Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); } @Test public void shouldConstructFrom4Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); } @Test public void shouldConstructFrom5Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); } @Test public void shouldConstructFrom6Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); } @Test public void shouldConstructFrom7Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); } @Test public void shouldConstructFrom8Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); } @Test public void shouldConstructFrom9Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); } @Test public void shouldConstructFrom10Entries() { final HashMap map = HashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); assertThat(map.get(10).get()).isEqualTo("10"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/collection/HashMultimapOfEntriesTest.java000066400000000000000000001101341342074374400304300ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.collection.Comparators.naturalComparator; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; public class HashMultimapOfEntriesTest { @Test public void shouldConstructFrom1EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSeq() { final HashMultimap map = HashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Seq).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSet() { final HashMultimap map = HashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Set).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithBuilderComparatorWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSortedSet() { final HashMultimap map = HashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/collection/LinkedHashMapOfEntriesTest.java000066400000000000000000000134461342074374400305140ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; public class LinkedHashMapOfEntriesTest { @Test public void shouldConstructFrom1Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get()).isEqualTo("1"); } @Test public void shouldConstructFrom2Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); } @Test public void shouldConstructFrom3Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); } @Test public void shouldConstructFrom4Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); } @Test public void shouldConstructFrom5Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); } @Test public void shouldConstructFrom6Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); } @Test public void shouldConstructFrom7Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); } @Test public void shouldConstructFrom8Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); } @Test public void shouldConstructFrom9Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); } @Test public void shouldConstructFrom10Entries() { final LinkedHashMap map = LinkedHashMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); assertThat(map.get(10).get()).isEqualTo("10"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/collection/LinkedHashMultimapOfEntriesTest.java000066400000000000000000001111021342074374400315530ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.collection.Comparators.naturalComparator; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; public class LinkedHashMultimapOfEntriesTest { @Test public void shouldConstructFrom1EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSeq() { final LinkedHashMultimap map = LinkedHashMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Seq).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Set).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithBuilderComparatorWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSortedSet() { final LinkedHashMultimap map = LinkedHashMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/collection/TreeMapOfEntriesTest.java000066400000000000000000000254451342074374400274030ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.collection.Comparators.naturalComparator; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; public class TreeMapOfEntriesTest { @Test public void shouldConstructFrom1EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithKeyComparator() { final TreeMap map = TreeMap .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); assertThat(map.get(10).get()).isEqualTo("10"); } @Test public void shouldConstructFrom1Entries() { final TreeMap map = TreeMap .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get()).isEqualTo("1"); } @Test public void shouldConstructFrom2Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); } @Test public void shouldConstructFrom3Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); } @Test public void shouldConstructFrom4Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); } @Test public void shouldConstructFrom5Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); } @Test public void shouldConstructFrom6Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); } @Test public void shouldConstructFrom7Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); } @Test public void shouldConstructFrom8Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); } @Test public void shouldConstructFrom9Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); } @Test public void shouldConstructFrom10Entries() { final TreeMap map = TreeMap .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get()).isEqualTo("1"); assertThat(map.get(2).get()).isEqualTo("2"); assertThat(map.get(3).get()).isEqualTo("3"); assertThat(map.get(4).get()).isEqualTo("4"); assertThat(map.get(5).get()).isEqualTo("5"); assertThat(map.get(6).get()).isEqualTo("6"); assertThat(map.get(7).get()).isEqualTo("7"); assertThat(map.get(8).get()).isEqualTo("8"); assertThat(map.get(9).get()).isEqualTo("9"); assertThat(map.get(10).get()).isEqualTo("10"); } }vavr-0.10.0/vavr/src-gen/test/java/io/vavr/collection/TreeMultimapOfEntriesTest.java000066400000000000000000002211741342074374400304530ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ G E N E R A T O R C R A F T E D \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ import static io.vavr.collection.Comparators.naturalComparator; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; public class TreeMultimapOfEntriesTest { @Test public void shouldConstructFrom1EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithKeyComparatorWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Seq).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSeq() { final TreeMultimap map = TreeMultimap.withSeq() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Seq).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Seq).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Seq).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Seq).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Seq).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Seq).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Seq).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Seq).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Seq).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Seq).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithKeyComparatorWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Set).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSet() { final TreeMultimap map = TreeMultimap.withSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof Set).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof Set).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof Set).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof Set).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof Set).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof Set).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof Set).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof Set).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof Set).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof Set).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithBuilderComparatorWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithBuilderComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet(naturalComparator()) .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithKeyComparatorWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(naturalComparator(), 1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } @Test public void shouldConstructFrom1EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1"); assertThat(map.size()).isEqualTo(1); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); } @Test public void shouldConstructFrom2EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2"); assertThat(map.size()).isEqualTo(2); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); } @Test public void shouldConstructFrom3EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3"); assertThat(map.size()).isEqualTo(3); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); } @Test public void shouldConstructFrom4EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4"); assertThat(map.size()).isEqualTo(4); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); } @Test public void shouldConstructFrom5EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5"); assertThat(map.size()).isEqualTo(5); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); } @Test public void shouldConstructFrom6EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6"); assertThat(map.size()).isEqualTo(6); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); } @Test public void shouldConstructFrom7EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7"); assertThat(map.size()).isEqualTo(7); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); } @Test public void shouldConstructFrom8EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8"); assertThat(map.size()).isEqualTo(8); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); } @Test public void shouldConstructFrom9EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9"); assertThat(map.size()).isEqualTo(9); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); } @Test public void shouldConstructFrom10EntriesWithSortedSet() { final TreeMultimap map = TreeMultimap.withSortedSet() .of(1, "1", 2, "2", 3, "3", 4, "4", 5, "5", 6, "6", 7, "7", 8, "8", 9, "9", 10, "10"); assertThat(map.size()).isEqualTo(10); assertThat(map.get(1).get() instanceof SortedSet).isTrue(); assertThat(map.get(1).get().head()).isEqualTo("1"); assertThat(map.get(2).get() instanceof SortedSet).isTrue(); assertThat(map.get(2).get().head()).isEqualTo("2"); assertThat(map.get(3).get() instanceof SortedSet).isTrue(); assertThat(map.get(3).get().head()).isEqualTo("3"); assertThat(map.get(4).get() instanceof SortedSet).isTrue(); assertThat(map.get(4).get().head()).isEqualTo("4"); assertThat(map.get(5).get() instanceof SortedSet).isTrue(); assertThat(map.get(5).get().head()).isEqualTo("5"); assertThat(map.get(6).get() instanceof SortedSet).isTrue(); assertThat(map.get(6).get().head()).isEqualTo("6"); assertThat(map.get(7).get() instanceof SortedSet).isTrue(); assertThat(map.get(7).get().head()).isEqualTo("7"); assertThat(map.get(8).get() instanceof SortedSet).isTrue(); assertThat(map.get(8).get().head()).isEqualTo("8"); assertThat(map.get(9).get() instanceof SortedSet).isTrue(); assertThat(map.get(9).get().head()).isEqualTo("9"); assertThat(map.get(10).get() instanceof SortedSet).isTrue(); assertThat(map.get(10).get().head()).isEqualTo("10"); } }vavr-0.10.0/vavr/src/000077500000000000000000000000001342074374400143235ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/000077500000000000000000000000001342074374400152475ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/java/000077500000000000000000000000001342074374400161705ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/java/io/000077500000000000000000000000001342074374400165775ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/java/io/vavr/000077500000000000000000000000001342074374400175555ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/java/io/vavr/$.java000066400000000000000000000070401342074374400205440ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.control.Either; import io.vavr.control.Try; import io.vavr.control.Validation; import io.vavr.match.annotation.Patterns; import io.vavr.match.annotation.Unapply; import io.vavr.collection.List; import io.vavr.concurrent.Future; import io.vavr.control.Option; /** * INTERNAL TYPE - turned to io.vavr.Patterns by vavr-match annotation processor. */ @Patterns class $ { // -- io.vavr // Tuple0-N @Unapply static Tuple0 Tuple0(Tuple0 tuple0) { return tuple0; } @Unapply static Tuple1 Tuple1(Tuple1 tuple1) { return tuple1; } @Unapply static Tuple2 Tuple2(Tuple2 tuple2) { return tuple2; } @Unapply static Tuple3 Tuple3(Tuple3 tuple3) { return tuple3; } @Unapply static Tuple4 Tuple4(Tuple4 tuple4) { return tuple4; } @Unapply static Tuple5 Tuple5(Tuple5 tuple5) { return tuple5; } @Unapply static Tuple6 Tuple6(Tuple6 tuple6) { return tuple6; } @Unapply static Tuple7 Tuple7(Tuple7 tuple7) { return tuple7; } @Unapply static Tuple8 Tuple8(Tuple8 tuple8) { return tuple8; } // -- io.vavr.collection // List @Unapply static Tuple2> Cons(List.Cons cons) { return Tuple.of(cons.head(), cons.tail()); } @Unapply static Tuple0 Nil(List.Nil nil) { return Tuple.empty(); } // -- io.vavr.concurrent @Unapply static Tuple1>> Future(Future future) { return Tuple.of(future.getValue()); } // -- io.vavr.control // Either @Unapply static Tuple1 Right(Either.Right right) { return Tuple.of(right.get()); } @Unapply static Tuple1 Left(Either.Left left) { return Tuple.of(left.getLeft()); } // Option @Unapply static Tuple1 Some(Option.Some some) { return Tuple.of(some.get()); } @Unapply static Tuple0 None(Option.None none) { return Tuple.empty(); } // Try @Unapply static Tuple1 Success(Try.Success success) { return Tuple.of(success.get()); } @Unapply static Tuple1 Failure(Try.Failure failure) { return Tuple.of(failure.getCause()); } // Validation @Unapply static Tuple1 Valid(Validation.Valid valid) { return Tuple.of(valid.get()); } @Unapply static Tuple1 Invalid(Validation.Invalid invalid) { return Tuple.of(invalid.getError()); } } vavr-0.10.0/vavr/src/main/java/io/vavr/CheckedConsumer.java000066400000000000000000000063511342074374400234670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import java.util.Objects; import java.util.function.Consumer; import static io.vavr.CheckedConsumerModule.sneakyThrow; /** * A consumer that may throw, equivalent to {@linkplain java.util.function.Consumer}. * * @param the value type supplied to this consumer. */ @FunctionalInterface public interface CheckedConsumer { /** * Creates a {@code CheckedConsumer}. * *
{@code
     * final CheckedConsumer checkedConsumer = CheckedConsumer.of(Value::stdout);
     * final Consumer consumer = checkedConsumer.unchecked();
     *
     * // prints "Hi" on the console
     * consumer.accept(CharSeq.of("Hi!"));
     *
     * // throws
     * consumer.accept(null);
     * }
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param type of values that are accepted by the consumer * @return a new {@code CheckedConsumer} * @see CheckedFunction1#of(CheckedFunction1) */ static CheckedConsumer of(CheckedConsumer methodReference) { return methodReference; } /** * Performs side-effects. * * @param t a value of type {@code T} * @throws Throwable if an error occurs */ void accept(T t) throws Throwable; /** * Returns a chained {@code CheckedConsumer} that first executes {@code this.accept(t)} * and then {@code after.accept(t)}, for a given {@code t} of type {@code T}. * * @param after the action that will be executed after this action * @return a new {@code CheckedConsumer} that chains {@code this} and {@code after} * @throws NullPointerException if {@code after} is null */ default CheckedConsumer andThen(CheckedConsumer after) { Objects.requireNonNull(after, "after is null"); return (T t) -> { accept(t); after.accept(t); }; } /** * Returns an unchecked {@link Consumer} that will sneaky throw if an exceptions occurs when accepting a value. * * @return a new {@link Consumer} that throws a {@code Throwable}. */ default Consumer unchecked() { return t -> { try { accept(t); } catch(Throwable x) { sneakyThrow(x); } }; } } interface CheckedConsumerModule { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } } vavr-0.10.0/vavr/src/main/java/io/vavr/CheckedPredicate.java000066400000000000000000000055761342074374400236040ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import java.util.function.Predicate; import static io.vavr.CheckedPredicateModule.sneakyThrow; /** * A {@linkplain java.util.function.Predicate} which may throw. * * @param the type of the input to the predicate */ @FunctionalInterface public interface CheckedPredicate { /** * Creates a {@code CheckedPredicate}. * *
{@code
     * final CheckedPredicate checkedPredicate = CheckedPredicate.of(Boolean::booleanValue);
     * final Predicate predicate = checkedPredicate.unchecked();
     *
     * // = true
     * predicate.test(Boolean.TRUE);
     *
     * // throws
     * predicate.test(null);
     * }
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @param type of values that are tested by the predicate * @return a new {@code CheckedPredicate} * @see CheckedFunction1#of(CheckedFunction1) */ static CheckedPredicate of(CheckedPredicate methodReference) { return methodReference; } /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, otherwise {@code false} * @throws Throwable if an error occurs */ boolean test(T t) throws Throwable; /** * Negates this predicate. * * @return A new CheckedPredicate. */ default CheckedPredicate negate() { return t -> !test(t); } /** * Returns an unchecked {@link Predicate} that will sneaky throw if an exceptions occurs when testing a value. * * @return a new {@link Predicate} that throws a {@code Throwable}. */ default Predicate unchecked() { return t -> { try { return test(t); } catch(Throwable x) { return sneakyThrow(x); } }; } } interface CheckedPredicateModule { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } } vavr-0.10.0/vavr/src/main/java/io/vavr/CheckedRunnable.java000066400000000000000000000047001342074374400234360ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import static io.vavr.CheckedRunnableModule.sneakyThrow; /** * A {@linkplain Runnable} which may throw. */ @FunctionalInterface public interface CheckedRunnable { /** * Creates a {@code CheckedRunnable}. * *
{@code
     * // class Evil { static void sideEffect() { ... } }
     * final CheckedRunnable checkedRunnable = CheckedRunnable.of(Evil::sideEffect);
     * final Runnable runnable = checkedRunnable.unchecked();
     *
     * // may or may not perform a side-effect while not throwing
     * runnable.run();
     *
     * // may or may not perform a side-effect while throwing
     * runnable.run();
     * }
* * @param methodReference (typically) a method reference, e.g. {@code Type::method} * @return a new {@code CheckedRunnable} * @see CheckedFunction1#of(CheckedFunction1) */ static CheckedRunnable of(CheckedRunnable methodReference) { return methodReference; } /** * Performs side-effects. * * @throws Throwable if an error occurs */ void run() throws Throwable; /** * Returns an unchecked {@link Runnable} that will sneaky throw if an exceptions occurs when running the unit of work. * * @return a new {@link Runnable} that throws a {@code Throwable}. */ default Runnable unchecked() { return () -> { try { run(); } catch(Throwable x) { sneakyThrow(x); } }; } } interface CheckedRunnableModule { // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } } vavr-0.10.0/vavr/src/main/java/io/vavr/GwtIncompatible.java000066400000000000000000000017311342074374400235120ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2018 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import java.lang.annotation.*; @Retention(RetentionPolicy.CLASS) @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD }) @Documented @interface GwtIncompatible { String value() default ""; } vavr-0.10.0/vavr/src/main/java/io/vavr/Lazy.java000066400000000000000000000207401342074374400213420ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.Iterator; import io.vavr.collection.Seq; import io.vavr.collection.Vector; import io.vavr.control.Option; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * Represents a lazy evaluated value. Compared to a Supplier, Lazy is memoizing, i.e. it evaluates only once and * therefore is referential transparent. * *
 * 
 * final Lazy<Double> l = Lazy.of(Math::random);
 * l.isEvaluated(); // = false
 * l.get();         // = 0.123 (random generated)
 * l.isEvaluated(); // = true
 * l.get();         // = 0.123 (memoized)
 * 
 * 
* * Example of creating a real lazy value (works only with interfaces): * *
final CharSequence chars = Lazy.val(() -> "Yay!", CharSequence.class);
* * @author Daniel Dietrich */ // DEV-NOTE: No flatMap and orElse because this more like a Functor than a Monad. // It represents a value rather than capturing a specific state. public final class Lazy implements Value, Supplier, Serializable { private static final long serialVersionUID = 1L; // read http://javarevisited.blogspot.de/2014/05/double-checked-locking-on-singleton-in-java.html private transient volatile Supplier supplier; private T value; // will behave as a volatile in reality, because a supplier volatile read will update all fields (see https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile) // should not be called directly private Lazy(Supplier supplier) { this.supplier = supplier; } /** * Narrows a widened {@code Lazy} to {@code Lazy} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param lazy A {@code Lazy}. * @param Component type of the {@code Lazy}. * @return the given {@code lazy} instance as narrowed type {@code Lazy}. */ @SuppressWarnings("unchecked") public static Lazy narrow(Lazy lazy) { return (Lazy) lazy; } /** * Creates a {@code Lazy} that requests its value from a given {@code Supplier}. The supplier is asked only once, * the value is memoized. * * @param type of the lazy value * @param supplier A supplier * @return A new instance of Lazy */ @SuppressWarnings("unchecked") public static Lazy of(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); if (supplier instanceof Lazy) { return (Lazy) supplier; } else { return new Lazy<>(supplier); } } /** * Reduces many {@code Lazy} values into a single {@code Lazy} by transforming an * {@code Iterable>} into a {@code Lazy>}. * * @param Type of the lazy values. * @param values An iterable of lazy values. * @return A lazy sequence of values. * @throws NullPointerException if values is null */ @SuppressWarnings("Convert2MethodRef") // TODO should be fixed in JDK 9 and Idea public static Lazy> sequence(Iterable> values) { Objects.requireNonNull(values, "values is null"); return Lazy.of(() -> Vector.ofAll(values).map(lazy -> lazy.get())); } /** * Creates a real _lazy value_ of type {@code T}, backed by a {@linkplain java.lang.reflect.Proxy} which delegates * to a {@code Lazy} instance. * * @param supplier A supplier * @param type An interface * @param type of the lazy value * @return A new instance of T */ @GwtIncompatible("reflection is not supported") @SuppressWarnings("unchecked") public static T val(Supplier supplier, Class type) { Objects.requireNonNull(supplier, "supplier is null"); Objects.requireNonNull(type, "type is null"); if (!type.isInterface()) { throw new IllegalArgumentException("type has to be an interface"); } final Lazy lazy = Lazy.of(supplier); final InvocationHandler handler = (proxy, method, args) -> method.invoke(lazy.get(), args); return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, handler); } public Option filter(Predicate predicate) { final T v = get(); return predicate.test(v) ? Option.some(v) : Option.none(); } /** * Evaluates this lazy value and caches it, when called the first time. * On subsequent calls, returns the cached value. * * @return the lazy evaluated value */ @Override public T get() { return (supplier == null) ? value : computeValue(); } private synchronized T computeValue() { final Supplier s = supplier; if (s != null) { value = s.get(); supplier = null; } return value; } /** * A {@code Lazy}'s value is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return false; } /** * Checks, if this lazy value is evaluated. *

* Note: A value is internally evaluated (once) by calling {@link #get()}. * * @return true, if the value is evaluated, false otherwise. * @throws UnsupportedOperationException if this value is undefined */ public boolean isEvaluated() { return supplier == null; } /** * A {@code Lazy}'s value is computed lazily. * * @return true */ @Override public boolean isLazy() { return true; } @Override public boolean isSingleValued() { return true; } @Override public Iterator iterator() { return Iterator.of(get()); } @Override public Lazy map(Function mapper) { return Lazy.of(() -> mapper.apply(get())); } @Override public Lazy peek(Consumer action) { action.accept(get()); return this; } /** * Transforms this {@code Lazy}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public String stringPrefix() { return "Lazy"; } @Override public boolean equals(Object o) { return (o == this) || (o instanceof Lazy && Objects.equals(((Lazy) o).get(), get())); } @Override public int hashCode() { return Objects.hashCode(get()); } @Override public String toString() { return stringPrefix() + "(" + (!isEvaluated() ? "?" : value) + ")"; } /** * Ensures that the value is evaluated before serialization. * * @param s An object serialization stream. * @throws java.io.IOException If an error occurs writing to the stream. */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void writeObject(ObjectOutputStream s) throws IOException { get(); // evaluates the lazy value if it isn't evaluated yet! s.defaultWriteObject(); } } vavr-0.10.0/vavr/src/main/java/io/vavr/MatchError.java000066400000000000000000000027401342074374400224710ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import java.util.NoSuchElementException; /** * A {@link API.Match} throws a MatchError if no case matches the applied object. * * @author Daniel Dietrich */ public class MatchError extends NoSuchElementException { private static final long serialVersionUID = 1L; private final Object obj; /** * Internally called by {@link API.Match}. * * @param obj The object which could not be matched. */ MatchError(Object obj) { super((obj == null) ? "null" : "type: " + obj.getClass().getName() + ", value: " + obj); this.obj = obj; } /** * Returns the object which could not be matched. * * @return An Object. */ public Object getObject() { return obj; } } vavr-0.10.0/vavr/src/main/java/io/vavr/Memoized.java000066400000000000000000000001561342074374400221730ustar00rootroot00000000000000package io.vavr; /** * INTERNAL. Zero abstract method (ZAM) / tagging interface. */ interface Memoized { } vavr-0.10.0/vavr/src/main/java/io/vavr/NotImplementedError.java000066400000000000000000000027551342074374400243670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; /** * This exception is temporarily used during development in order to indicate that an implementation is missing. *

* The idiomatic way is to use one of {@link API#TODO()} and {@link API#TODO(String)}. */ public class NotImplementedError extends Error { private static final long serialVersionUID = 1L; /** * Creates a {@code NotImplementedError} containing the message "an implementation is missing". */ public NotImplementedError() { super("An implementation is missing."); } /** * Creates a {@code NotImplementedError} containing the given {@code message}. * * @param message A text that describes the error */ public NotImplementedError(String message) { super(message); } } vavr-0.10.0/vavr/src/main/java/io/vavr/PartialFunction.java000066400000000000000000000114631342074374400235270ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.control.Option; import java.util.function.Function; /** * Represents a partial function T -> R that is not necessarily defined for all input values of type T. * The caller is responsible for calling the method isDefinedAt() before this function is applied to the value. *

* If the function is not defined for a specific value, apply() may produce an arbitrary result. * More specifically it is not guaranteed that the function will throw an exception. *

* If the function is defined for a specific value, apply() may still throw an exception. * * @param type of the function input, called domain of the function * @param type of the function output, called codomain of the function * @author Daniel Dietrich */ public interface PartialFunction extends Function1 { /** * The serial version uid. */ long serialVersionUID = 1L; /** * Unlifts a {@code totalFunction} that returns an {@code Option} result into a partial function. * The total function should be side effect free because it might be invoked twice: when checking if the * unlifted partial function is defined at a value and when applying the partial function to a value. * * @param totalFunction the function returning an {@code Option} result. * @param type of the function input, called domain of the function * @param type of the function output, called codomain of the function * @return a partial function that is not necessarily defined for all input values of type T. */ static PartialFunction unlift(Function> totalFunction) { return new PartialFunction() { private static final long serialVersionUID = 1L; @Override public R apply(T t) { return totalFunction.apply(t).get(); } @Override public boolean isDefinedAt(T value) { return totalFunction.apply(value).isDefined(); } }; } /** * Factory method for creating a partial function that maps a given {@code Value} to its underlying value. * The partial function is defined for an input {@code Value} if and only if the input {@code Value} is not * empty. If the input {@code Value} is not empty, the partial function will return the underlying value of * the input {@code Value}. * * @param type of the underlying value of the input {@code Value}. * @param type of the function input, called domain of the function * @return a partial function that maps a {@code Value} to its underlying value. */ static > PartialFunction getIfDefined() { return new PartialFunction() { private static final long serialVersionUID = 1L; @Override public T apply(V v) { return v.get(); } @Override public boolean isDefinedAt(V v) { return !v.isEmpty(); } }; } /** * Applies this function to the given argument and returns the result. * * @param t the argument * @return the result of function application * */ R apply(T t); /** * Tests if a value is contained in the function's domain. * * @param value a potential function argument * @return true, if the given value is contained in the function's domain, false otherwise */ boolean isDefinedAt(T value); /** * Lifts this partial function into a total function that returns an {@code Option} result. * * @return a function that applies arguments to this function and returns {@code Some(result)} * if the function is defined for the given arguments, and {@code None} otherwise. */ default Function1> lift() { return t -> Option.when(isDefinedAt(t), apply(t)); } } vavr-0.10.0/vavr/src/main/java/io/vavr/Predicates.java000066400000000000000000000236431342074374400225130ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.Iterator; import io.vavr.collection.List; import java.util.Objects; import java.util.function.Predicate; /** * Defines general-purpose predicates which are particularly useful when working with {@link API.Match}. * * @author Daniel Dietrich, Grzegorz Piwowarek */ public final class Predicates { // hidden private Predicates() { } /** * A combinator that checks if all of the given {@code predicates} are satisfied. *

* By definition {@code allOf} is satisfied if the given {@code predicates} are empty. * *

{@code
     * Predicate isGreaterThanOne = i -> i > 1;
     * Predicate isGreaterThanTwo = i -> i > 2;
     * allOf().test(0);                                   // true
     * allOf(isGreaterThanOne, isGreaterThanTwo).test(3); // true
     * allOf(isGreaterThanOne, isGreaterThanTwo).test(2); // false
     * }
* * @param predicates An array of predicates * @param closure over tested object types * @return A new {@code Predicate} * @throws NullPointerException if {@code predicates} is null */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public static Predicate allOf(Predicate... predicates) { Objects.requireNonNull(predicates, "predicates is null"); return t -> List.of(predicates).foldLeft(true, (bool, pred) -> bool && pred.test(t)); } /** * A combinator that checks if at least one of the given {@code predicates} is satisfies. * *
{@code
     * Predicate isGreaterThanOne = i -> i > 1;
     * Predicate isGreaterThanTwo = i -> i > 2;
     * anyOf().test(0);                                   // false
     * anyOf(isGreaterThanOne, isGreaterThanTwo).test(3); // true
     * anyOf(isGreaterThanOne, isGreaterThanTwo).test(2); // true
     * anyOf(isGreaterThanOne, isGreaterThanTwo).test(1); // false
     * }
* * @param predicates An array of predicates * @param closure over tested object types * @return A new {@code Predicate} * @throws NullPointerException if {@code predicates} is null */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public static Predicate anyOf(Predicate... predicates) { Objects.requireNonNull(predicates, "predicates is null"); return t -> List.of(predicates).find(pred -> pred.test(t)).isDefined(); } /** * A combinator that checks if one or more elements of an {@code Iterable} satisfy the {@code predicate}. * *
{@code
     * Predicate isGreaterThanOne = i -> i > 1;
     * Predicate> existsGreaterThanOne = exists(isGreaterThanOne);
     * existsGreaterThanOne.test(List.of(0, 1, 2)); // true
     * existsGreaterThanOne.test(List.of(0, 1));    // false
     * }
* * @param predicate A {@code Predicate} that tests elements of type {@code T} * @param tested object type * @return A new {@code Predicate} * @throws NullPointerException if {@code predicate} is null */ public static Predicate> exists(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterable -> Iterator.ofAll(iterable).exists(predicate); } /** * A combinator that checks if all elements of an {@code Iterable} satisfy the {@code predicate}. * *
{@code
     * Predicate isGreaterThanOne = i -> i > 1;
     * Predicate> forAllGreaterThanOne = forAll(isGreaterThanOne);
     * forAllGreaterThanOne.test(List.of(0, 1, 2)); // false
     * forAllGreaterThanOne.test(List.of(2, 3, 4)); // true
     * }
* * @param predicate A {@code Predicate} that tests elements of type {@code T} * @param tested object type * @return A new {@code Predicate} * @throws NullPointerException if {@code predicate} is null */ public static Predicate> forAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterable -> Iterator.ofAll(iterable).forAll(predicate); } /** * Creates a {@code Predicate} that tests, if an object is instance of the specified {@code type}. * *
{@code
     * Predicate instanceOfNumber = instanceOf(Number.class);
     * instanceOfNumber.test(1);    // true
     * instanceOfNumber.test("1");  // false
     * }
     *
     * @param type A type
     * @param   tested object type
     * @return A new {@code Predicate}
     * @throws NullPointerException if {@code type} is null
     */
    // DEV-NOTE: We need Class instead of Class, see {@link TryTest#shouldRecoverSuccessUsingCase()}
    @GwtIncompatible
    public static  Predicate instanceOf(Class type) {
        Objects.requireNonNull(type, "type is null");
        return obj -> obj != null && type.isAssignableFrom(obj.getClass());
    }

    /**
     * Creates a {@code Predicate} that tests, if an object is equal to the specified {@code value} using
     * {@link Objects#equals(Object, Object)} for comparison.
     *
     * 
{@code
     * Predicate isOne = is(1);
     * isOne.test(1); // true
     * isOne.test(2); // false
     * }
* * @param value A value, may be null * @param tested object type * @return A new {@code Predicate} */ public static Predicate is(T value) { return obj -> Objects.equals(obj, value); } /** * Creates a {@code Predicate} that tests, if an object is equal to at least one of the specified {@code values} * using {@link Objects#equals(Object, Object)} for comparison. * *
{@code
     * Predicate isIn = isIn(1, 2, 3);
     * isIn.test(1); // true
     * isIn.test(0); // false
     * }
* * @param values an array of values of type T * @param closure over tested object types * @return A new {@code Predicate} * @throws NullPointerException if {@code values} is null */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public static Predicate isIn(T... values) { Objects.requireNonNull(values, "values is null"); return obj -> List.of(values).find(value -> Objects.equals(value, obj)).isDefined(); } /** * Creates a {@code Predicate} that tests, if an object is not null * *
{@code
     * Predicate isNotNull = isNotNull();
     * isNotNull.test(0);    // true
     * isNotNull.test(null); // false
     * }
* * @param tested object type * @return A new {@code Predicate} */ public static Predicate isNotNull() { return Objects::nonNull; } /** * Creates a {@code Predicate} that tests, if an object is null * *
{@code
     * Predicate isNull = isNull();
     * isNull.test(null); // true
     * isNull.test(0);    // false
     * }
* * @param tested object type * @return A new {@code Predicate} */ public static Predicate isNull() { return Objects::isNull; } /** * A combinator that checks if none of the given {@code predicates} is satisfied. *

* Naturally {@code noneOf} is satisfied if the given {@code predicates} are empty. * *

{@code
     * Predicate isGreaterThanOne = i -> i > 1;
     * Predicate isGreaterThanTwo = i -> i > 2;
     * noneOf().test(0);                                   // true
     * noneOf(isGreaterThanOne, isGreaterThanTwo).test(1); // true
     * noneOf(isGreaterThanOne, isGreaterThanTwo).test(2); // false
     * }
* * @param predicates An array of predicates * @param closure over tested object types * @return A new {@code Predicate} * @throws NullPointerException if {@code predicates} is null */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public static Predicate noneOf(Predicate... predicates) { Objects.requireNonNull(predicates, "predicates is null"); return anyOf(predicates).negate(); } /** * Negates a given {@code Predicate}. * *
{@code
     * // negates a method reference
     * Predicate isNotNull1 = not(Objects::isNull);
     * isNotNull1.test("");   // true
     * isNotNull1.test(null); // false
     *
     * // negates a predicate instance
     * Predicate isNotNull2 = not(Predicates.isNull());
     * isNotNull2.test("");   // true
     * isNotNull2.test(null); // false
     * }
* * @param predicate A {@code Predicate} that tests elements of type {@code T} * @param tested object type * @return A new {@code Predicate} * @throws NullPointerException if {@code predicate} is null */ @SuppressWarnings("unchecked") public static Predicate not(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return (Predicate) predicate.negate(); } } vavr-0.10.0/vavr/src/main/java/io/vavr/Value.java000066400000000000000000001564441342074374400215120ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.Array; import io.vavr.collection.CharSeq; import io.vavr.collection.HashMap; import io.vavr.collection.HashSet; import io.vavr.collection.Iterator; import io.vavr.collection.LinkedHashMap; import io.vavr.collection.LinkedHashSet; import io.vavr.collection.List; import io.vavr.collection.Map; import io.vavr.collection.*; import io.vavr.collection.PriorityQueue; import io.vavr.collection.Queue; import io.vavr.collection.Set; import io.vavr.collection.SortedMap; import io.vavr.collection.SortedSet; import io.vavr.collection.Stream; import io.vavr.collection.TreeMap; import io.vavr.collection.TreeSet; import io.vavr.collection.Vector; import io.vavr.concurrent.Future; import io.vavr.control.Either; import io.vavr.control.Option; import io.vavr.control.Try; import io.vavr.control.Validation; import java.io.PrintStream; import java.io.PrintWriter; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.*; import java.util.function.Function; import java.util.stream.Collector; import java.util.stream.StreamSupport; import static io.vavr.API.*; /** * Functional programming is all about values and transformation of values using functions. The {@code Value} * type reflects the values in a functional setting. It can be seen as the result of a partial function application. * Hence the result may be undefined. If a value is undefined, we say it is empty. *

* How the empty state is interpreted depends on the context, i.e. it may be undefined, failed, * no elements, etc. *

* Basic operations: * *

    *
  • {@link #get()}
  • *
  • {@link #getOrElse(Object)}
  • *
  • {@link #getOrElse(Supplier)}
  • *
  • {@link #getOrElseThrow(Supplier)}
  • *
  • {@link #getOrElseTry(CheckedFunction0)}
  • *
  • {@link #getOrNull()}
  • *
  • {@link #map(Function)}
  • *
  • {@link #stringPrefix()}
  • *
* * Equality checks: * *
    *
  • {@link #corresponds(Iterable, BiPredicate)}
  • *
  • {@link #eq(Object)}
  • *
* * Iterable extensions: * *
    *
  • {@link #contains(Object)}
  • *
  • {@link #exists(Predicate)}
  • *
  • {@link #forAll(Predicate)}
  • *
  • {@link #forEach(Consumer)}
  • *
  • {@link #iterator()}
  • *
* * Side-effects: * *
    *
  • {@link #out(PrintStream)}
  • *
  • {@link #out(PrintWriter)}
  • *
  • {@link #peek(Consumer)}
  • *
  • {@link #stderr()}
  • *
  • {@link #stdout()}
  • *
* * Tests: * *
    *
  • {@link #isAsync()}
  • *
  • {@link #isEmpty()}
  • *
  • {@link #isLazy()}
  • *
  • {@link #isSingleValued()}
  • *
* * Type conversion: * *
    *
  • {@link #collect(Collector)}
  • *
  • {@link #collect(Supplier, BiConsumer, BiConsumer)}
  • *
  • {@link #toArray()}
  • *
  • {@link #toCharSeq()}
  • *
  • {@link #toEither(Object)}
  • *
  • {@link #toEither(Supplier)}
  • *
  • {@link #toInvalid(Object)}
  • *
  • {@link #toInvalid(Supplier)}
  • *
  • {@link #toJavaArray()}
  • *
  • {@link #toJavaArray(Class)}
  • *
  • {@link #toJavaCollection(Function)}
  • *
  • {@link #toJavaList()}
  • *
  • {@link #toJavaList(Function)}
  • *
  • {@link #toJavaMap(Function)}
  • *
  • {@link #toJavaMap(Supplier, Function)}
  • *
  • {@link #toJavaMap(Supplier, Function, Function)}
  • *
  • {@link #toJavaOptional()}
  • *
  • {@link #toJavaParallelStream()}
  • *
  • {@link #toJavaSet()}
  • *
  • {@link #toJavaSet(Function)}
  • *
  • {@link #toJavaStream()}
  • *
  • {@link #toLeft(Object)}
  • *
  • {@link #toLeft(Supplier)}
  • *
  • {@link #toLinkedMap(Function)}
  • *
  • {@link #toLinkedMap(Function, Function)}
  • *
  • {@link #toLinkedSet()}
  • *
  • {@link #toList()}
  • *
  • {@link #toMap(Function)}
  • *
  • {@link #toMap(Function, Function)}
  • *
  • {@link #toOption()}
  • *
  • {@link #toPriorityQueue()}
  • *
  • {@link #toPriorityQueue(Comparator)}
  • *
  • {@link #toQueue()}
  • *
  • {@link #toRight(Object)}
  • *
  • {@link #toRight(Supplier)}
  • *
  • {@link #toSet()}
  • *
  • {@link #toSortedMap(Comparator, Function)}
  • *
  • {@link #toSortedMap(Comparator, Function, Function)}
  • *
  • {@link #toSortedMap(Function)}
  • *
  • {@link #toSortedMap(Function, Function)}
  • *
  • {@link #toSortedSet()}
  • *
  • {@link #toSortedSet(Comparator)}
  • *
  • {@link #toStream()}
  • *
  • {@link #toString()}
  • *
  • {@link #toTree()}
  • *
  • {@link #toTry()}
  • *
  • {@link #toTry(Supplier)}
  • *
  • {@link #toValid(Object)}
  • *
  • {@link #toValid(Supplier)}
  • *
  • {@link #toValidation(Object)}
  • *
  • {@link #toValidation(Supplier)}
  • *
  • {@link #toVector()}
  • *
* * Please note: flatMap signatures are manifold and have to be declared by subclasses of Value. * * @param The type of the wrapped value. * @author Daniel Dietrich */ public interface Value extends Iterable { /** * Narrows a widened {@code Value} to {@code Value} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param value A {@code Value}. * @param Component type of the {@code Value}. * @return the given {@code value} instance as narrowed type {@code Value}. */ @SuppressWarnings("unchecked") static Value narrow(Value value) { return (Value) value; } /** * Collects the underlying value(s) (if present) using the provided {@code collector}. * * @param the mutable accumulation type of the reduction operation * @param the result type of the reduction operation * @param collector Collector performing reduction * @return R reduction result */ default R collect(Collector collector) { return StreamSupport.stream(spliterator(), false).collect(collector); } /** * Collects the underlying value(s) (if present) using the given {@code supplier}, {@code accumulator} and * {@code combiner}. * * @param type of the result * @param supplier provide unit value for reduction * @param accumulator perform reduction with unit value * @param combiner function for combining two values, which must be * compatible with the accumulator. * @return R reduction result */ default R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) { return StreamSupport.stream(spliterator(), false).collect(supplier, accumulator, combiner); } /** * Shortcut for {@code exists(e -> Objects.equals(e, element))}, tests if the given {@code element} is contained. * * @param element An Object of type A, may be null. * @return true, if element is contained, false otherwise. */ default boolean contains(T element) { return exists(e -> Objects.equals(e, element)); } /** * Tests whether every element of this iterable relates to the corresponding element of another iterable by * satisfying a test predicate. * * @param Component type of that iterable * @param that the other iterable * @param predicate the test predicate, which relates elements from both iterables * @return {@code true} if both iterables have the same length and {@code predicate(x, y)} * is {@code true} for all corresponding elements {@code x} of this iterable and {@code y} of {@code that}, * otherwise {@code false}. */ default boolean corresponds(Iterable that, BiPredicate predicate) { final java.util.Iterator it1 = iterator(); final java.util.Iterator it2 = that.iterator(); while (it1.hasNext() && it2.hasNext()) { if (!predicate.test(it1.next(), it2.next())) { return false; } } return !it1.hasNext() && !it2.hasNext(); } /** * A smoothing replacement for {@code equals}. It is similar to Scala's {@code ==} but better in the way * that it is not limited to collection types, e.g. {@code Some(1) eq List(1)}, {@code None eq Failure(x)} etc. *

* In a nutshell: eq checks congruence of structures and equality of contained values. *

* Example: * *


     * // ((1, 2), ((3))) => structure: (()(())) values: 1, 2, 3
     * final Value<?> i1 = List.of(List.of(1, 2), Arrays.asList(List.of(3)));
     * final Value<?> i2 = Queue.of(Stream.of(1, 2), List.of(Lazy.of(() -> 3)));
     * assertThat(i1.eq(i2)).isTrue();
     * 
*

* Semantics: * *


     * o == this             : true
     * o instanceof Value    : iterable elements are eq, non-iterable elements equals, for all (o1, o2) in (this, o)
     * o instanceof Iterable : this eq Iterator.of((Iterable<?>) o);
     * otherwise             : false
     * 
* * @param o An object * @return true, if this equals o according to the rules defined above, otherwise false. */ default boolean eq(Object o) { if (o == this) { return true; } else if (o instanceof Value) { final Value that = (Value) o; return this.iterator().corresponds(that.iterator(), (o1, o2) -> { if (o1 instanceof Value) { return ((Value) o1).eq(o2); } else if (o2 instanceof Value) { return ((Value) o2).eq(o1); } else { return Objects.equals(o1, o2); } }); } else if (o instanceof Iterable) { final Value that = Iterator.ofAll((Iterable) o); return this.eq(that); } else { return false; } } /** * Checks, if an element exists such that the predicate holds. * * @param predicate A Predicate * @return true, if predicate holds for one or more elements, false otherwise * @throws NullPointerException if {@code predicate} is null */ default boolean exists(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (T t : this) { if (predicate.test(t)) { return true; } } return false; } /** * Checks, if the given predicate holds for all elements. * * @param predicate A Predicate * @return true, if the predicate holds for all elements, false otherwise * @throws NullPointerException if {@code predicate} is null */ default boolean forAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return !exists(predicate.negate()); } /** * Performs an action on each element. * * @param action A {@code Consumer} * @throws NullPointerException if {@code action} is null */ @Override default void forEach(Consumer action) { Objects.requireNonNull(action, "action is null"); for (T t : this) { action.accept(t); } } /** * Gets the underlying value or throws if no value is present. *

* IMPORTANT! This method will throw an undeclared {@link Throwable} if {@code isEmpty() == true} is true. *

* Because the 'empty' state indicates that there is no value present that can be returned, * {@code get()} has to throw in such a case. Generally, implementing classes should throw a * {@link java.util.NoSuchElementException} if {@code isEmpty()} returns true. *

* However, there exist use-cases, where implementations may throw other exceptions. See {@link Try#get()}. *

* Additional note: Dynamic proxies will wrap an undeclared exception in a {@link java.lang.reflect.UndeclaredThrowableException}. * * @return the underlying value if this is not empty, otherwise {@code get()} throws a {@code Throwable} */ T get(); /** * Returns the underlying value if present, otherwise {@code other}. * * @param other An alternative value. * @return A value of type {@code T} */ default T getOrElse(T other) { return isEmpty() ? other : get(); } /** * Returns the underlying value if present, otherwise {@code other}. * * @param supplier An alternative value supplier. * @return A value of type {@code T} * @throws NullPointerException if supplier is null */ default T getOrElse(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isEmpty() ? supplier.get() : get(); } /** * Returns the underlying value if present, otherwise throws {@code supplier.get()}. * * @param a Throwable type * @param supplier An exception supplier. * @return A value of type {@code T}. * @throws NullPointerException if supplier is null * @throws X if no value is present */ default T getOrElseThrow(Supplier supplier) throws X { Objects.requireNonNull(supplier, "supplier is null"); if (isEmpty()) { throw supplier.get(); } else { return get(); } } /** * Returns the underlying value if present, otherwise returns the result of {@code Try.of(supplier).get()}. * * @param supplier An alternative value supplier. * @return A value of type {@code T}. * @throws NullPointerException if supplier is null */ default T getOrElseTry(CheckedFunction0 supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isEmpty() ? Try.of(supplier).get() : get(); } /** * Returns the underlying value if present, otherwise {@code null}. * * @return A value of type {@code T} or {@code null}. */ default T getOrNull() { return isEmpty() ? null : get(); } /** * Checks if this {@code Value} is asynchronously (short: async) computed. *

* Methods of a {@code Value} instance that operate on the underlying value may block the current thread * until the value is present and the computation can be performed. * * @return true if this {@code Value} is async (like {@link io.vavr.concurrent.Future}), false otherwise. */ boolean isAsync(); /** * Checks, this {@code Value} is empty, i.e. if the underlying value is absent. * * @return false, if no underlying value is present, true otherwise. */ boolean isEmpty(); /** * Checks if this {@code Value} is lazily evaluated. * * @return true if this {@code Value} is lazy (like {@link Lazy} and {@link Stream}), false otherwise. */ boolean isLazy(); /** * States whether this is a single-valued type. * * @return {@code true} if this is single-valued, {@code false} otherwise. */ boolean isSingleValued(); /** * Maps the underlying value to a different component type. * * @param mapper A mapper * @param The new component type * @return A new value */ Value map(Function mapper); /** * Performs the given {@code action} on the first element if this is an eager implementation. * Performs the given {@code action} on all elements (the first immediately, successive deferred), * if this is a lazy implementation. * * @param action The action that will be performed on the element(s). * @return this instance */ Value peek(Consumer action); /** * Returns the name of this Value type, which is used by toString(). * * @return This type name. */ String stringPrefix(); // -- output /** * Sends the string representations of this to the {@link PrintStream}. * If this value consists of multiple elements, each element is displayed in a new line. * * @param out The PrintStream to write to * @throws IllegalStateException if {@code PrintStream.checkError()} is true after writing to stream. */ @GwtIncompatible("java.io.PrintStream is not implemented") default void out(PrintStream out) { for (T t : this) { out.println(String.valueOf(t)); if (out.checkError()) { throw new IllegalStateException("Error writing to PrintStream"); } } } /** * Sends the string representations of this to the {@link PrintWriter}. * If this value consists of multiple elements, each element is displayed in a new line. * * @param writer The PrintWriter to write to * @throws IllegalStateException if {@code PrintWriter.checkError()} is true after writing to writer. */ @GwtIncompatible("java.io.PrintWriter is not implemented") default void out(PrintWriter writer) { for (T t : this) { writer.println(String.valueOf(t)); if (writer.checkError()) { throw new IllegalStateException("Error writing to PrintWriter"); } } } /** * Sends the string representations of this to the standard error stream {@linkplain System#err}. * If this value consists of multiple elements, each element is displayed in a new line. * * @throws IllegalStateException if {@code PrintStream.checkError()} is true after writing to stderr. */ @GwtIncompatible("java.io.PrintStream is not implemented") default void stderr() { out(System.err); } /** * Sends the string representations of this to the standard output stream {@linkplain System#out}. * If this value consists of multiple elements, each element is displayed in a new line. * * @throws IllegalStateException if {@code PrintStream.checkError()} is true after writing to stdout. */ @GwtIncompatible("java.io.PrintStream is not implemented") default void stdout() { out(System.out); } // -- Adjusted return types of Iterable /** * Returns a rich {@code io.vavr.collection.Iterator}. * * @return A new Iterator */ @Override Iterator iterator(); // -- conversion methods /** * Converts this to a {@link Array}. * * @return A new {@link Array}. */ default Array toArray() { return ValueModule.toTraversable(this, Array.empty(), Array::of, Array::ofAll); } /** * Converts this to a {@link CharSeq}. * * @return A new {@link CharSeq}. */ default CharSeq toCharSeq() { if (this instanceof CharSeq) { return (CharSeq) this; } else if (isEmpty()) { return CharSeq.empty(); } else { return CharSeq.of(iterator().mkString()); } } /** * Converts this to a {@link CompletableFuture} * * @return A new {@link CompletableFuture} containing the value */ @GwtIncompatible default CompletableFuture toCompletableFuture() { final CompletableFuture completableFuture = new CompletableFuture<>(); Try.of(this::get) .onSuccess(completableFuture::complete) .onFailure(completableFuture::completeExceptionally); return completableFuture; } /** * Converts this to a {@link Validation}. * * @param value type of a {@code Valid} * @param value An instance of a {@code Valid} value * @return A new {@link Validation.Valid} containing the given {@code value} if this is empty, otherwise * a new {@link Validation.Invalid} containing this value. * @deprecated Use {@link #toValidation(Object)} instead. */ @Deprecated default Validation toInvalid(U value) { return isEmpty() ? Validation.valid(value) : Validation.invalid(get()); } /** * Converts this to a {@link Validation}. * * @param value type of a {@code Valid} * @param valueSupplier A supplier of a {@code Valid} value * @return A new {@link Validation.Valid} containing the result of {@code valueSupplier} if this is empty, * otherwise a new {@link Validation.Invalid} containing this value. * @throws NullPointerException if {@code valueSupplier} is null * @deprecated Use {@link #toValidation(Supplier)} instead. */ @Deprecated default Validation toInvalid(Supplier valueSupplier) { Objects.requireNonNull(valueSupplier, "valueSupplier is null"); return isEmpty() ? Validation.valid(valueSupplier.get()) : Validation.invalid(get()); } /** * Converts this to a Java array with component type {@code Object} * *

{@code
     * // = [] of type Object[]
     * Future. of(() -> { throw new Error(); })
     *       .toJavaArray()
     *
     * // = [ok] of type Object[]
     * Try.of(() -> "ok")
     *    .toJavaArray()
     *
     * // = [1, 2, 3] of type Object[]
     * List.of(1, 2, 3)
     *     .toJavaArray()
     * }
* * @return A new Java array. */ default Object[] toJavaArray() { if ((this instanceof Traversable) && ((Traversable) this).isTraversableAgain()) { final Object[] results = new Object[((Traversable) this).size()]; final Iterator iter = iterator(); Arrays.setAll(results, i -> iter.next()); return results; } else { return toJavaList().toArray(); } } /** * Converts this to a Java array having an accurate component type. * *
{@code
     * // = [] of type String[]
     * Future. of(() -> { throw new Error(); })
     *       .toJavaArray(String.class)
     *
     * // = [ok] of type String[]
     * Try.of(() -> "ok")
     *    .toJavaArray(String.class)
     *
     * // = [1, 2, 3] of type Integer[]
     * List.of(1, 2, 3)
     *     .toJavaArray(Integer.class)
     * }
* * @param componentType Component type of the array * @return A new Java array. * @throws NullPointerException if componentType is null * @deprecated Use {@link #toJavaArray(IntFunction)} instead */ @Deprecated @SuppressWarnings("unchecked") @GwtIncompatible("reflection is not supported") default T[] toJavaArray(Class componentType) { Objects.requireNonNull(componentType, "componentType is null"); if (componentType.isPrimitive()) { final Class boxedType = componentType == boolean.class ? Boolean.class : componentType == byte.class ? Byte.class : componentType == char.class ? Character.class : componentType == double.class ? Double.class : componentType == float.class ? Float.class : componentType == int.class ? Integer.class : componentType == long.class ? Long.class : componentType == short.class ? Short.class : componentType == void.class ? Void.class : null; componentType = (Class) boxedType; } final java.util.List list = toJavaList(); return list.toArray((T[]) java.lang.reflect.Array.newInstance(componentType, list.size())); } /** * Converts this to a Java array having an accurate component type. * *
{@code
     * // = [] of type String[]
     * Future. of(() -> { throw new Error(); })
     *       .toJavaArray(String[]::new)
     *
     * // = [ok] of type String[]
     * Try.of(() -> "ok")
     *    .toJavaArray(String[]::new)
     *
     * // = [1, 2, 3] of type Integer[]
     * List.of(1, 2, 3)
     *     .toJavaArray(Integer[]::new)
     * }
* * @param arrayFactory an int argument function that * creates an array of the correct component * type with the specified size * @return The array provided by the factory filled with the values from this Value. * @throws NullPointerException if componentType is null */ default T[] toJavaArray(IntFunction arrayFactory) { java.util.List javaList = toJavaList(); return javaList.toArray(arrayFactory.apply(javaList.size())); } /** * Converts this to a specific mutable {@link java.util.Collection} of type {@code C}. * Elements are added by calling {@link java.util.Collection#add(Object)}. * *
{@code
     * // = []
     * Future. of(() -> { throw new Error(); })
     *       .toJavaCollection(java.util.HashSet::new)
     *
     * // = [ok]
     * Try.of(() -> "ok")
     *    .toJavaCollection(java.util.HashSet::new)
     * 
     * // = [1, 2, 3]
     * List.of(1, 2, 3)
     *     .toJavaCollection(java.util.LinkedHashSet::new)
     * }
* * @param factory A factory that returns an empty mutable {@code java.util.Collection} with the specified initial capacity * @param a sub-type of {@code java.util.Collection} * @return a new {@code java.util.Collection} of type {@code C} */ default > C toJavaCollection(Function factory) { return ValueModule.toJavaCollection(this, factory); } /** * Converts this to a mutable {@link java.util.List}. * Elements are added by calling {@link java.util.List#add(Object)}. * *
{@code
     * // = []
     * Future. of(() -> { throw new Error(); })
     *       .toJavaList()
     * 
     * // = [ok]
     * Try.of(() -> "ok")
     *    .toJavaList()
     *
     * // = [1, 2, 3]
     * List.of(1, 2, 3)
     *     .toJavaList()
     * }
* * @return A new {@link java.util.ArrayList}. */ default java.util.List toJavaList() { return ValueModule.toJavaCollection(this, ArrayList::new, 10); } /** * Converts this to a specific mutable {@link java.util.List}. * Elements are added by calling {@link java.util.List#add(Object)}. * *
{@code
     * // = []
     * Future. of(() -> { throw new Error(); })
     *       .toJavaList(java.util.ArrayList::new)
     * 
     * // = [ok]
     * Try.of(() -> "ok")
     *    .toJavaList(java.util.ArrayList::new)
     *
     * // = [1, 2, 3]
     * List.of(1, 2, 3)
     *     .toJavaList(java.util.ArrayList::new)
     *
     * // = [1, 2, 3]
     * List.of(1, 2, 3)
     *     .toJavaList(capacity -> new java.util.LinkedList<>())
     * }
* * @param factory A factory that returns an empty mutable {@code java.util.List} with the specified initial capacity * @param A sub-type of {@code java.util.List} * @return a new {@code java.util.List} of type {@code LIST} */ default > LIST toJavaList(Function factory) { return ValueModule.toJavaCollection(this, factory); } /** * Converts this to a mutable {@link java.util.Map}. * Elements are added by calling {@link java.util.Map#put(Object, Object)}. * *
{@code
     * // = {}
     * Future. of(() -> { throw new Error(); })
     *       .toJavaMap(s -> Tuple.of(s, s.length()))
     * 
     * // = {ok=2}
     * Try.of(() -> "ok")
     *    .toJavaMap(s -> Tuple.of(s, s.length()))
     *
     * // = {1=A, 2=B, 3=C}
     * List.of(1, 2, 3)
     *     .toJavaMap(i -> Tuple.of(i, (char) (i + 64)))
     * }
* * @param f A function that maps an element to a key/value pair represented by Tuple2 * @param The key type * @param The value type * @return A new {@link java.util.HashMap}. */ default java.util.Map toJavaMap(Function> f) { return toJavaMap(java.util.HashMap::new, f); } /** * Converts this to a specific mutable {@link java.util.Map}. * Elements are added by calling {@link java.util.Map#put(Object, Object)}. * *
{@code
     * // = {}
     * Future. of(() -> { throw new Error(); })
     *       .toJavaMap(java.util.HashMap::new, s -> s, String::length)
     * 
     * // = {ok=2}
     * Try.of(() -> "ok")
     *    .toJavaMap(java.util.TreeMap::new, s -> s, String::length)
     *
     * // = {1=A, 2=B, 3=C}
     * List.of(1, 2, 3)
     *     .toJavaMap(java.util.TreeMap::new, i -> i, i -> (char) (i + 64))
     * }
* * @param factory A factory that creates an empty mutable {@code java.util.Map} * @param keyMapper A function that maps an element to a key * @param valueMapper A function that maps an element to a value * @param The key type * @param The value type * @param a sub-type of {@code java.util.Map} * @return a new {@code java.util.Map} of type {@code MAP} */ default > MAP toJavaMap(Supplier factory, Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return toJavaMap(factory, t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t))); } /** * Converts this to a specific mutable {@link java.util.Map}. * Elements are added by calling {@link java.util.Map#put(Object, Object)}. * *
{@code
     * // = {}
     * Future. of(() -> { throw new Error(); })
     *       .toJavaMap(java.util.HashMap::new, s -> Tuple.of(s, s.length()))
     * 
     * // = {ok=2}
     * Try.of(() -> "ok")
     *     .toJavaMap(java.util.TreeMap::new, s -> Tuple.of(s, s.length()))
     * 
     * // = {1=A, 2=B, 3=C}
     * List.of(1, 2, 3)
     *     .toJavaMap(java.util.TreeMap::new, i -> Tuple.of(i, (char) (i + 64)))
     * }
* * @param factory A factory that creates an empty mutable {@code java.util.Map} * @param f A function that maps an element to a key/value pair represented by Tuple2 * @param The key type * @param The value type * @param a sub-type of {@code java.util.Map} * @return a new {@code java.util.Map} of type {@code MAP} */ default > MAP toJavaMap(Supplier factory, Function> f) { Objects.requireNonNull(f, "f is null"); final MAP map = factory.get(); if (!isEmpty()) { if (isSingleValued()) { final Tuple2 entry = f.apply(get()); map.put(entry._1, entry._2); } else { for (T a : this) { final Tuple2 entry = f.apply(a); map.put(entry._1, entry._2); } } } return map; } /** * Converts this to an {@link java.util.Optional}. * *
{@code
     * // = Optional.empty
     * Future.of(() -> { throw new Error(); })
     *       .toJavaOptional()
     *
     * // = Optional[ok]
     * Try.of(() -> "ok")
     *     .toJavaOptional()
     *
     * // = Optional[1]
     * List.of(1, 2, 3)
     *     .toJavaOptional()
     * }
* * @return A new {@link java.util.Optional}. */ default Optional toJavaOptional() { return isEmpty() ? Optional.empty() : Optional.ofNullable(get()); } /** * Converts this to a mutable {@link java.util.Set}. * Elements are added by calling {@link java.util.Set#add(Object)}. * *
{@code
     * // = []
     * Future.of(() -> { throw new Error(); })
     *       .toJavaSet()
     * 
     * // = [ok]
     * Try.of(() -> "ok")
     *     .toJavaSet()
     *
     * // = [1, 2, 3]
     * List.of(1, 2, 3)
     *     .toJavaSet()
     * }
* * @return A new {@link java.util.HashSet}. */ default java.util.Set toJavaSet() { return ValueModule.toJavaCollection(this, java.util.HashSet::new, 16); } /** * Converts this to a specific {@link java.util.Set}. * Elements are added by calling {@link java.util.Set#add(Object)}. * *
{@code
     * // = []
     * Future.of(() -> { throw new Error(); })
     *       .toJavaSet(java.util.HashSet::new)
     * 
     * // = [ok]
     * Try.of(() -> "ok")
     *     .toJavaSet(java.util.HashSet::new)
     *
     * // = [3, 2, 1]
     * List.of(1, 2, 3)
     *     .toJavaSet(capacity -> new java.util.TreeSet<>(Comparator.reverseOrder()))
     * }
* * @param factory A factory that returns an empty mutable {@code java.util.Set} with the specified initial capacity * @param a sub-type of {@code java.util.Set} * @return a new {@code java.util.Set} of type {@code SET} */ default > SET toJavaSet(Function factory) { return ValueModule.toJavaCollection(this, factory); } /** * Converts this to a sequential {@link java.util.stream.Stream} by calling * {@code StreamSupport.stream(this.spliterator(), false)}. * *
{@code
     * // empty Stream
     * Future.of(() -> { throw new Error(); })
     *       .toJavaStream()
     *
     * // Stream containing "ok"
     * Try.of(() -> "ok")
     *    .toJavaStream()
     *
     * // Stream containing 1, 2, 3
     * List.of(1, 2, 3)
     *     .toJavaStream()
     * }
* * @return A new sequential {@link java.util.stream.Stream}. * @see Value#spliterator() */ default java.util.stream.Stream toJavaStream() { return StreamSupport.stream(spliterator(), false); } /** * Converts this to a parallel {@link java.util.stream.Stream} by calling * {@code StreamSupport.stream(this.spliterator(), true)}. * *
{@code
     * // empty Stream
     * Future.of(() -> { throw new Error(); })
     *       .toJavaParallelStream()
     *
     * // Stream containing "ok"
     * Try.of(() -> "ok")
     *    .toJavaParallelStream()
     *
     * // Stream containing 1, 2, 3
     * List.of(1, 2, 3)
     *     .toJavaParallelStream()
     * }
* * @return A new parallel {@link java.util.stream.Stream}. * @see Value#spliterator() */ default java.util.stream.Stream toJavaParallelStream() { return StreamSupport.stream(spliterator(), true); } /** * Converts this to a {@link Either}. * * @param right type * @param right An instance of a right value * @return A new {@link Either.Right} containing the value of {@code right} if this is empty, otherwise * a new {@link Either.Left} containing this value. * @deprecated Use {@link #toEither(Object)} instead. */ @Deprecated default Either toLeft(R right) { return isEmpty() ? Either.right(right) : Either.left(get()); } /** * Converts this to a {@link Either}. * * @param right type * @param right A supplier of a right value * @return A new {@link Either.Right} containing the result of {@code right} if this is empty, otherwise * a new {@link Either.Left} containing this value. * @throws NullPointerException if {@code right} is null * @deprecated Use {@link #toEither(Supplier)} instead. */ @Deprecated default Either toLeft(Supplier right) { Objects.requireNonNull(right, "right is null"); return isEmpty() ? Either.right(right.get()) : Either.left(get()); } /** * Converts this to a {@link List}. * * @return A new {@link List}. */ default List toList() { return ValueModule.toTraversable(this, List.empty(), List::of, List::ofAll); } /** * Converts this to a {@link Map}. * * @param keyMapper A function that maps an element to a key * @param valueMapper A function that maps an element to a value * @param The key type * @param The value type * @return A new {@link HashMap}. */ default Map toMap(Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return toMap(t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t))); } /** * Converts this to a {@link Map}. * * @param f A function that maps an element to a key/value pair represented by Tuple2 * @param The key type * @param The value type * @return A new {@link HashMap}. */ default Map toMap(Function> f) { Objects.requireNonNull(f, "f is null"); final Function, Map> ofElement = HashMap::of; final Function>, Map> ofAll = HashMap::ofEntries; return ValueModule.toMap(this, HashMap.empty(), ofElement, ofAll, f); } /** * Converts this to a {@link Map}. * * @param keyMapper A function that maps an element to a key * @param valueMapper A function that maps an element to a value * @param The key type * @param The value type * @return A new {@link LinkedHashMap}. */ default Map toLinkedMap(Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return toLinkedMap(t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t))); } /** * Converts this to a {@link Map}. * * @param f A function that maps an element to a key/value pair represented by Tuple2 * @param The key type * @param The value type * @return A new {@link LinkedHashMap}. */ default Map toLinkedMap(Function> f) { Objects.requireNonNull(f, "f is null"); final Function, Map> ofElement = LinkedHashMap::of; final Function>, Map> ofAll = LinkedHashMap::ofEntries; return ValueModule.toMap(this, LinkedHashMap.empty(), ofElement, ofAll, f); } /** * Converts this to a {@link Map}. * * @param keyMapper A function that maps an element to a key * @param valueMapper A function that maps an element to a value * @param The key type * @param The value type * @return A new {@link TreeMap}. */ default , V> SortedMap toSortedMap(Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return toSortedMap(t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t))); } /** * Converts this to a {@link Map}. * * @param f A function that maps an element to a key/value pair represented by Tuple2 * @param The key type * @param The value type * @return A new {@link TreeMap}. */ default , V> SortedMap toSortedMap(Function> f) { Objects.requireNonNull(f, "f is null"); return toSortedMap(Comparator.naturalOrder(), f); } /** * Converts this to a {@link Map}. * * @param comparator A comparator that induces an order of the Map keys. * @param keyMapper A function that maps an element to a key * @param valueMapper A function that maps an element to a value * @param The key type * @param The value type * @return A new {@link TreeMap}. */ default SortedMap toSortedMap(Comparator comparator, Function keyMapper, Function valueMapper) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return toSortedMap(comparator, t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t))); } /** * Converts this to a {@link Map}. * * @param comparator A comparator that induces an order of the Map keys. * @param f A function that maps an element to a key/value pair represented by Tuple2 * @param The key type * @param The value type * @return A new {@link TreeMap}. */ default SortedMap toSortedMap(Comparator comparator, Function> f) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(f, "f is null"); final Function, SortedMap> ofElement = t -> TreeMap.of(comparator, t); final Function>, SortedMap> ofAll = t -> TreeMap.ofEntries(comparator, t); return ValueModule.toMap(this, TreeMap.empty(comparator), ofElement, ofAll, f); } /** * Converts this to an {@link Option}. * * @return A new {@link Option}. */ default Option toOption() { if (this instanceof Option) { return (Option) this; } else { return isEmpty() ? Option.none() : Option.some(get()); } } /** * Converts this to an {@link Either}. * * @param left A left value for the {@link Either} * @param Either left component type * @return A new {@link Either}. */ default Either toEither(L left) { if (this instanceof Either) { return ((Either) this).mapLeft(ignored -> left); } else { return isEmpty() ? Left(left) : Right(get()); } } /** * Converts this to an {@link Either}. * * @param leftSupplier A {@link Supplier} for the left value for the {@link Either} * @param Validation error component type * @return A new {@link Either}. */ default Either toEither(Supplier leftSupplier) { Objects.requireNonNull(leftSupplier, "leftSupplier is null"); if (this instanceof Either) { return ((Either) this).mapLeft(ignored -> leftSupplier.get()); } else { return isEmpty() ? Left(leftSupplier.get()) : Right(get()); } } /** * Converts this to an {@link Validation}. * * @param invalid An invalid value for the {@link Validation} * @param Validation error component type * @return A new {@link Validation}. */ default Validation toValidation(E invalid) { if (this instanceof Validation) { return ((Validation) this).mapError(ignored -> invalid); } else { return isEmpty() ? Invalid(invalid) : Valid(get()); } } /** * Converts this to an {@link Validation}. * * @param invalidSupplier A {@link Supplier} for the invalid value for the {@link Validation} * @param Validation error component type * @return A new {@link Validation}. */ default Validation toValidation(Supplier invalidSupplier) { Objects.requireNonNull(invalidSupplier, "invalidSupplier is null"); if (this instanceof Validation) { return ((Validation) this).mapError(ignored -> invalidSupplier.get()); } else { return isEmpty() ? Invalid(invalidSupplier.get()) : Valid(get()); } } /** * Converts this to a {@link Queue}. * * @return A new {@link Queue}. */ default Queue toQueue() { return ValueModule.toTraversable(this, Queue.empty(), Queue::of, Queue::ofAll); } /** * Converts this to a {@link PriorityQueue}. * * @return A new {@link PriorityQueue}. */ @SuppressWarnings("unchecked") default PriorityQueue toPriorityQueue() { if (this instanceof PriorityQueue) { return (PriorityQueue) this; } else { final Comparator comparator = (this instanceof Ordered) ? ((Ordered) this).comparator() : (Comparator) Comparator.naturalOrder(); return toPriorityQueue(comparator); } } /** * Converts this to a {@link PriorityQueue}. * * @param comparator A comparator that induces an order of the PriorityQueue elements. * @return A new {@link PriorityQueue}. */ default PriorityQueue toPriorityQueue(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final PriorityQueue empty = PriorityQueue.empty(comparator); final Function> of = value -> PriorityQueue.of(comparator, value); final Function, PriorityQueue> ofAll = values -> PriorityQueue.ofAll(comparator, values); return ValueModule.toTraversable(this, empty, of, ofAll); } /** * Converts this to a {@link Either}. * * @param left type * @param left An instance of a left value * @return A new {@link Either.Left} containing the value of {@code left} if this is empty, otherwise * a new {@link Either.Right} containing this value. * @deprecated Use {@link #toEither(Object)} instead. */ @Deprecated default Either toRight(L left) { return isEmpty() ? Either.left(left) : Either.right(get()); } /** * Converts this to a {@link Either}. * * @param left type * @param left A supplier of a left value * @return A new {@link Either.Left} containing the result of {@code left} if this is empty, otherwise * a new {@link Either.Right} containing this value. * @throws NullPointerException if {@code left} is null * @deprecated Use {@link #toEither(Supplier)} instead. */ @Deprecated default Either toRight(Supplier left) { Objects.requireNonNull(left, "left is null"); return isEmpty() ? Either.left(left.get()) : Either.right(get()); } /** * Converts this to a {@link Set}. * * @return A new {@link HashSet}. */ default Set toSet() { return ValueModule.toTraversable(this, HashSet.empty(), HashSet::of, HashSet::ofAll); } /** * Converts this to a {@link Set}. * * @return A new {@link LinkedHashSet}. */ default Set toLinkedSet() { return ValueModule.toTraversable(this, LinkedHashSet.empty(), LinkedHashSet::of, LinkedHashSet::ofAll); } /** * Converts this to a {@link SortedSet}. * Current items must be comparable * * @return A new {@link TreeSet}. * @throws ClassCastException if items are not comparable */ @SuppressWarnings("unchecked") default SortedSet toSortedSet() throws ClassCastException { if (this instanceof TreeSet) { return (TreeSet) this; } else { final Comparator comparator = (this instanceof Ordered) ? ((Ordered) this).comparator() : (Comparator) Comparator.naturalOrder(); return toSortedSet(comparator); } } /** * Converts this to a {@link SortedSet}. * * @param comparator A comparator that induces an order of the SortedSet elements. * @return A new {@link TreeSet}. */ default SortedSet toSortedSet(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return ValueModule.toTraversable(this, TreeSet.empty(comparator), value -> TreeSet.of(comparator, value), values -> TreeSet.ofAll(comparator, values)); } /** * Converts this to a {@link Stream}. * * @return A new {@link Stream}. */ default Stream toStream() { return ValueModule.toTraversable(this, Stream.empty(), Stream::of, Stream::ofAll); } /** * Converts this to a {@link Try}. *

* If this value is undefined, i.e. empty, then a new {@code Failure(NoSuchElementException)} is returned, * otherwise a new {@code Success(value)} is returned. * * @return A new {@link Try}. */ default Try toTry() { if (this instanceof Try) { return (Try) this; } else { return Try.of(this::get); } } /** * Converts this to a {@link Try}. *

* If this value is undefined, i.e. empty, then a new {@code Failure(ifEmpty.get())} is returned, * otherwise a new {@code Success(value)} is returned. * * @param ifEmpty an exception supplier * @return A new {@link Try}. */ default Try toTry(Supplier ifEmpty) { Objects.requireNonNull(ifEmpty, "ifEmpty is null"); return isEmpty() ? Try.failure(ifEmpty.get()) : toTry(); } /** * Converts this to a {@link Tree}. * * @return A new {@link Tree}. */ default Tree toTree() { return ValueModule.toTraversable(this, Tree.empty(), Tree::of, Tree::ofAll); } /** * Converts this to a {@link Tree} using a {@code idMapper} and {@code parentMapper}. * * @param Id type * @param idMapper A mapper from source item to unique identifier of that item * @param parentMapper A mapper from source item to unique identifier of parent item. Need return null for root items * @return A new {@link Tree}. * @see Tree#build(Iterable, Function, Function) */ default List> toTree(Function idMapper, Function parentMapper) { return Tree.build(this, idMapper, parentMapper); } /** * Converts this to a {@link Validation}. * * @param error type of an {@code Invalid} * @param error An error * @return A new {@link Validation.Invalid} containing the given {@code error} if this is empty, otherwise * a new {@link Validation.Valid} containing this value. * @deprecated Use {@link #toValidation(Object)} instead. */ @Deprecated default Validation toValid(E error) { return isEmpty() ? Validation.invalid(error) : Validation.valid(get()); } /** * Converts this to a {@link Validation}. * * @param error type of an {@code Invalid} * @param errorSupplier A supplier of an error * @return A new {@link Validation.Invalid} containing the result of {@code errorSupplier} if this is empty, * otherwise a new {@link Validation.Valid} containing this value. * @throws NullPointerException if {@code valueSupplier} is null * @deprecated Use {@link #toValidation(Supplier)} instead. */ @Deprecated default Validation toValid(Supplier errorSupplier) { Objects.requireNonNull(errorSupplier, "errorSupplier is null"); return isEmpty() ? Validation.invalid(errorSupplier.get()) : Validation.valid(get()); } /** * Converts this to a {@link Vector}. * * @return A new {@link Vector}. */ default Vector toVector() { return ValueModule.toTraversable(this, Vector.empty(), Vector::of, Vector::ofAll); } @Override default Spliterator spliterator() { return Spliterators.spliterator(iterator(), isEmpty() ? 0 : 1, Spliterator.IMMUTABLE | Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED); } // -- Object /** * Clarifies that values have a proper equals() method implemented. *

* See Object.hashCode(). * * @return The hashcode of this object */ @Override int hashCode(); /** * Clarifies that values have a proper toString() method implemented. *

* See Object.toString(). * * @return A String representation of this object */ @Override String toString(); } interface ValueModule { static > R toTraversable( Value value, R empty, Function ofElement, Function, R> ofAll) { if (value.isEmpty()) { return empty; } else if (value.isSingleValued()) { return ofElement.apply(value.get()); } else { return ofAll.apply(value); } } static , R extends Map> R toMap( Value value, R empty, Function ofElement, Function, R> ofAll, Function f) { if (value.isEmpty()) { return empty; } else if (value.isSingleValued()) { return ofElement.apply(f.apply(value.get())); } else { return ofAll.apply(Iterator.ofAll(value).map(f)); } } static > R toJavaCollection( Value value, Function containerSupplier) { return toJavaCollection(value, containerSupplier, 16); } static > R toJavaCollection( Value value, Function containerSupplier, int defaultInitialCapacity) { final int size; if (value instanceof Traversable && ((Traversable) value).isTraversableAgain() && !value.isLazy()) { size = ((Traversable) value).size(); } else { size = defaultInitialCapacity; } final R container = containerSupplier.apply(size); value.forEach(container::add); return container; } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/000077500000000000000000000000001342074374400217105ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/java/io/vavr/collection/AbstractIterator.java000066400000000000000000000030301342074374400260240ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import java.util.NoSuchElementException; /** * Provides a common {@link Object#toString()} implementation. *

* {@code equals(Object)} and {@code hashCode()} are intentionally not overridden in order to prevent this iterator * from being evaluated. In other words, (identity-)equals and hashCode are implemented by Object. * * @param Component type * @author Daniel Dietrich */ abstract class AbstractIterator implements Iterator { @Override public String toString() { return stringPrefix() + "(" + (isEmpty() ? "" : "?") + ")"; } protected abstract T getNext(); @Override public final T next() { if (!hasNext()) { throw new NoSuchElementException("next() on empty iterator"); } return getNext(); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/AbstractMultimap.java000066400000000000000000000503541342074374400260360ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import java.io.Serializable; import java.util.Collection; import java.util.Comparator; import java.util.Objects; import java.util.function.*; import static io.vavr.API.Tuple; /** * An {@link Multimap} implementation (not intended to be public). * * @param Key type * @param Value type * @param Multimap type * @author Ruslan Sennov */ abstract class AbstractMultimap> implements Multimap { private static final long serialVersionUID = 1L; protected final Map> back; protected final SerializableSupplier> emptyContainer; private final ContainerType containerType; AbstractMultimap(Map> back, ContainerType containerType, SerializableSupplier> emptyContainer) { this.back = back; this.containerType = containerType; this.emptyContainer = emptyContainer; } protected abstract Map emptyMapSupplier(); protected abstract Multimap emptyInstance(); protected abstract Multimap createFromMap(Map> back); @SuppressWarnings("unchecked") private Multimap createFromEntries(Iterable> entries) { Map> back = emptyMapSupplier(); for (Tuple2 entry : entries) { if (back.containsKey(entry._1)) { back = back.put(entry._1, containerType.add(back.get(entry._1).get(), entry._2)); } else { back = back.put(entry._1, containerType.add(emptyContainer.get(), entry._2)); } } return createFromMap(back); } @Override public Map> asMap() { return back; } @Override public Multimap bimap(Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); final Iterator> entries = iterator().map(entry -> Tuple.of(keyMapper.apply(entry._1), valueMapper.apply(entry._2))); return createFromEntries(entries); } @Override public boolean containsKey(K key) { return back.containsKey(key); } @Override public ContainerType getContainerType() { return containerType; } @Override public Multimap flatMap(BiFunction>> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return foldLeft(this.emptyInstance(), (acc, entry) -> { for (Tuple2 mappedEntry : mapper.apply(entry._1, entry._2)) { acc = acc.put(mappedEntry); } return acc; }); } @Override public Option> get(K key) { return back.get(key); } @Override @SuppressWarnings("unchecked") public Traversable getOrElse(K key, Traversable defaultValue) { return back.getOrElse(key, (Traversable) defaultValue); } @Override public Set keySet() { return back.keySet(); } @Override public Multimap map(BiFunction> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return foldLeft(this.emptyInstance(), (acc, entry) -> acc.put(mapper.apply(entry._1, entry._2))); } @Override public Multimap mapValues(Function valueMapper) { Objects.requireNonNull(valueMapper, "valueMapper is null"); return map((k, v) -> Tuple.of(k, valueMapper.apply(v))); } @SuppressWarnings("unchecked") @Override public M put(K key, V value) { final Traversable values = back.get(key).getOrElse((Traversable) emptyContainer.get()); final Traversable newValues = containerType.add(values, value); return (M) (newValues == values ? this : createFromMap(back.put(key, newValues))); } @Override public M put(Tuple2 entry) { Objects.requireNonNull(entry, "entry is null"); return put(entry._1, entry._2); } @SuppressWarnings("unchecked") @Override public M remove(K key) { return (M) (back.containsKey(key) ? createFromMap(back.remove(key)) : this); } @SuppressWarnings("unchecked") @Override public M remove(K key, V value) { final Traversable values = back.get(key).getOrElse((Traversable) emptyContainer.get()); final Traversable newValues = containerType.remove(values, value); if (newValues == values) { return (M) this; } else if (newValues.isEmpty()) { return (M) createFromMap(back.remove(key)); } else { return (M) createFromMap(back.put(key, newValues)); } } @SuppressWarnings("unchecked") @Override public M removeAll(Iterable keys) { final Map> result = back.removeAll(keys); return (M) (result == back ? this : createFromMap(result)); } @Override public int size() { return back.foldLeft(0, (s, t) -> s + t._2.size()); } @Override public Traversable values() { return Iterator.concat(back.values()).toStream(); } @SuppressWarnings("unchecked") @Override public M distinct() { return (M) (containerType == ContainerType.SEQ ? createFromEntries(iterator().distinct()) : this); } @SuppressWarnings("unchecked") @Override public M distinctBy(Comparator> comparator) { Objects.requireNonNull(comparator, "comparator is null"); return (M) (isEmpty() ? this : createFromEntries(iterator().distinctBy(comparator))); } @SuppressWarnings("unchecked") @Override public M distinctBy(Function, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return (M) (isEmpty() ? this : createFromEntries(iterator().distinctBy(keyExtractor))); } @Override @SuppressWarnings("unchecked") public M drop(int n) { if (n <= 0 || isEmpty()) { return (M) this; } else if (n >= length()) { return (M) this.emptyInstance(); } else { return (M) createFromEntries(iterator().drop(n)); } } @Override @SuppressWarnings("unchecked") public M dropRight(int n) { if (n <= 0 || isEmpty()) { return (M) this; } else if (n >= length()) { return (M) this.emptyInstance(); } else { return (M) createFromEntries(iterator().dropRight(n)); } } @Override public M dropUntil(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @SuppressWarnings("unchecked") @Override public M dropWhile(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return (M) (isEmpty() ? this : createFromEntries(iterator().dropWhile(predicate))); } @SuppressWarnings("unchecked") @Override public M filter(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return (M) this; } else { return (M) createFromEntries(iterator().filter(predicate)); } } @Override public M reject(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(predicate.negate()); } @Override public M filter(BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(t -> predicate.test(t._1, t._2)); } @Override public M reject(BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(t -> predicate.test(t._1, t._2)); } @Override public M filterKeys(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(t -> predicate.test(t._1)); } @Override public M rejectKeys(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(t -> predicate.test(t._1)); } @Override public M filterValues(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(t -> predicate.test(t._2)); } @Override public M rejectValues(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(t -> predicate.test(t._2)); } @Override @Deprecated public M removeAll(BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override @Deprecated public M removeKeys(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectKeys(predicate); } @Override @Deprecated public M removeValues(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectValues(predicate); } @SuppressWarnings("unchecked") @Override public Map groupBy(Function, ? extends C> classifier) { return (Map) Collections.groupBy(this, classifier, this::createFromEntries); } @Override public Iterator grouped(int size) { return sliding(size, size); } @Override public M init() { if (back.isEmpty()) { throw new UnsupportedOperationException("init of empty HashMap"); } else { final Tuple2 last = last(); return remove(last._1, last._2); } } @Override public Tuple2 head() { final Tuple2> head = back.head(); return Tuple.of(head._1, head._2.head()); } @SuppressWarnings("unchecked") @Override public Option initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override public boolean isAsync() { return back.isAsync(); } @Override public boolean isEmpty() { return back.isEmpty(); } @Override public boolean isLazy() { return back.isLazy(); } @Override public Iterator> iterator() { if (containerType == ContainerType.SORTED_SET) { return back.iterator().flatMap(t -> t._2.iterator().map(v -> Tuple.of(t._1, v))); } else { return back.iterator().flatMap(t -> t._2.map(v -> Tuple.of(t._1, v))); } } @Override public Tuple2 last() { final Tuple2> last = back.last(); return Tuple.of(last._1, last._2.last()); } @SuppressWarnings("unchecked") @Override public M merge(Multimap that) { Objects.requireNonNull(that, "that is null"); if (isEmpty()) { return (M) createFromEntries(that); } else if (that.isEmpty()) { return (M) this; } else { return that.foldLeft((M) this, (map, entry) -> (M) map.put(entry)); } } @SuppressWarnings("unchecked") @Override public M merge(Multimap that, BiFunction, Traversable, Traversable> collisionResolution) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(collisionResolution, "collisionResolution is null"); if (isEmpty()) { return (M) createFromEntries(that); } else if (that.isEmpty()) { return (M) this; } else { final Map> result = that.keySet().foldLeft(this.back, (map, key) -> { final Traversable thisValues = map.get(key).getOrElse((Traversable) emptyContainer.get()); final Traversable thatValues = that.get(key).get(); final Traversable newValues = collisionResolution.apply(thisValues, thatValues); return map.put(key, newValues); }); return (M) createFromMap(result); } } /** * Returns this {@code Multimap} if it is nonempty, * otherwise {@code Multimap} created from iterable, using existing multimap properties. * * @param other An alternative {@code Traversable} * @return this {@code Multimap} if it is nonempty, * otherwise {@code Multimap} created from iterable, using existing multimap properties. */ @SuppressWarnings("unchecked") @Override public M orElse(Iterable> other) { return isEmpty() ? (M) createFromEntries(other) : (M) this; } /** * Returns this {@code Multimap} if it is nonempty, * otherwise {@code Multimap} created from result of evaluating supplier, using existing multimap properties. * * @param supplier An alternative {@code Traversable} * @return this {@code Multimap} if it is nonempty, * otherwise {@code Multimap} created from result of evaluating supplier, using existing multimap properties. */ @SuppressWarnings("unchecked") @Override public M orElse(Supplier>> supplier) { return isEmpty() ? (M) createFromEntries(supplier.get()) : (M) this; } @SuppressWarnings("unchecked") @Override public Tuple2 partition(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2>, Iterator>> p = iterator().partition(predicate); return Tuple.of((M) createFromEntries(p._1), (M) createFromEntries(p._2)); } @SuppressWarnings("unchecked") @Override public M peek(Consumer> action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return (M) this; } @SuppressWarnings("unchecked") @Override public M replace(Tuple2 currentElement, Tuple2 newElement) { Objects.requireNonNull(currentElement, "currentElement is null"); Objects.requireNonNull(newElement, "newElement is null"); return (M) (containsKey(currentElement._1) ? remove(currentElement._1, currentElement._2).put(newElement) : this); } @Override public M replaceAll(Tuple2 currentElement, Tuple2 newElement) { return replace(currentElement, newElement); } @SuppressWarnings("unchecked") @Override public M replaceValue(K key, V value) { return (M) (containsKey(key) ? remove(key).put(key, value) : this); } @SuppressWarnings("unchecked") @Override public M replace(K key, V oldValue, V newValue) { return (M) (contains(Tuple(key, oldValue)) ? remove(key, oldValue).put(key, newValue) : this); } @SuppressWarnings("unchecked") @Override public M replaceAll(BiFunction function) { return (M) map((k, v) -> Tuple(k, function.apply(k, v))); } @SuppressWarnings("unchecked") @Override public M retainAll(Iterable> elements) { Objects.requireNonNull(elements, "elements is null"); return (M) createFromEntries(back.flatMap(t -> t._2.map(v -> Tuple.of(t._1, v))).retainAll(elements)); } @SuppressWarnings("unchecked") @Override public M scan(Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation) { return (M) Collections.scanLeft(this, zero, operation, this::createFromEntries); } @SuppressWarnings("unchecked") @Override public Iterator slideBy(Function, ?> classifier) { return (Iterator) iterator().slideBy(classifier).map(this::createFromEntries); } @Override public Iterator sliding(int size) { return sliding(size, 1); } @SuppressWarnings("unchecked") @Override public Iterator sliding(int size, int step) { return (Iterator) iterator().sliding(size, step).map(this::createFromEntries); } @SuppressWarnings("unchecked") @Override public Tuple2 span(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2>, Iterator>> t = iterator().span(predicate); return Tuple.of((M) createFromEntries(t._1), (M) createFromEntries(t._2)); } @Override public M tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty Multimap"); } else { final Tuple2 head = head(); return remove(head._1, head._2); } } @Override public Option tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override @SuppressWarnings("unchecked") public M take(int n) { if (isEmpty() || n >= length()) { return (M) this; } else if (n <= 0) { return (M) this.emptyInstance(); } else { return (M) createFromEntries(iterator().take(n)); } } @Override @SuppressWarnings("unchecked") public M takeRight(int n) { if (isEmpty() || n >= length()) { return (M) this; } else if (n <= 0) { return (M) this.emptyInstance(); } else { return (M) createFromEntries(iterator().takeRight(n)); } } @Override public M takeUntil(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @SuppressWarnings("unchecked") @Override public M takeWhile(Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Multimap taken = createFromEntries(iterator().takeWhile(predicate)); return (M) (taken.length() == length() ? this : taken); } @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return back.hashCode(); } @Override public String stringPrefix() { return getClass().getSimpleName() + "[" + emptyContainer.get().stringPrefix() + "]"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } @Override public java.util.Map> toJavaMap() { return toJavaMap(new java.util.HashMap<>()); } protected >> JM toJavaMap(JM javaMap) { for (Tuple2 t : this) { javaMap.computeIfAbsent(t._1, k -> containerType.instantiate()).add(t._2); } return javaMap; } interface SerializableSupplier extends Supplier, Serializable { } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/AbstractQueue.java000066400000000000000000000142541342074374400253310ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Predicate; /** * @author Pap Lőrinc, Daniel Dietrich */ abstract class AbstractQueue> implements Traversable { /** * Removes an element from this Queue. * * @return a tuple containing the first element and the remaining elements of this Queue * @throws NoSuchElementException if this Queue is empty */ public Tuple2 dequeue() { if (isEmpty()) { throw new NoSuchElementException("dequeue of empty " + getClass().getSimpleName()); } else { return Tuple.of(head(), tail()); } } /** * Removes an element from this Queue. * * @return {@code None} if this Queue is empty, otherwise {@code Some} {@code Tuple} containing the first element and the remaining elements of this Queue */ public Option> dequeueOption() { return isEmpty() ? Option.none() : Option.some(dequeue()); } /** * Enqueues a new element. * * @param element The new element * @return a new {@code Queue} instance, containing the new element */ public abstract Q enqueue(T element); /** * Enqueues the given elements. A queue has FIFO order, i.e. the first of the given elements is * the first which will be retrieved. * * @param elements Elements, may be empty * @return a new {@code Queue} instance, containing the new elements * @throws NullPointerException if elements is null */ @SuppressWarnings("unchecked") public Q enqueue(T... elements) { Objects.requireNonNull(elements, "elements is null"); return enqueueAll(List.of(elements)); } /** * Enqueues the given elements. A queue has FIFO order, i.e. the first of the given elements is * the first which will be retrieved. * * @param elements An Iterable of elements, may be empty * @return a new {@code Queue} instance, containing the new elements * @throws NullPointerException if elements is null */ public abstract Q enqueueAll(Iterable elements); /** * Returns the first element without modifying it. * * @return the first element * @throws NoSuchElementException if this Queue is empty */ public T peek() { if (isEmpty()) { throw new NoSuchElementException("peek of empty " + getClass().getSimpleName()); } else { return head(); } } /** * Returns the first element without modifying the Queue. * * @return {@code None} if this Queue is empty, otherwise a {@code Some} containing the first element */ public Option peekOption() { return isEmpty() ? Option.none() : Option.some(peek()); } @Override public Q dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override public abstract Q dropWhile(Predicate predicate); /** * Dual of {@linkplain #tail()}, returning all elements except the last. * * @return a new instance containing all elements except the last. * @throws UnsupportedOperationException if this is empty */ @Override public abstract Q init(); /** * Dual of {@linkplain #tailOption()}, returning all elements except the last as {@code Option}. * * @return {@code Some(Q)} or {@code None} if this is empty. */ @Override public Option initOption() { return isEmpty() ? Option.none() : Option.some(init()); } /** * Drops the first element of a non-empty Traversable. * * @return A new instance of Traversable containing all elements except the first. * @throws UnsupportedOperationException if this is empty */ @Override public abstract Q tail(); @Override public Option tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override @SuppressWarnings("unchecked") public Q retainAll(Iterable elements) { return Collections.retainAll((Q) this, elements); } @SuppressWarnings("unchecked") public Q removeAll(Iterable elements) { return Collections.removeAll((Q) this, elements); } @Deprecated public Q removeAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @SuppressWarnings("unchecked") @Override public Q reject(Predicate predicate) { return Collections.reject((Q) this, predicate); } @Override public Q takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeUntil(predicate.negate()); } @Override public abstract Q takeUntil(Predicate predicate); @SuppressWarnings("unchecked") @Override public Q peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return (Q) this; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Array.java000066400000000000000000001412631342074374400236400ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.collection.ArrayModule.Combinations; import io.vavr.control.Option; import java.io.Serializable; import java.util.*; import java.util.function.*; import java.util.stream.Collector; import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE; import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE; import static java.util.Arrays.copyOf; import static java.util.Arrays.sort; /** * Array is a Traversable wrapper for {@code Object[]} containing elements of type {@code T}. * * @param Component type * @author Ruslan Sennov, Daniel Dietrich */ public final class Array implements IndexedSeq, Serializable { private static final long serialVersionUID = 1L; private static final Array EMPTY = new Array<>(new Object[0]); private final Object[] delegate; private Array(Object[] delegate) { this.delegate = delegate; } static Array wrap(Object[] array) { return (array.length == 0) ? empty() : new Array<>(array); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link Array}. * * @param Component type of the Array. * @return A {@link Array} Collector. */ public static Collector, Array> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, Array> finisher = Array::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } @SuppressWarnings("unchecked") public static Array empty() { return (Array) EMPTY; } /** * Narrows a widened {@code Array} to {@code Array} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param array An {@code Array}. * @param Component type of the {@code Array}. * @return the given {@code array} instance as narrowed type {@code Array}. */ @SuppressWarnings("unchecked") public static Array narrow(Array array) { return (Array) array; } /** * Returns a singleton {@code Array}, i.e. a {@code Array} of one element. * * @param element An element. * @param The component type * @return A new Array instance containing the given element */ public static Array of(T element) { return wrap(new Object[] { element }); } /** * Creates an Array of the given elements. * * @param Component type of the Array. * @param elements Zero or more elements. * @return An Array containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Array of(T... elements) { Objects.requireNonNull(elements, "elements is null"); return wrap(copyOf(elements, elements.length)); } /** * Creates an Array of the given elements. *

* The resulting Array has the same iteration order as the given iterable of elements * if the iteration order of the elements is stable. * * @param Component type of the Array. * @param elements An Iterable of elements. * @return An Array containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("unchecked") public static Array ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); return elements instanceof Array ? (Array) elements : wrap(toArray(elements)); } /** * Creates an Array that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return An Array containing the given elements in the same order. */ public static Array ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return wrap(javaStream.toArray()); } /** * Creates an Array from boolean values. * * @param elements boolean values * @return A new Array of Boolean values * @throws NullPointerException if elements is null */ public static Array ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates an Array from byte values. * * @param elements byte values * @return A new Array of Byte values * @throws NullPointerException if elements is null */ public static Array ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates an Array from char values. * * @param elements char values * @return A new Array of Character values * @throws NullPointerException if elements is null */ public static Array ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates an Array from double values. * * @param elements double values * @return A new Array of Double values * @throws NullPointerException if elements is null */ public static Array ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates an Array from float values. * * @param elements float values * @return A new Array of Float values * @throws NullPointerException if elements is null */ public static Array ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates an Array from int values. * * @param elements int values * @return A new Array of Integer values * @throws NullPointerException if elements is null */ public static Array ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates an Array from long values. * * @param elements long values * @return A new Array of Long values * @throws NullPointerException if elements is null */ public static Array ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates an Array from short values. * * @param elements short values * @return A new Array of Short values * @throws NullPointerException if elements is null */ public static Array ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Returns an Array containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the Array * @param n The number of elements in the Array * @param f The Function computing element values * @return An Array consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static Array tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return io.vavr.collection.Collections.tabulate(n, f, empty(), Array::of); } /** * Returns an Array containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the Array * @param n The number of elements in the Array * @param s The Supplier computing element values * @return An Array of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static Array fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return io.vavr.collection.Collections.fill(n, s, empty(), Array::of); } /** * Returns an Array containing {@code n} times the given {@code element} * * @param Component type of the Array * @param n The number of elements in the Array * @param element The element * @return An Array of size {@code n}, where each element is the given {@code element}. */ public static Array fill(int n, T element) { return io.vavr.collection.Collections.fillObject(n, element, empty(), Array::of); } public static Array range(char from, char toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } public static Array rangeBy(char from, char toExclusive, int step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } @GwtIncompatible public static Array rangeBy(double from, double toExclusive, double step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates an Array of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Array.range(0, 0)  // = Array()
     * Array.range(2, 0)  // = Array()
     * Array.range(-2, 2) // = Array(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ public static Array range(int from, int toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } /** * Creates an Array of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Array.rangeBy(1, 3, 1)  // = Array(1, 2)
     * Array.rangeBy(1, 4, 2)  // = Array(1, 3)
     * Array.rangeBy(4, 1, -2) // = Array(4, 2)
     * Array.rangeBy(4, 1, 2)  // = Array()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Array rangeBy(int from, int toExclusive, int step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates an Array of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Array.range(0L, 0L)  // = Array()
     * Array.range(2L, 0L)  // = Array()
     * Array.range(-2L, 2L) // = Array(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ public static Array range(long from, long toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } /** * Creates an Array of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Array.rangeBy(1L, 3L, 1L)  // = Array(1L, 2L)
     * Array.rangeBy(1L, 4L, 2L)  // = Array(1L, 3L)
     * Array.rangeBy(4L, 1L, -2L) // = Array(4L, 2L)
     * Array.rangeBy(4L, 1L, 2L)  // = Array()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Array rangeBy(long from, long toExclusive, long step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static Array rangeClosed(char from, char toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } public static Array rangeClosedBy(char from, char toInclusive, int step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @GwtIncompatible public static Array rangeClosedBy(double from, double toInclusive, double step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates an Array of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Array.rangeClosed(0, 0)  // = Array(0)
     * Array.rangeClosed(2, 0)  // = Array()
     * Array.rangeClosed(-2, 2) // = Array(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ public static Array rangeClosed(int from, int toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates an Array of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Array.rangeClosedBy(1, 3, 1)  // = Array(1, 2, 3)
     * Array.rangeClosedBy(1, 4, 2)  // = Array(1, 3)
     * Array.rangeClosedBy(4, 1, -2) // = Array(4, 2)
     * Array.rangeClosedBy(4, 1, 2)  // = Array()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Array rangeClosedBy(int from, int toInclusive, int step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates an Array of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Array.rangeClosed(0L, 0L)  // = Array(0L)
     * Array.rangeClosed(2L, 0L)  // = Array()
     * Array.rangeClosed(-2L, 2L) // = Array(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ public static Array rangeClosed(long from, long toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates an Array of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Array.rangeClosedBy(1L, 3L, 1L)  // = Array(1L, 2L, 3L)
     * Array.rangeClosedBy(1L, 4L, 2L)  // = Array(1L, 3L)
     * Array.rangeClosedBy(4L, 1L, -2L) // = Array(4L, 2L)
     * Array.rangeClosedBy(4L, 1L, 2L)  // = Array()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Array rangeClosedBy(long from, long toInclusive, long step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Transposes the rows and columns of an {@link Array} matrix. * * @param matrix to be transposed. * @return a transposed {@link Array} matrix. * @throws IllegalArgumentException if the row lengths of {@code matrix} differ. *

* ex: {@code * Array.transpose(Array(Array(1,2,3), Array(4,5,6))) → Array(Array(1,4), Array(2,5), Array(3,6)) * } */ static Array> transpose(Array> matrix) { return io.vavr.collection.Collections.transpose(matrix, Array::ofAll, Array::of); } /** * Creates an Array from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Array, otherwise {@code Some} {@code Tuple} * of the element for the next call and the value to add to the * resulting Array. *

* Example: *

     * 
     * Array.unfoldRight(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<gt;(x, x-1)));
     * // Array(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return an Array with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Array unfoldRight(T seed, Function>> f) { return Iterator.unfoldRight(seed, f).toArray(); } /** * Creates an Array from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the list, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting list and * the element for the next call. *

* Example: *

     * 
     * Array.unfoldLeft(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<gt;(x-1, x)));
     * // Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return an Array with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Array unfoldLeft(T seed, Function>> f) { return Iterator.unfoldLeft(seed, f).toArray(); } /** * Creates an Array from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the list, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting list and * the element for the next call. *

* Example: *

     * 
     * Array.unfold(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<gt;(x-1, x)));
     * // Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds and unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return an Array with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Array unfold(T seed, Function>> f) { return Iterator.unfold(seed, f).toArray(); } @Override public Array append(T element) { final Object[] copy = copyOf(delegate, delegate.length + 1); copy[delegate.length] = element; return wrap(copy); } @Override public Array appendAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() && elements instanceof Array) { @SuppressWarnings("unchecked") final Array array = (Array) elements; return array; } final Object[] source = toArray(elements); if (source.length == 0) { return this; } else { final Object[] arr = copyOf(delegate, delegate.length + source.length); System.arraycopy(source, 0, arr, delegate.length, source.length); return wrap(arr); } } @GwtIncompatible @Override public java.util.List asJava() { return JavaConverters.asJava(this, IMMUTABLE); } @GwtIncompatible @Override public Array asJava(Consumer> action) { return Collections.asJava(this, action, IMMUTABLE); } @GwtIncompatible @Override public java.util.List asJavaMutable() { return JavaConverters.asJava(this, MUTABLE); } @GwtIncompatible @Override public Array asJavaMutable(Consumer> action) { return Collections.asJava(this, action, MUTABLE); } @Override public Array collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } @Override public boolean hasDefiniteSize() { return true; } /** * An {@code Array} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } /** * An {@code Array} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } @SuppressWarnings("unchecked") @Override public Iterator iterator() { return new AbstractIterator() { private int index = 0; @Override public boolean hasNext() { return index < delegate.length; } @Override public T getNext() { return (T) delegate[index++]; } }; } @Override public Array> combinations() { return rangeClosed(0, length()).map(this::combinations).flatMap(Function.identity()); } @Override public Array> combinations(int k) { return Combinations.apply(this, Math.max(k, 0)); } @Override public Iterator> crossProduct(int power) { return io.vavr.collection.Collections.crossProduct(empty(), this, power); } @SuppressWarnings("unchecked") @Override public T get(int index) { if (index < 0 || index >= length()) { throw new IndexOutOfBoundsException("get(" + index + ")"); } return (T) delegate[index]; } @Override public Array distinct() { return distinctBy(Function.identity()); } @Override public Array distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final java.util.Set seen = new java.util.TreeSet<>(comparator); return filter(seen::add); } @Override public Array distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); final java.util.Set seen = new java.util.HashSet<>(); return filter(t -> seen.add(keyExtractor.apply(t))); } @Override public Array drop(int n) { if (n <= 0) { return this; } else if (n >= length()) { return empty(); } else { final Object[] arr = new Object[delegate.length - n]; System.arraycopy(delegate, n, arr, 0, arr.length); return wrap(arr); } } @Override public Array dropUntil(Predicate predicate) { return io.vavr.collection.Collections.dropUntil(this, predicate); } @Override public Array dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropUntil(predicate.negate()); } @Override public Array dropRight(int n) { if (n <= 0) { return this; } else if (n >= length()) { return empty(); } else { return wrap(copyOf(delegate, delegate.length - n)); } } @Override public Array dropRightUntil(Predicate predicate) { return io.vavr.collection.Collections.dropRightUntil(this, predicate); } @Override public Array dropRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropRightUntil(predicate.negate()); } @Override public Array filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final java.util.List list = new ArrayList<>(); for (T t : this) { if (predicate.test(t)) { list.add(t); } } if (list.isEmpty()) { return empty(); } else if (list.size() == size()) { return this; } else { return wrap(list.toArray()); } } @Override public Array reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Collections.reject(this, predicate); } @Override public Array flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final java.util.List list = new ArrayList<>(); for (T t : this) { for (U u : mapper.apply(t)) { list.add(u); } } return wrap(list.toArray()); } } @Override public Map> groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(this, classifier, Array::ofAll); } @Override public Iterator> grouped(int size) { return sliding(size, size); } @SuppressWarnings("unchecked") @Override public T head() { if (isEmpty()) { throw new NoSuchElementException("head on empty Array"); } else { return (T) delegate[0]; } } @Override public int indexOf(T element, int from) { for (int i = from; i < length(); i++) { if (Objects.equals(get(i), element)) { return i; } } return -1; } @Override public Array init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty Array"); } return dropRight(1); } @Override public Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override public boolean isEmpty() { return delegate.length == 0; } private Object readResolve() { return isEmpty() ? EMPTY : this; } @Override public Array insert(int index, T element) { if (index < 0 || index > length()) { throw new IndexOutOfBoundsException("insert(" + index + ", e) on Array of length " + length()); } final Object[] arr = new Object[delegate.length + 1]; System.arraycopy(delegate, 0, arr, 0, index); arr[index] = element; System.arraycopy(delegate, index, arr, index + 1, delegate.length - index); return wrap(arr); } @Override public Array insertAll(int index, Iterable elements) { if (index < 0 || index > length()) { throw new IndexOutOfBoundsException("insert(" + index + ", e) on Array of length " + length()); } if (isEmpty() && elements instanceof Array) { @SuppressWarnings("unchecked") final Array array = (Array) elements; return array; } final Object[] list = toArray(elements); if (list.length == 0) { return this; } else { final Object[] arr = new Object[delegate.length + list.length]; System.arraycopy(delegate, 0, arr, 0, index); System.arraycopy(list, 0, arr, index, list.length); System.arraycopy(delegate, index, arr, index + list.length, delegate.length - index); return wrap(arr); } } @Override public Array intersperse(T element) { if (delegate.length <= 1) { return this; } else { final Object[] arr = new Object[delegate.length * 2 - 1]; for (int i = 0; i < delegate.length; i++) { arr[i * 2] = delegate[i]; if (i > 0) { arr[i * 2 - 1] = element; } } return wrap(arr); } } @Override public int lastIndexOf(T element, int end) { for (int i = Math.min(end, length() - 1); i >= 0; i--) { if (Objects.equals(get(i), element)) { return i; } } return -1; } @Override public int length() { return delegate.length; } @Override public Array map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); final Object[] arr = new Object[length()]; for (int i = 0; i < delegate.length; i++) { arr[i] = mapper.apply(get(i)); } return wrap(arr); } @Override public Array orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override public Array orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override public Array padTo(int length, T element) { final int actualLength = length(); if (length <= actualLength) { return this; } else { return appendAll(Iterator.continually(element).take(length - actualLength)); } } @Override public Array leftPadTo(int length, T element) { final int actualLength = length(); if (length <= actualLength) { return this; } else { return prependAll(Iterator.continually(element).take(length - actualLength)); } } @Override public Array patch(int from, Iterable that, int replaced) { from = from < 0 ? 0 : from; replaced = replaced < 0 ? 0 : replaced; Array result = take(from).appendAll(that); from += replaced; result = result.appendAll(drop(from)); return result; } @Override public Tuple2, Array> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final java.util.List left = new ArrayList<>(), right = new ArrayList<>(); for (T t : this) { (predicate.test(t) ? left : right).add(t); } return Tuple.of(ofAll(left), ofAll(right)); } @Override public Array peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return this; } @Override public Array> permutations() { if (isEmpty()) { return empty(); } else if (delegate.length == 1) { return of(this); } else { final Array> zero = empty(); return distinct().foldLeft(zero, (xs, x) -> { final Function, Array> prepend = l -> l.prepend(x); return xs.appendAll(remove(x).permutations().map(prepend)); }); } } @Override public Array prepend(T element) { return insert(0, element); } @Override public Array prependAll(Iterable elements) { return insertAll(0, elements); } @Override public Array remove(T element) { int index = -1; for (int i = 0; i < length(); i++) { final T value = get(i); if (Objects.equals(element, value)) { index = i; break; } } if (index < 0) { return this; } else { return removeAt(index); } } @Override public Array removeFirst(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); int found = -1; for (int i = 0; i < length(); i++) { final T value = get(i); if (predicate.test(value)) { found = i; break; } } if (found < 0) { return this; } else { return removeAt(found); } } @Override public Array removeLast(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); int found = -1; for (int i = length() - 1; i >= 0; i--) { final T value = get(i); if (predicate.test(value)) { found = i; break; } } if (found < 0) { return this; } else { return removeAt(found); } } @Override public Array removeAt(int index) { if (index < 0) { throw new IndexOutOfBoundsException("removeAt(" + index + ")"); } else if (index >= length()) { throw new IndexOutOfBoundsException("removeAt(" + index + ")"); } else { final Object[] arr = new Object[length() - 1]; System.arraycopy(delegate, 0, arr, 0, index); System.arraycopy(delegate, index + 1, arr, index, length() - index - 1); return wrap(arr); } } @Override public Array removeAll(T element) { return io.vavr.collection.Collections.removeAll(this, element); } @Override public Array removeAll(Iterable elements) { return io.vavr.collection.Collections.removeAll(this, elements); } @Override @Deprecated public Array removeAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override public Array replace(T currentElement, T newElement) { final Object[] arr = new Object[length()]; boolean found = false; for (int i = 0; i < length(); i++) { final T value = get(i); if (found) { arr[i] = delegate[i]; } else { if (Objects.equals(currentElement, value)) { arr[i] = newElement; found = true; } else { arr[i] = delegate[i]; } } } return found ? wrap(arr) : this; } @Override public Array replaceAll(T currentElement, T newElement) { final Object[] arr = new Object[length()]; boolean changed = false; for (int i = 0; i < length(); i++) { final T value = get(i); if (Objects.equals(currentElement, value)) { arr[i] = newElement; changed = true; } else { arr[i] = delegate[i]; } } return changed ? wrap(arr) : this; } @Override public Array retainAll(Iterable elements) { return io.vavr.collection.Collections.retainAll(this, elements); } @Override public Array reverse() { if (size() <= 1) { return this; } else { final int length = delegate.length; final Object[] arr = new Object[length]; for (int i = 0, j = length - 1; i < length; i++, j--) { arr[j] = delegate[i]; } return wrap(arr); } } @Override public Array rotateLeft(int n) { return Collections.rotateLeft(this, n); } @Override public Array rotateRight(int n) { return Collections.rotateRight(this, n); } @Override public Array scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override public Array scanLeft(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, Array::ofAll); } @Override public Array scanRight(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, Array::ofAll); } @Override public Array shuffle() { return io.vavr.collection.Collections.shuffle(this, Array::ofAll); } @Override public Array slice(int beginIndex, int endIndex) { if (beginIndex >= endIndex || beginIndex >= length() || isEmpty()) { return empty(); } if (beginIndex <= 0 && endIndex >= length()) { return this; } final int index = Math.max(beginIndex, 0); final int length = Math.min(endIndex, length()) - index; final Object[] arr = new Object[length]; System.arraycopy(delegate, index, arr, 0, length); return wrap(arr); } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(Array::ofAll); } @Override public Iterator> sliding(int size) { return sliding(size, 1); } @Override public Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(Array::ofAll); } @Override public Array sorted() { final Object[] arr = copyOf(delegate, delegate.length); sort(arr); return wrap(arr); } @SuppressWarnings("unchecked") @Override public Array sorted(Comparator comparator) { final Object[] arr = copyOf(delegate, delegate.length); sort(arr, (o1, o2) -> comparator.compare((T) o1, (T) o2)); return wrap(arr); } @Override public > Array sortBy(Function mapper) { return sortBy(U::compareTo, mapper); } @Override public Array sortBy(Comparator comparator, Function mapper) { return Collections.sortBy(this, comparator, mapper, collector()); } @Override public Tuple2, Array> splitAt(int n) { return Tuple.of(take(n), drop(n)); } @Override public Tuple2, Array> splitAt(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Array init = takeWhile(predicate.negate()); return Tuple.of(init, drop(init.length())); } @Override public Tuple2, Array> splitAtInclusive(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = 0; i < delegate.length; i++) { final T value = get(i); if (predicate.test(value)) { if (i == delegate.length - 1) { return Tuple.of(this, empty()); } else { return Tuple.of(take(i + 1), drop(i + 1)); } } } return Tuple.of(this, empty()); } @Override public Tuple2, Array> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Tuple.of(takeWhile(predicate), dropWhile(predicate)); } @Override public Array subSequence(int beginIndex) { if (beginIndex < 0 || beginIndex > length()) { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ")"); } else { return drop(beginIndex); } } @Override public Array subSequence(int beginIndex, int endIndex) { Collections.subSequenceRangeCheck(beginIndex, endIndex, length()); if (beginIndex == endIndex) { return empty(); } else if (beginIndex == 0 && endIndex == length()) { return this; } else { final Object[] arr = new Object[endIndex - beginIndex]; System.arraycopy(delegate, beginIndex, arr, 0, arr.length); return wrap(arr); } } @Override public Array tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail() on empty Array"); } else { final Object[] arr = new Object[delegate.length - 1]; System.arraycopy(delegate, 1, arr, 0, arr.length); return wrap(arr); } } @Override public Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override public Array take(int n) { if (n >= length()) { return this; } else if (n <= 0) { return empty(); } else { return wrap(copyOf(delegate, n)); } } @Override public Array takeUntil(Predicate predicate) { return io.vavr.collection.Collections.takeUntil(this, predicate); } @Override public Array takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeUntil(predicate.negate()); } @Override public Array takeRight(int n) { if (n >= length()) { return this; } else if (n <= 0) { return empty(); } else { final Object[] arr = new Object[n]; System.arraycopy(delegate, delegate.length - n, arr, 0, n); return wrap(arr); } } @Override public Array takeRightUntil(Predicate predicate) { return io.vavr.collection.Collections.takeRightUntil(this, predicate); } @Override public Array takeRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeRightUntil(predicate.negate()); } /** * Transforms this {@code Array}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public Tuple2, Array> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (isEmpty()) { return Tuple.of(empty(), empty()); } else { final Object[] xs = new Object[delegate.length]; final Object[] ys = new Object[delegate.length]; for (int i = 0; i < delegate.length; i++) { final Tuple2 t = unzipper.apply(get(i)); xs[i] = t._1; ys[i] = t._2; } return Tuple.of(wrap(xs), wrap(ys)); } } @Override public Tuple3, Array, Array> unzip3(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (isEmpty()) { return Tuple.of(empty(), empty(), empty()); } else { final Object[] xs = new Object[delegate.length]; final Object[] ys = new Object[delegate.length]; final Object[] zs = new Object[delegate.length]; for (int i = 0; i < delegate.length; i++) { final Tuple3 t = unzipper.apply(get(i)); xs[i] = t._1; ys[i] = t._2; zs[i] = t._3; } return Tuple.of(wrap(xs), wrap(ys), wrap(zs)); } } @Override public Array update(int index, T element) { if ((index < 0) || (index >= length())) { throw new IndexOutOfBoundsException("update(" + index + ")"); } else { final Object[] arr = copyOf(delegate, delegate.length); arr[index] = element; return wrap(arr); } } @Override public Array update(int index, Function updater) { Objects.requireNonNull(updater, "updater is null"); return update(index, updater.apply(get(index))); } @Override public Array> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public Array zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return ofAll(iterator().zipWith(that, mapper)); } @Override public Array> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public Array> zipWithIndex() { return ofAll(iterator().zipWithIndex()); } @Override public Array zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return ofAll(iterator().zipWithIndex(mapper)); } @Override public boolean equals(Object o) { return io.vavr.collection.Collections.equals(this, o); } @Override public int hashCode() { return io.vavr.collection.Collections.hashOrdered(this); } @Override public String stringPrefix() { return "Array"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } private static Object[] toArray(Iterable elements) { if (elements instanceof Array) { final Array array = (Array) elements; return array.delegate; } else { return io.vavr.collection.Collections.withSize(elements).toArray(); } } } interface ArrayModule { final class Combinations { static Array> apply(Array elements, int k) { if (k == 0) { return Array.of(Array.empty()); } else { return elements.zipWithIndex().flatMap( t -> apply(elements.drop(t._2 + 1), (k - 1)).map(c -> c.prepend(t._1)) ); } } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/BitMappedTrie.java000066400000000000000000000360331342074374400252510ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import java.io.Serializable; import java.util.NoSuchElementException; import java.util.function.Function; import java.util.function.Predicate; import static java.util.function.Function.identity; import static io.vavr.collection.ArrayType.obj; import static io.vavr.collection.Collections.withSize; import static io.vavr.collection.NodeModifier.COPY_NODE; import static io.vavr.collection.NodeModifier.IDENTITY; /** * A `bit-mapped trie` is a very wide and shallow tree (for integer indices the depth will be `≤6`). * Each node has a maximum of `32` children (configurable). * Access to a given position is done by converting the index to a base 32 number and using each digit to descend down the tree. * Modifying the tree is done similarly, but along the way the path is copied, returning a new root every time. * `Append` inserts in the last leaf, or if the tree is full from the right, it adds another layer on top of it (the old root will be the first of the new one). * `Prepend` is done similarly, but an offset is needed, because adding a new top node (where the current root would be the last node of the new root) * shifts the indices by half of the current tree's full size. The `offset` shifts them back to the correct index. * `Slice` is done by trimming the path from the root and discarding any `leading`/`trailing` values in effectively constant time (without memory leak, as in `Java`/`Clojure`). * * @author Pap Lőrinc */ final class BitMappedTrie implements Serializable { static final int BRANCHING_BASE = 5; static final int BRANCHING_FACTOR = 1 << BRANCHING_BASE; static final int BRANCHING_MASK = -1 >>> -BRANCHING_BASE; static int firstDigit(int num, int depthShift) { return num >> depthShift; } static int digit(int num, int depthShift) { return lastDigit(firstDigit(num, depthShift)); } static int lastDigit(int num) { return num & BRANCHING_MASK; } private static final long serialVersionUID = 1L; private static final BitMappedTrie EMPTY = new BitMappedTrie<>(obj(), obj().empty(), 0, 0, 0); @SuppressWarnings("unchecked") static BitMappedTrie empty() { return (BitMappedTrie) EMPTY; } final ArrayType type; private final Object array; private final int offset, length; private final int depthShift; private BitMappedTrie(ArrayType type, Object array, int offset, int length, int depthShift) { this.type = type; this.array = array; this.offset = offset; this.length = length; this.depthShift = depthShift; } private static int treeSize(int branchCount, int depthShift) { final int fullBranchSize = 1 << depthShift; return branchCount * fullBranchSize; } static BitMappedTrie ofAll(Object array) { final ArrayType type = ArrayType.of(array); final int size = type.lengthOf(array); return (size == 0) ? empty() : ofAll(array, type, size); } private static BitMappedTrie ofAll(Object array, ArrayType type, int size) { int shift = 0; for (ArrayType t = type; t.lengthOf(array) > BRANCHING_FACTOR; shift += BRANCHING_BASE) { array = t.grouped(array, BRANCHING_FACTOR); t = obj(); } return new BitMappedTrie<>(type, array, 0, size, shift); } private BitMappedTrie boxed() { return map(identity()); } BitMappedTrie prependAll(Iterable iterable) { final Collections.IterableWithSize iter = withSize(iterable); try { return prepend(iter.reverseIterator(), iter.size()); } catch (ClassCastException ignored) { return boxed().prepend(iter.reverseIterator(), iter.size()); } } private BitMappedTrie prepend(java.util.Iterator iterator, int size) { BitMappedTrie result = this; while (size > 0) { Object array = result.array; int shift = result.depthShift, offset = result.offset; if (result.isFullLeft()) { array = obj().copyUpdate(obj().empty(), BRANCHING_FACTOR - 1, array); shift += BRANCHING_BASE; offset = treeSize(BRANCHING_FACTOR - 1, shift); } final int index = offset - 1; final int delta = Math.min(size, lastDigit(index) + 1); size -= delta; array = result.modify(array, shift, index, COPY_NODE, prependToLeaf(iterator)); result = new BitMappedTrie<>(type, array, offset - delta, result.length + delta, shift); } return result; } private boolean isFullLeft() { return offset == 0; } private NodeModifier prependToLeaf(java.util.Iterator iterator) { return (array, index) -> { final Object copy = type.copy(array, BRANCHING_FACTOR); while (iterator.hasNext() && index >= 0) { type.setAt(copy, index--, iterator.next()); } return copy; }; } BitMappedTrie appendAll(Iterable iterable) { final Collections.IterableWithSize iter = withSize(iterable); try { return append(iter.iterator(), iter.size()); } catch (ClassCastException ignored) { return boxed().append(iter.iterator(), iter.size()); } } private BitMappedTrie append(java.util.Iterator iterator, int size) { BitMappedTrie result = this; while (size > 0) { Object array = result.array; int shift = result.depthShift; if (result.isFullRight()) { array = obj().asArray(array); shift += BRANCHING_BASE; } final int index = offset + result.length; final int leafSpace = lastDigit(index); final int delta = Math.min(size, BRANCHING_FACTOR - leafSpace); size -= delta; array = result.modify(array, shift, index, COPY_NODE, appendToLeaf(iterator, leafSpace + delta)); result = new BitMappedTrie<>(type, array, offset, result.length + delta, shift); } return result; } private boolean isFullRight() { return (offset + length + 1) > treeSize(BRANCHING_FACTOR, depthShift); } private NodeModifier appendToLeaf(java.util.Iterator iterator, int leafSize) { return (array, index) -> { final Object copy = type.copy(array, leafSize); while (iterator.hasNext() && index < leafSize) { type.setAt(copy, index++, iterator.next()); } return copy; }; } BitMappedTrie update(int index, T element) { try { final Object root = modify(array, depthShift, offset + index, COPY_NODE, updateLeafWith(type, element)); return new BitMappedTrie<>(type, root, offset, length, depthShift); } catch (ClassCastException ignored) { return boxed().update(index, element); } } private NodeModifier updateLeafWith(ArrayType type, T element) { return (a, i) -> type.copyUpdate(a, i, element); } BitMappedTrie drop(int n) { if (n <= 0) { return this; } else if (n >= length) { return empty(); } else { final int index = offset + n; final Object root = arePointingToSameLeaf(0, n) ? array : modify(array, depthShift, index, obj()::copyDrop, IDENTITY); return collapsed(type, root, index, length - n, depthShift); } } BitMappedTrie take(int n) { if (n >= length) { return this; } else if (n <= 0) { return empty(); } else { final int index = n - 1; final Object root = arePointingToSameLeaf(index, length - 1) ? array : modify(array, depthShift, offset + index, obj()::copyTake, IDENTITY); return collapsed(type, root, offset, n, depthShift); } } private boolean arePointingToSameLeaf(int i, int j) { return firstDigit(offset + i, BRANCHING_BASE) == firstDigit(offset + j, BRANCHING_BASE); } /* drop root node while it has a single element */ private static BitMappedTrie collapsed(ArrayType type, Object array, int offset, int length, int shift) { for (; shift > 0; shift -= BRANCHING_BASE) { final int skippedElements = obj().lengthOf(array) - 1; if (skippedElements != digit(offset, shift)) { break; } array = obj().getAt(array, skippedElements); offset -= treeSize(skippedElements, shift); } return new BitMappedTrie<>(type, array, offset, length, shift); } /* descend the tree from root to leaf, applying the given modifications along the way, returning the new root */ private Object modify(Object root, int depthShift, int index, NodeModifier node, NodeModifier leaf) { return (depthShift == 0) ? leaf.apply(root, index) : modifyNonLeaf(root, depthShift, index, node, leaf); } private Object modifyNonLeaf(Object root, int depthShift, int index, NodeModifier node, NodeModifier leaf) { int previousIndex = firstDigit(index, depthShift); root = node.apply(root, previousIndex); Object array = root; for (int shift = depthShift - BRANCHING_BASE; shift >= BRANCHING_BASE; shift -= BRANCHING_BASE) { final int prev = previousIndex; previousIndex = digit(index, shift); array = setNewNode(node, prev, array, previousIndex); } final Object newLeaf = leaf.apply(obj().getAt(array, previousIndex), lastDigit(index)); obj().setAt(array, previousIndex, newLeaf); return root; } private Object setNewNode(NodeModifier node, int previousIndex, Object array, int offset) { final Object previous = obj().getAt(array, previousIndex); final Object newNode = node.apply(previous, offset); obj().setAt(array, previousIndex, newNode); return newNode; } T get(int index) { final Object leaf = getLeaf(index); final int leafIndex = lastDigit(offset + index); return type.getAt(leaf, leafIndex); } /** * fetch the leaf, corresponding to the given index. * Node: the offset and length should be taken into consideration as there may be leading and trailing garbage. * Also, the returned array is mutable, but should not be mutated! */ @SuppressWarnings("WeakerAccess") Object getLeaf(int index) { if (depthShift == 0) { return array; } else { return getLeafGeneral(index); } } private Object getLeafGeneral(int index) { index += offset; Object leaf = obj().getAt(array, firstDigit(index, depthShift)); for (int shift = depthShift - BRANCHING_BASE; shift > 0; shift -= BRANCHING_BASE) { leaf = obj().getAt(leaf, digit(index, shift)); } return leaf; } Iterator iterator() { return new Iterator() { private final int globalLength = BitMappedTrie.this.length; private int globalIndex = 0; private int index = lastDigit(offset); private Object leaf = getLeaf(globalIndex); private int length = type.lengthOf(leaf); @Override public boolean hasNext() { return globalIndex < globalLength; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException("next() on empty iterator"); } if (index == length) { setCurrentArray(); } final T next = type.getAt(leaf, index); index++; globalIndex++; return next; } private void setCurrentArray() { index = 0; leaf = getLeaf(globalIndex); length = type.lengthOf(leaf); } }; } @SuppressWarnings("unchecked") int visit(LeafVisitor visitor) { int globalIndex = 0, start = lastDigit(offset); for (int index = 0; index < length; ) { final T2 leaf = (T2) getLeaf(index); final int end = getMin(start, index, leaf); globalIndex = visitor.visit(globalIndex, leaf, start, end); index += end - start; start = 0; } return globalIndex; } private int getMin(int start, int index, Object leaf) { return Math.min(type.lengthOf(leaf), start + length - index); } BitMappedTrie filter(Predicate predicate) { final Object results = type.newInstance(length()); final int length = this. visit((index, leaf, start, end) -> filter(predicate, results, index, leaf, start, end)); return (this.length == length) ? this : BitMappedTrie.ofAll(type.copyRange(results, 0, length)); } private int filter(Predicate predicate, Object results, int index, T leaf, int start, int end) { for (int i = start; i < end; i++) { final T value = type.getAt(leaf, i); if (predicate.test(value)) { type.setAt(results, index++, value); } } return index; } BitMappedTrie map(Function mapper) { final Object results = obj().newInstance(length); this. visit((index, leaf, start, end) -> map(mapper, results, index, leaf, start, end)); return BitMappedTrie.ofAll(results); } private int map(Function mapper, Object results, int index, T leaf, int start, int end) { for (int i = start; i < end; i++) { obj().setAt(results, index++, mapper.apply(type.getAt(leaf, i))); } return index; } int length() { return length; } } @FunctionalInterface interface NodeModifier { Object apply(Object array, int index); NodeModifier COPY_NODE = (o, i) -> obj().copy(o, i + 1); NodeModifier IDENTITY = (o, i) -> o; } @FunctionalInterface interface LeafVisitor { int visit(int index, T leaf, int start, int end); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/BitSet.java000066400000000000000000001160501342074374400237500ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Function1; import io.vavr.PartialFunction; import io.vavr.Tuple3; import io.vavr.Tuple2; import io.vavr.control.Option; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.*; import java.util.stream.Collector; /** * An immutable {@code BitSet} implementation. * * @author Ruslan Sennov */ public interface BitSet extends SortedSet { long serialVersionUID = 1L; class Builder { final static Builder DEFAULT = new Builder<>(i -> i, i -> i); final Function1 fromInt; final Function1 toInt; Builder(Function1 fromInt, Function1 toInt) { this.fromInt = fromInt; this.toInt = toInt; } public Collector, BitSet> collector() { final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; return Collector.of(ArrayList::new, ArrayList::add, combiner, this::ofAll); } public BitSet empty() { return new BitSetModule.BitSet1<>(fromInt, toInt, 0L); } public BitSet of(T t) { final int value = toInt.apply(t); if (value < BitSetModule.BITS_PER_WORD) { return new BitSetModule.BitSet1<>(fromInt, toInt, 1L << value); } else if (value < 2 * BitSetModule.BITS_PER_WORD) { return new BitSetModule.BitSet2<>(fromInt, toInt, 0L, 1L << value); } else { return empty().add(t); } } @SuppressWarnings("varargs") @SafeVarargs public final BitSet of(T... values) { return empty().addAll(Array.wrap(values)); } public BitSet ofAll(Iterable values) { Objects.requireNonNull(values, "values is null"); return empty().addAll(values); } public BitSet ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return empty().addAll(Iterator.ofAll(javaStream.iterator())); } public BitSet tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return empty().addAll(Collections.tabulate(n, f)); } public BitSet fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return empty().addAll(Collections.fill(n, s)); } } static Builder withRelations(Function1 fromInt, Function1 toInt) { return new Builder<>(fromInt, toInt); } @SuppressWarnings("RedundantTypeArguments") static > Builder withEnum(Class enumClass) { return new Builder<>(i -> enumClass.getEnumConstants()[i], Enum::ordinal); } static Builder withCharacters() { return new Builder<>(i -> (char) i.intValue(), c -> (int) c); } static Builder withBytes() { return new Builder<>(Integer::byteValue, Byte::intValue); } static Builder withLongs() { return new Builder<>(Integer::longValue, Long::intValue); } static Builder withShorts() { return new Builder<>(Integer::shortValue, Short::intValue); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link BitSet}. * * @return A {@link BitSet} Collector. */ static Collector, BitSet> collector() { return Builder.DEFAULT.collector(); } static BitSet empty() { return Builder.DEFAULT.empty(); } static BitSet of(Integer value) { return Builder.DEFAULT.of(value); } static BitSet of(Integer... values) { return Builder.DEFAULT.of(values); } /** * Returns a BitSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param n The number of elements in the BitSet * @param f The Function computing element values * @return A BitSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ static BitSet tabulate(int n, Function f) { return Builder.DEFAULT.tabulate(n, f); } /** * Returns a BitSet containing {@code n} values supplied by a given Supplier {@code s}. * * @param n The number of elements in the BitSet * @param s The Supplier computing element values * @return A BitSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ static BitSet fill(int n, Supplier s) { return Builder.DEFAULT.fill(n, s); } static BitSet ofAll(Iterable values) { return Builder.DEFAULT.ofAll(values); } static BitSet ofAll(java.util.stream.Stream javaStream) { return Builder.DEFAULT.ofAll(javaStream); } /** * Creates a BitSet from boolean values. * * @param elements boolean values * @return A new BitSet of boolean values * @throws NullPointerException if elements is null */ static BitSet ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return BitSet.withRelations(i -> i != 0, b -> b ? 1 : 0).ofAll(Iterator.ofAll(elements)); } /** * Creates a BitSet from byte values. * * @param elements byte values * @return A new BitSet of byte values * @throws NullPointerException if elements is null */ static BitSet ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return BitSet.withBytes().ofAll(Iterator.ofAll(elements)); } /** * Creates a BitSet from char values. * * @param elements char values * @return A new BitSet of char values * @throws NullPointerException if elements is null */ static BitSet ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return BitSet.withCharacters().ofAll(Iterator.ofAll(elements)); } /** * Creates a BitSet from int values. * * @param elements int values * @return A new BitSet of int values * @throws NullPointerException if elements is null */ static BitSet ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return BitSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a BitSet from long values. * * @param elements long values * @return A new BitSet of long values * @throws NullPointerException if elements is null */ static BitSet ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return BitSet.withLongs().ofAll(Iterator.ofAll(elements)); } /** * Creates a BitSet from short values. * * @param elements short values * @return A new BitSet of short values * @throws NullPointerException if elements is null */ static BitSet ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return BitSet.withShorts().ofAll(Iterator.ofAll(elements)); } /** * Creates a BitSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. * * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ static BitSet range(int from, int toExclusive) { return BitSet.ofAll(Iterator.range(from, toExclusive)); } static BitSet range(char from, char toExclusive) { return BitSet.withCharacters().ofAll(Iterator.range(from, toExclusive)); } static BitSet range(long from, long toExclusive) { return BitSet.withLongs().ofAll(Iterator.range(from, toExclusive)); } /** * Creates a BitSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. * * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static BitSet rangeBy(int from, int toExclusive, int step) { return BitSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } static BitSet rangeBy(char from, char toExclusive, int step) { return BitSet.withCharacters().ofAll(Iterator.rangeBy(from, toExclusive, step)); } static BitSet rangeBy(long from, long toExclusive, long step) { return BitSet.withLongs().ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a BitSet of int numbers starting from {@code from}, extending to {@code toInclusive}. * * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ static BitSet rangeClosed(int from, int toInclusive) { return BitSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } static BitSet rangeClosed(char from, char toInclusive) { return BitSet.withCharacters().ofAll(Iterator.rangeClosed(from, toInclusive)); } static BitSet rangeClosed(long from, long toInclusive) { return BitSet.withLongs().ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a BitSet of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. * * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static BitSet rangeClosedBy(int from, int toInclusive, int step) { return BitSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } static BitSet rangeClosedBy(char from, char toInclusive, int step) { return BitSet.withCharacters().ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } static BitSet rangeClosedBy(long from, long toInclusive, long step) { return BitSet.withLongs().ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @Override BitSet add(T element); @Override BitSet addAll(Iterable elements); @Override default SortedSet collect(PartialFunction partialFunction) { Objects.requireNonNull(partialFunction, "partialFunction is null"); return TreeSet.ofAll(Comparators.naturalComparator(), iterator().collect(partialFunction)); } @Override default BitSet diff(Set elements) { return removeAll(elements); } @Override default BitSet distinct() { return this; } @Override BitSet distinctBy(Comparator comparator); @Override BitSet distinctBy(Function keyExtractor); @Override BitSet drop(int n); @Override BitSet dropRight(int n); @Override default BitSet dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override BitSet dropWhile(Predicate predicate); @Override BitSet filter(Predicate predicate); @Override BitSet reject(Predicate predicate); @Override default SortedSet flatMap(Comparator comparator, Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(comparator, iterator().flatMap(mapper)); } @Override default SortedSet flatMap(Function> mapper) { return flatMap(Comparators.naturalComparator(), mapper); } @Override default U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return iterator().foldRight(zero, f); } @Override Map> groupBy(Function classifier); @Override default Iterator> grouped(int size) { return sliding(size, size); } @Override default boolean hasDefiniteSize() { return true; } @Override BitSet init(); @Override default Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } /** * An {@code BitSet}'s value is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } @Override default boolean isTraversableAgain() { return true; } /** * An {@code BitSet}'s value is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } @Override BitSet intersect(Set elements); @Override default T last() { return Collections.last(this); } @Override Tuple2, BitSet> partition(Predicate predicate); @Override default BitSet peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return this; } @Override default String stringPrefix() { return "BitSet"; } @Override default SortedSet map(Comparator comparator, Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(comparator, iterator().map(mapper)); } @Override default SortedSet map(Function mapper) { return map(Comparators.naturalComparator(), mapper); } @Override BitSet remove(T element); @Override BitSet removeAll(Iterable elements); @Override default BitSet replace(T currentElement, T newElement) { if (contains(currentElement)) { return remove(currentElement).add(newElement); } else { return this; } } @Override default BitSet replaceAll(T currentElement, T newElement) { // a set has only one occurrence return replace(currentElement, newElement); } @Override default BitSet retainAll(Iterable elements) { return Collections.retainAll(this, elements); } @Override BitSet scan(T zero, BiFunction operation); @Override default Set scanLeft(U zero, BiFunction operation) { return Collections.scanLeft(this, zero, operation, HashSet::ofAll); } @Override default Set scanRight(U zero, BiFunction operation) { return Collections.scanRight(this, zero, operation, HashSet::ofAll); } @Override Iterator> slideBy(Function classifier); @Override default Iterator> sliding(int size) { return sliding(size, 1); } @Override Iterator> sliding(int size, int step); @Override Tuple2, BitSet> span(Predicate predicate); @Override default BitSet tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty BitSet"); } else { return drop(1); } } @Override default Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override BitSet take(int n); @Override BitSet takeRight(int n); @Override default BitSet takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override BitSet takeWhile(Predicate predicate); @Override default java.util.SortedSet toJavaSet() { return toJavaSet(ignore -> new java.util.TreeSet<>(comparator())); } @Override default BitSet union(Set elements) { Objects.requireNonNull(elements, "elements is null"); return elements.isEmpty() ? this : addAll(elements); } @Override default Tuple2, TreeSet> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip(unzipper).map(i1 -> TreeSet.ofAll(Comparators.naturalComparator(), i1), i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2)); } @Override default Tuple3, TreeSet, TreeSet> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map( i1 -> TreeSet.ofAll(Comparators.naturalComparator(), i1), i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2), i3 -> TreeSet.ofAll(Comparators.naturalComparator(), i3)); } @Override default TreeSet> zip(Iterable that) { Objects.requireNonNull(that, "that is null"); final Comparator> tuple2Comparator = Tuple2.comparator(comparator(), Comparators.naturalComparator()); return TreeSet.ofAll(tuple2Comparator, iterator().zip(that)); } @Override default TreeSet zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWith(that, mapper)); } @Override default TreeSet> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); final Comparator> tuple2Comparator = Tuple2.comparator(comparator(), Comparators.naturalComparator()); return TreeSet.ofAll(tuple2Comparator, iterator().zipAll(that, thisElem, thatElem)); } @Override default TreeSet> zipWithIndex() { final Comparator component1Comparator = comparator(); final Comparator> tuple2Comparator = (t1, t2) -> component1Comparator.compare(t1._1, t2._1); return TreeSet.ofAll(tuple2Comparator, iterator().zipWithIndex()); } @Override default TreeSet zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWithIndex(mapper)); } } interface BitSetModule { int ADDRESS_BITS_PER_WORD = 6; int BITS_PER_WORD = 64; abstract class AbstractBitSet implements BitSet, Serializable { private static final long serialVersionUID = 1L; final Function1 fromInt; final Function1 toInt; AbstractBitSet(Function1 fromInt, Function1 toInt) { this.fromInt = fromInt; this.toInt = toInt; } abstract int getWordsNum(); abstract long[] copyExpand(int wordsNum); abstract long getWord(int index); BitSet createEmpty() { return new BitSet1<>(fromInt, toInt, 0L); } @SuppressWarnings("unchecked") BitSet createFromAll(Iterable values) { return values instanceof BitSet ? (BitSet) values : createEmpty().addAll(values); } BitSet fromBitMaskNoCopy(long[] elements) { switch (elements.length) { case 0: return createEmpty(); case 1: return new BitSet1<>(fromInt, toInt, elements[0]); case 2: return new BitSet2<>(fromInt, toInt, elements[0], elements[1]); default: return new BitSetN<>(fromInt, toInt, elements); } } private void setElement(long[] words, int element) { final int index = element >> ADDRESS_BITS_PER_WORD; words[index] |= (1L << element); } private void unsetElement(long[] words, int element) { final int index = element >> ADDRESS_BITS_PER_WORD; words[index] &= ~(1L << element); } long[] shrink(long[] elements) { int newlen = elements.length; while (newlen > 0 && elements[newlen - 1] == 0) { newlen--; } final long[] newelems = new long[newlen]; System.arraycopy(elements, 0, newelems, 0, newlen); return newelems; } BitSet addElement(int element) { final long[] copy = copyExpand(1 + (element >> ADDRESS_BITS_PER_WORD)); setElement(copy, element); return fromBitMaskNoCopy(copy); } @Override public BitSet distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return isEmpty() ? this : createFromAll(iterator().distinctBy(comparator)); } @Override public BitSet distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return isEmpty() ? this : createFromAll(iterator().distinctBy(keyExtractor)); } @Override public BitSet drop(int n) { if (n <= 0 || isEmpty()) { return this; } else if (n >= length()) { return createEmpty(); } else { return createFromAll(iterator().drop(n)); } } @Override public BitSet dropRight(int n) { if (n <= 0 || isEmpty()) { return this; } else if (n >= length()) { return createEmpty(); } else { return createFromAll(iterator().dropRight(n)); } } @Override public BitSet dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final BitSet bitSet = createFromAll(iterator().dropWhile(predicate)); return (bitSet.length() == length()) ? this : bitSet; } @Override public BitSet intersect(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { return this; } else if (elements.isEmpty()) { return createEmpty(); } else { final int size = size(); if (size <= elements.size()) { return retainAll(elements); } else { final BitSet results = createFromAll(elements).retainAll(this); return (size == results.size()) ? this : results; } } } /** * Returns this {@code BitSet} if it is nonempty, * otherwise {@code BitSet} created from iterable, using existing bitset properties. * * @param other An alternative {@code Traversable} * @return this {@code BitSet} if it is nonempty, * otherwise {@code BitSet} created from iterable, using existing bitset properties. */ @Override public BitSet orElse(Iterable other) { return isEmpty() ? createFromAll(other) : this; } /** * Returns this {@code BitSet} if it is nonempty, * otherwise {@code BitSet} created from result of evaluating supplier, using existing bitset properties. * * @param supplier An alternative {@code Traversable} * @return this {@code BitSet} if it is nonempty, * otherwise {@code BitSet} created from result of evaluating supplier, using existing bitset properties. */ @Override public BitSet orElse(Supplier> supplier) { return isEmpty() ? createFromAll(supplier.get()) : this; } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(this::createFromAll); } @Override public Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(this::createFromAll); } @Override public Tuple2, BitSet> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterator().span(predicate).map(this::createFromAll, this::createFromAll); } @Override public BitSet scan(T zero, BiFunction operation) { return Collections.scanLeft(this, zero, operation, this::createFromAll); } @Override public Tuple2, BitSet> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterator().partition(predicate).map(this::createFromAll, this::createFromAll); } @Override public BitSet filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final BitSet bitSet = createFromAll(iterator().filter(predicate)); return (bitSet.length() == length()) ? this : bitSet; } @Override public BitSet reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final BitSet bitSet = createFromAll(iterator().reject(predicate)); return (bitSet.length() == length()) ? this : bitSet; } @Override public Map> groupBy(Function classifier) { return Collections.groupBy(this, classifier, this::createFromAll); } @Override public Comparator comparator() { return Comparator.comparing(toInt); } @Override public BitSet takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final BitSet result = createFromAll(iterator().takeWhile(predicate)); return (result.length() == length()) ? this : result; } @Override @SuppressWarnings("unchecked") public BitSet addAll(Iterable elements) { final Stream source = Stream.ofAll(elements).map(toInt); if (source.isEmpty()) { return this; } else { final long[] copy = copyExpand(1 + (source.max().getOrElse(0) >> ADDRESS_BITS_PER_WORD)); source.forEach(element -> { if (element < 0) { throw new IllegalArgumentException("bitset element must be >= 0"); } setElement(copy, element); }); final BitSet bitSet = fromBitMaskNoCopy(copy); return (bitSet.length() == length()) ? this : bitSet; } } @Override public boolean contains(T t) { final int element = toInt.apply(t); if (element < 0) { throw new IllegalArgumentException("bitset element must be >= 0"); } final int index = element >> ADDRESS_BITS_PER_WORD; return index < getWordsNum() && (getWord(index) & (1L << element)) != 0; } @Override public BitSet init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty TreeSet"); } else { final long last = getWord(getWordsNum() - 1); final int element = BITS_PER_WORD * (getWordsNum() - 1) + BITS_PER_WORD - Long.numberOfLeadingZeros(last) - 1; return remove(fromInt.apply(element)); } } @Override public Iterator iterator() { return new BitSetIterator<>(this); } @Override public BitSet take(int n) { if (isEmpty() || n >= length()) { return this; } else if (n <= 0) { return createEmpty(); } else { return createFromAll(iterator().take(n)); } } @Override public BitSet takeRight(int n) { if (isEmpty() || n >= length()) { return this; } else if (n <= 0) { return createEmpty(); } else { return createFromAll(iterator().takeRight(n)); } } @Override public BitSet remove(T t) { if (contains(t)) { final int element = toInt.apply(t); final long[] copy = copyExpand(getWordsNum()); unsetElement(copy, element); return fromBitMaskNoCopy(shrink(copy)); } else { return this; } } @Override public BitSet removeAll(Iterable elements) { if (isEmpty()) { return this; } else { final Stream source = Stream.ofAll(elements).map(toInt); if (source.isEmpty()) { return this; } else { final long[] copy = copyExpand(getWordsNum()); source.forEach(element -> unsetElement(copy, element)); return fromBitMaskNoCopy(shrink(copy)); } } } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } } class BitSetIterator extends AbstractIterator { private final AbstractBitSet bitSet; private long element; private int index; BitSetIterator(AbstractBitSet bitSet) { this.bitSet = bitSet; this.element = bitSet.getWord(0); this.index = 0; } @Override protected T getNext() { final int pos = Long.numberOfTrailingZeros(element); element &= ~(1L << pos); return bitSet.fromInt.apply(pos + (index << ADDRESS_BITS_PER_WORD)); } @Override public boolean hasNext() { if (element == 0) { while (element == 0 && index < bitSet.getWordsNum() - 1) { element = bitSet.getWord(++index); } return element != 0; } else { return true; } } } class BitSet1 extends AbstractBitSet { private static final long serialVersionUID = 1L; private final long elements; private final int len; BitSet1(Function1 fromInt, Function1 toInt, long elements) { super(fromInt, toInt); this.elements = elements; this.len = Long.bitCount(elements); } @Override int getWordsNum() { return 1; } @Override long[] copyExpand(int wordsNum) { if (wordsNum < 1) { wordsNum = 1; } final long[] arr = new long[wordsNum]; arr[0] = elements; return arr; } @Override long getWord(int index) { return elements; } @Override public T head() { if (elements == 0) { throw new NoSuchElementException("head of empty BitSet"); } else { return fromInt.apply(Long.numberOfTrailingZeros(elements)); } } @Override public int length() { return len; } @Override public BitSet add(T t) { final int element = toInt.apply(t); if (element < 0) { throw new IllegalArgumentException("bitset element must be >= 0"); } if (element < BITS_PER_WORD) { final long mask = 1L << element; if ((elements & mask) != 0) { return this; } else { return new BitSet1<>(fromInt, toInt, elements | mask); } } else { return addElement(element); } } } class BitSet2 extends AbstractBitSet { private static final long serialVersionUID = 1L; private final long elements1, elements2; private final int len; BitSet2(Function1 fromInt, Function1 toInt, long elements1, long elements2) { super(fromInt, toInt); this.elements1 = elements1; this.elements2 = elements2; this.len = Long.bitCount(elements1) + Long.bitCount(elements2); } @Override int getWordsNum() { return 2; } @Override long[] copyExpand(int wordsNum) { if (wordsNum < 2) { wordsNum = 2; } final long[] arr = new long[wordsNum]; arr[0] = elements1; arr[1] = elements2; return arr; } @Override long getWord(int index) { if (index == 0) { return elements1; } else { return elements2; } } @Override public T head() { if (elements1 == 0) { return fromInt.apply(BITS_PER_WORD + Long.numberOfTrailingZeros(elements2)); } else { return fromInt.apply(Long.numberOfTrailingZeros(elements1)); } } @Override public int length() { return len; } @Override public BitSet add(T t) { final int element = toInt.apply(t); if (element < 0) { throw new IllegalArgumentException("bitset element must be >= 0"); } final long mask = 1L << element; if (element < BITS_PER_WORD) { if ((elements1 & mask) != 0) { return this; } else { return new BitSet2<>(fromInt, toInt, elements1 | mask, elements2); } } else if (element < 2 * BITS_PER_WORD) { if ((elements2 & mask) != 0) { return this; } else { return new BitSet2<>(fromInt, toInt, elements1, elements2 | mask); } } else { return addElement(element); } } } class BitSetN extends AbstractBitSet { private static final long serialVersionUID = 1L; private final long[] elements; private final int len; BitSetN(Function1 fromInt, Function1 toInt, long[] elements) { super(fromInt, toInt); this.elements = elements; this.len = calcLength(elements); } private static int calcLength(long[] elements) { int len = 0; for (long element : elements) { len += Long.bitCount(element); } return len; } @Override int getWordsNum() { return elements.length; } @Override long[] copyExpand(int wordsNum) { if (wordsNum < elements.length) { wordsNum = elements.length; } final long[] arr = new long[wordsNum]; System.arraycopy(elements, 0, arr, 0, elements.length); return arr; } @Override long getWord(int index) { return elements[index]; } @Override public T head() { int offset = 0; int element = 0; for (int i = 0; i < getWordsNum(); i++) { if (elements[i] == 0) { offset += BITS_PER_WORD; } else { element = offset + Long.numberOfTrailingZeros(elements[i]); break; } } return fromInt.apply(element); } @Override public int length() { return len; } @Override public BitSet add(T t) { if (contains(t)) { return this; } else { return addElement(toInt.apply(t)); } } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/CharSeq.java000066400000000000000000003637421342074374400241200ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.collection.CharSeqModule.Combinations; import io.vavr.control.Option; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.*; import java.util.function.*; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.stream.Collector; import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE; import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE; /** * The CharSeq (read: character sequence) collection essentially is a rich String wrapper having all operations * we know from the functional Vavr collections. *

* Note:Because CharSeq represents a sequence of primitive characters (i.e. a String), * it breaks the Liskov Substitution Principle in the way, that the CharSeq cannot contain {@code null} elements. * In future version of Java, CharSeq should extend IndexedSeq<char> instead. * * @author Ruslan Sennov, Daniel Dietrich */ public final class CharSeq implements CharSequence, IndexedSeq, Serializable { private static final long serialVersionUID = 1L; private static final CharSeq EMPTY = new CharSeq(""); private final String back; private CharSeq(String javaString) { this.back = javaString; } public static CharSeq empty() { return EMPTY; } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link CharSeq}. * * @return A {@code CharSeq} Collector. */ public static Collector, CharSeq> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, Character> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, CharSeq> finisher = CharSeq::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Creates a String of {@code CharSequence}. * * @param sequence {@code CharSequence} instance. * @return A new {@link io.vavr.collection.CharSeq} */ // DEV-NOTE: Needs to be 'of' instead of 'ofAll' because 'ofAll(CharSeq)' is ambiguous. public static CharSeq of(CharSequence sequence) { Objects.requireNonNull(sequence, "sequence is null"); if (sequence instanceof CharSeq) { return (CharSeq) sequence; } else { return sequence.length() == 0 ? empty() : new CharSeq(sequence.toString()); } } /** * Returns a singleton {@code CharSeq}, i.e. a {@code CharSeq} of one character. * * @param character A character. * @return A new {@code CharSeq} instance containing the given element */ public static CharSeq of(char character) { return new CharSeq(new String(new char[] { character })); } /** * Creates a String of the given characters. * * @param characters Zero or more characters. * @return A string containing the given characters in the same order. * @throws NullPointerException if {@code elements} is null */ public static CharSeq of(char... characters) { Objects.requireNonNull(characters, "characters is null"); if (characters.length == 0) { return empty(); } else { final char[] chrs = new char[characters.length]; System.arraycopy(characters, 0, chrs, 0, characters.length); return new CharSeq(new String(chrs)); } } /** * Creates a String of the given elements. *

* The resulting string has the same iteration order as the given iterable of elements * if the iteration order of the elements is stable. * * @param elements An Iterable of elements. * @return A string containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null or {@code elements} contains null */ public static CharSeq ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (Collections.isEmpty(elements)){ return EMPTY; } if (elements instanceof CharSeq) { return (CharSeq) elements; } final StringBuilder sb = new StringBuilder(); for (char character : elements) { sb.append(character); } return of(sb); } /** * Returns a CharSeq containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param n The number of elements in the CharSeq * @param f The Function computing element values * @return A CharSeq consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static CharSeq tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); final StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { sb.append(f.apply(i).charValue()); } return of(sb); } /** * Returns a CharSeq containing {@code n} values supplied by a given Supplier {@code s}. * * @param n The number of elements in the CharSeq * @param s The Supplier computing element values * @return A CharSeq of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static CharSeq fill(int n, Supplier s) { return tabulate(n, anything -> s.get()); } /** * Creates a CharSeq starting from character {@code from}, extending to character {@code toExclusive - 1}. *

* Examples: *

     * 
     * CharSeq.range('a', 'c')  // = "ab"
     * CharSeq.range('c', 'a')  // = ""
     * 
     * 
* * @param from the first character * @param toExclusive the successor of the last character * @return a range of characters as specified or the empty range if {@code from >= toExclusive} */ public static CharSeq range(char from, char toExclusive) { return new CharSeq(io.vavr.collection.Iterator.range(from, toExclusive).mkString()); } public static CharSeq rangeBy(char from, char toExclusive, int step) { return new CharSeq(io.vavr.collection.Iterator.rangeBy(from, toExclusive, step).mkString()); } /** * Creates a CharSeq starting from character {@code from}, extending to character {@code toInclusive}. *

* Examples: *

     * 
     * CharSeq.rangeClosed('a', 'c')  // = "abc"
     * CharSeq.rangeClosed('c', 'a')  // = ""
     * 
     * 
* * @param from the first character * @param toInclusive the last character * @return a range of characters as specified or the empty range if {@code from > toInclusive} */ public static CharSeq rangeClosed(char from, char toInclusive) { return new CharSeq(io.vavr.collection.Iterator.rangeClosed(from, toInclusive).mkString()); } /** * Creates a CharSeq starting from character {@code from}, extending to character {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * CharSeq.rangeClosedBy('a', 'c', 1)  // = ('a', 'b', 'c')
     * CharSeq.rangeClosedBy('a', 'd', 2)  // = ('a', 'c')
     * CharSeq.rangeClosedBy('d', 'a', -2) // = ('d', 'b')
     * CharSeq.rangeClosedBy('d', 'a', 2)  // = ()
     * 
     * 
* * @param from the first character * @param toInclusive the last character * @param step the step * @return a range of characters as specified or the empty range if {@code step * (from - toInclusive) > 0}. * @throws IllegalArgumentException if {@code step} is zero */ public static CharSeq rangeClosedBy(char from, char toInclusive, int step) { return new CharSeq(io.vavr.collection.Iterator.rangeClosedBy(from, toInclusive, step).mkString()); } /** * Creates a CharSeq from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the CharSeq, otherwise {@code Some} {@code Tuple} * of the element for the next call and the value to add to the * resulting CharSeq. *

* Example: *

     * 
     * CharSeq.unfoldRight('j', x -> x == 'a'
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(new Character(x), (char)(x-1))));
     * // CharSeq.of("jihgfedcb"))
     * 
     * 
* * @param type of seeds * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a CharSeq with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static CharSeq unfoldRight(T seed, Function>> f) { return CharSeq.ofAll(io.vavr.collection.Iterator.unfoldRight(seed, f)); } /** * Creates a CharSeq from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the CharSeq, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting CharSeq and * the element for the next call. *

* Example: *

     * 
     * CharSeq.unfoldLeft('j', x -> x == 'a'
     *             ? Option.none()
     *             : Option.of(new Tuple2<>((char)(x-1), new Character(x))));
     * // CharSeq.of("bcdefghij"))
     * 
     * 
* * @param type of seeds * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a CharSeq with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static CharSeq unfoldLeft(T seed, Function>> f) { return CharSeq.ofAll(io.vavr.collection.Iterator.unfoldLeft(seed, f)); } /** * Creates a CharSeq from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the CharSeq, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting CharSeq and * the element for the next call. *

* Example: *

     * 
     * CharSeq.unfold('j', x -> x == 'a'
     *                ? Option.none()
     *                : Option.of(new Tuple2<>((char)(x-1), new Character(x))));
     * // CharSeq.of("bcdefghij"))
     * 
     * 
* * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a CharSeq with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static CharSeq unfold(Character seed, Function>> f) { return CharSeq.ofAll(io.vavr.collection.Iterator.unfold(seed, f)); } private Tuple2 splitByBuilder(StringBuilder sb) { if (sb.length() == 0) { return Tuple.of(EMPTY, this); } else if (sb.length() == length()) { return Tuple.of(this, EMPTY); } else { return Tuple.of(of(sb), of(back.substring(sb.length()))); } } /** * Repeats a character {@code times} times. * * @param character A character * @param times Repetition count * @return A CharSeq representing {@code character * times} */ public static CharSeq repeat(char character, int times) { final int length = Math.max(times, 0); final char[] characters = new char[length]; java.util.Arrays.fill(characters, character); return new CharSeq(String.valueOf(characters)); } /** * Repeats this CharSeq {@code times} times. *

* Example: {@code CharSeq.of("ja").repeat(13) = "jajajajajajajajajajajajaja"} * * @param times Repetition count * @return A CharSeq representing {@code this * times} */ public CharSeq repeat(int times) { if (times <= 0 || isEmpty()) { return empty(); } else if (times == 1) { return this; } else { final int finalLength = length() * times; final char[] result = new char[finalLength]; back.getChars(0, length(), result, 0); int i = length(); for (; i <= (finalLength >>> 1); i <<= 1) { System.arraycopy(result, 0, result, i, i); } System.arraycopy(result, 0, result, i, finalLength - i); return of(new String(result)); } } // // // IndexedSeq // // @Override public CharSeq append(Character element) { // DEV-NOTE: we need to unbox, otherwise "null" will be appended to back final char c = element; return of(back + c); } @Override public CharSeq appendAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (Collections.isEmpty(elements)) { return this; } final StringBuilder sb = new StringBuilder(back); for (char element : elements) { sb.append(element); } return of(sb); } @GwtIncompatible @Override public java.util.List asJava() { return JavaConverters.asJava(this, IMMUTABLE); } @GwtIncompatible @Override public CharSeq asJava(Consumer> action) { return Collections.asJava(this, action, IMMUTABLE); } @GwtIncompatible @Override public java.util.List asJavaMutable() { return JavaConverters.asJava(this, MUTABLE); } @GwtIncompatible @Override public CharSeq asJavaMutable(Consumer> action) { return Collections.asJava(this, action, MUTABLE); } @Override public IndexedSeq collect(PartialFunction partialFunction) { return Vector.ofAll(iterator(). collect(partialFunction)); } @Override public IndexedSeq combinations() { return Vector.rangeClosed(0, length()).map(this::combinations).flatMap(Function.identity()); } @Override public IndexedSeq combinations(int k) { return Combinations.apply(this, Math.max(k, 0)); } @Override public io.vavr.collection.Iterator crossProduct(int power) { return io.vavr.collection.Collections.crossProduct(CharSeq.empty(), this, power); } @Override public CharSeq distinct() { return distinctBy(Function.identity()); } @Override public CharSeq distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final java.util.Set seen = new java.util.TreeSet<>(comparator); return filter(seen::add); } @Override public CharSeq distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); final java.util.Set seen = new java.util.HashSet<>(); return filter(t -> seen.add(keyExtractor.apply(t))); } @Override public CharSeq drop(int n) { if (n <= 0) { return this; } else if (n >= length()) { return EMPTY; } else { return of(back.substring(n)); } } @Override public CharSeq dropUntil(Predicate predicate) { return io.vavr.collection.Collections.dropUntil(this, predicate); } @Override public CharSeq dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropUntil(predicate.negate()); } @Override public CharSeq dropRight(int n) { if (n <= 0) { return this; } else if (n >= length()) { return EMPTY; } else { return of(back.substring(0, length() - n)); } } @Override public CharSeq dropRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropRightUntil(predicate.negate()); } @Override public CharSeq dropRightUntil(Predicate predicate) { return io.vavr.collection.Collections.dropRightUntil(this, predicate); } @Override public CharSeq filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final StringBuilder sb = new StringBuilder(); for (int i = 0; i < back.length(); i++) { final char ch = get(i); if (predicate.test(ch)) { sb.append(ch); } } if (sb.length() == 0) { return EMPTY; } else if (sb.length() == length()) { return this; } else { return of(sb); } } @Override public CharSeq reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Collections.reject(this, predicate); } @Override public IndexedSeq flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return Vector.empty(); } else { IndexedSeq result = Vector.empty(); for (int i = 0; i < length(); i++) { for (U u : mapper.apply(get(i))) { result = result.append(u); } } return result; } } public CharSeq flatMapChars(CharFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return this; } else { final StringBuilder builder = new StringBuilder(); for (int i = 0; i < back.length(); i++) { builder.append(mapper.apply(back.charAt(i))); } return of(builder); } } @Override public Map groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(this, classifier, CharSeq::ofAll); } @Override public io.vavr.collection.Iterator grouped(int size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public CharSeq init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty string"); } else { return of(back.substring(0, length() - 1)); } } @Override public Option initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override public CharSeq insert(int index, Character element) { if (index < 0) { throw new IndexOutOfBoundsException("insert(" + index + ", e)"); } if (index > length()) { throw new IndexOutOfBoundsException("insert(" + index + ", e) on String of length " + length()); } final char c = element; return of(new StringBuilder(back).insert(index, c).toString()); } @Override public CharSeq insertAll(int index, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (index < 0) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements)"); } if (index > length()) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements) on String of length " + length()); } final StringBuilder sb = new StringBuilder(back.substring(0, index)); for (char element : elements) { sb.append(element); } sb.append(back.substring(index)); return of(sb); } @Override public io.vavr.collection.Iterator iterator() { return io.vavr.collection.Iterator.ofAll(toCharArray()); } @Override public CharSeq intersperse(Character element) { final char c = element; // intentionally throw when element is null if (isEmpty()) { return EMPTY; } else { final StringBuilder sb = new StringBuilder().append(head()); for (int i = 1; i < length(); i++) { sb.append(c).append(get(i)); } return of(sb); } } @Override public IndexedSeq map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); IndexedSeq result = Vector.empty(); for (int i = 0; i < length(); i++) { result = result.append(mapper.apply(get(i))); } return result; } @Override public String mkString() { return back; } @Override public CharSeq padTo(int length, Character element) { final int actualLength = back.length(); if (length <= actualLength) { return this; } else { return new CharSeq(back + padding(element, length - actualLength)); } } @Override public CharSeq leftPadTo(int length, Character element) { final int actualLength = back.length(); if (length <= actualLength) { return this; } else { return of(padding(element, length - actualLength).append(back)); } } @Override public CharSeq orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override public CharSeq orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } private static StringBuilder padding(char element, int limit) { final StringBuilder padding = new StringBuilder(); for (int i = 0; i < limit; i++) { padding.append(element); } return padding; } @Override public CharSeq patch(int from, Iterable that, int replaced) { from = from < 0 ? 0 : from > length() ? length() : from; replaced = replaced < 0 ? 0 : replaced; final StringBuilder sb = new StringBuilder(back.substring(0, from)); for (char character : that) { sb.append(character); } from += replaced; if (from < length()) { sb.append(back.substring(from)); } return sb.length() == 0 ? EMPTY : of(sb); } public CharSeq mapChars(CharUnaryOperator mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return this; } else { final char[] chars = back.toCharArray(); for (int i = 0; i < chars.length; i++) { chars[i] = mapper.apply(chars[i]); } return CharSeq.of(chars); } } @Override public Tuple2 partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Tuple.of(EMPTY, EMPTY); } final StringBuilder left = new StringBuilder(); final StringBuilder right = new StringBuilder(); for (int i = 0; i < length(); i++) { final Character t = get(i); (predicate.test(t) ? left : right).append(t); } if (left.length() == 0) { return Tuple.of(EMPTY, of(right.toString())); } else if (right.length() == 0) { return Tuple.of(of(left.toString()), EMPTY); } else { return Tuple.of(of(left.toString()), of(right.toString())); } } @Override public CharSeq peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(get(0)); } return this; } @Override public IndexedSeq permutations() { if (isEmpty()) { return Vector.empty(); } else { if (length() == 1) { return Vector.of(this); } else { IndexedSeq result = Vector.empty(); for (Character t : distinct()) { for (CharSeq ts : remove(t).permutations()) { result = result.append(CharSeq.of(t).appendAll(ts)); } } return result; } } } @Override public CharSeq prepend(Character element) { final char c = element; return of(c + back); } @Override public CharSeq prependAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (Collections.isEmpty(elements)) { return this; } else if (isEmpty()) { return ofAll(elements); } else { final StringBuilder sb = new StringBuilder(); for (char element : elements) { sb.append(element); } sb.append(back); return CharSeq.of(sb); } } @Override public CharSeq remove(Character element) { if (element == null) { return this; } final StringBuilder sb = new StringBuilder(); boolean found = false; for (int i = 0; i < length(); i++) { final char c = get(i); if (!found && c == element) { found = true; } else { sb.append(c); } } return sb.length() == 0 ? EMPTY : sb.length() == length() ? this : of(sb); } @Override public CharSeq removeFirst(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final StringBuilder sb = new StringBuilder(); boolean found = false; for (int i = 0; i < back.length(); i++) { final char ch = get(i); if (predicate.test(ch)) { if (found) { sb.append(ch); } found = true; } else { sb.append(ch); } } return found ? (sb.length() == 0 ? EMPTY : of(sb.toString())) : this; } @Override public CharSeq removeLast(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = length() - 1; i >= 0; i--) { if (predicate.test(get(i))) { return removeAt(i); } } return this; } @Override public CharSeq removeAt(int index) { final String removed = back.substring(0, index) + back.substring(index + 1); return removed.isEmpty() ? EMPTY : of(removed); } @Override public CharSeq removeAll(Character element) { if (element == null) { return this; } return io.vavr.collection.Collections.removeAll(this, element); } @Override public CharSeq removeAll(Iterable elements) { return io.vavr.collection.Collections.removeAll(this, elements); } @Override @Deprecated public CharSeq removeAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override public CharSeq replace(Character currentElement, Character newElement) { if (currentElement == null) { return this; } final char currentChar = currentElement; final char newChar = newElement; final StringBuilder sb = new StringBuilder(); boolean found = false; for (int i = 0; i < length(); i++) { final char c = get(i); if (!found && c == currentChar) { sb.append(newChar); found = true; } else { sb.append(c); } } return found ? of(sb) : this; } @Override public CharSeq replaceAll(Character currentElement, Character newElement) { if (currentElement == null) { return this; } final char currentChar = currentElement; final char newChar = newElement; final StringBuilder sb = new StringBuilder(); boolean found = false; for (int i = 0; i < length(); i++) { final char c = get(i); if (c == currentChar) { sb.append(newChar); found = true; } else { sb.append(c); } } return found ? of(sb) : this; } @Override public CharSeq retainAll(Iterable elements) { return io.vavr.collection.Collections.retainAll(this, elements); } @Override public CharSeq reverse() { return of(new StringBuilder(back).reverse().toString()); } @Override public CharSeq rotateLeft(int n) { return Collections.rotateLeft(this, n); } @Override public CharSeq rotateRight(int n) { return Collections.rotateRight(this, n); } @Override public CharSeq scan(Character zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, io.vavr.collection.Iterator::toCharSeq); } @Override public IndexedSeq scanLeft(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, io.vavr.collection.Iterator::toVector); } @Override public IndexedSeq scanRight(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, io.vavr.collection.Iterator::toVector); } @Override public CharSeq shuffle() { return io.vavr.collection.Collections.shuffle(this, CharSeq::ofAll); } @Override public CharSeq slice(int beginIndex, int endIndex) { final int from = beginIndex < 0 ? 0 : beginIndex; final int to = endIndex > length() ? length() : endIndex; if (from >= to) { return EMPTY; } if (from <= 0 && to >= length()) { return this; } return CharSeq.of(back.substring(from, to)); } @Override public io.vavr.collection.Iterator slideBy(Function classifier) { return iterator().slideBy(classifier).map(CharSeq::ofAll); } @Override public io.vavr.collection.Iterator sliding(int size) { return sliding(size, 1); } @Override public io.vavr.collection.Iterator sliding(int size, int step) { return iterator().sliding(size, step).map(CharSeq::ofAll); } @Override public CharSeq sorted() { return isEmpty() ? this : toJavaStream().sorted().collect(CharSeq.collector()); } @Override public CharSeq sorted(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return isEmpty() ? this : toJavaStream().sorted(comparator).collect(CharSeq.collector()); } @Override public > CharSeq sortBy(Function mapper) { return sortBy(U::compareTo, mapper); } @Override public CharSeq sortBy(Comparator comparator, Function mapper) { return Collections.sortBy(this, comparator, mapper, collector()); } @Override public Tuple2 span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final StringBuilder sb = new StringBuilder(); for (int i = 0; i < length(); i++) { final char c = get(i); if (predicate.test(c)) { sb.append(c); } else { break; } } return splitByBuilder(sb); } @Override public CharSeq subSequence(int beginIndex) { if (beginIndex < 0 || beginIndex > length()) { throw new IndexOutOfBoundsException("begin index " + beginIndex + " < 0"); } if (beginIndex == 0) { return this; } else if (beginIndex == length()) { return EMPTY; } else { return CharSeq.of(back.substring(beginIndex)); } } @Override public CharSeq tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty string"); } else { return CharSeq.of(back.substring(1)); } } @Override public Option tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override public CharSeq take(int n) { if (n <= 0) { return EMPTY; } else if (n >= length()) { return this; } else { return CharSeq.of(back.substring(0, n)); } } @Override public CharSeq takeUntil(Predicate predicate) { return io.vavr.collection.Collections.takeUntil(this, predicate); } @Override public CharSeq takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeUntil(predicate.negate()); } @Override public CharSeq takeRight(int n) { if (n <= 0) { return EMPTY; } else if (n >= length()) { return this; } else { return CharSeq.of(back.substring(length() - n)); } } @Override public CharSeq takeRightUntil(Predicate predicate) { return io.vavr.collection.Collections.takeRightUntil(this, predicate); } @Override public CharSeq takeRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeRightUntil(predicate.negate()); } /** * Transforms this {@code CharSeq}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public Tuple2, IndexedSeq> unzip(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); IndexedSeq xs = Vector.empty(); IndexedSeq ys = Vector.empty(); for (int i = 0; i < length(); i++) { final Tuple2 t = unzipper.apply(get(i)); xs = xs.append(t._1); ys = ys.append(t._2); } return Tuple.of(xs, ys); } @Override public Tuple3, IndexedSeq, IndexedSeq> unzip3(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); IndexedSeq xs = Vector.empty(); IndexedSeq ys = Vector.empty(); IndexedSeq zs = Vector.empty(); for (int i = 0; i < length(); i++) { final Tuple3 t = unzipper.apply(get(i)); xs = xs.append(t._1); ys = ys.append(t._2); zs = zs.append(t._3); } return Tuple.of(xs, ys, zs); } @Override public CharSeq update(int index, Character element) { if ((index < 0) || (index >= length())) { throw new IndexOutOfBoundsException("update(" + index + ")"); } else { char c = element; return of(back.substring(0, index) + c + back.substring(index + 1)); } } @Override public CharSeq update(int index, Function updater) { Objects.requireNonNull(updater, "updater is null"); final char c = updater.apply(get(index)); return update(index, c); } @Override public IndexedSeq> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public IndexedSeq zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); IndexedSeq result = Vector.empty(); final io.vavr.collection.Iterator list1 = iterator(); final java.util.Iterator list2 = that.iterator(); while (list1.hasNext() && list2.hasNext()) { result = result.append(mapper.apply(list1.next(), list2.next())); } return result; } @Override public IndexedSeq> zipAll(Iterable that, Character thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); IndexedSeq> result = Vector.empty(); final io.vavr.collection.Iterator list1 = iterator(); final java.util.Iterator list2 = that.iterator(); while (list1.hasNext() || list2.hasNext()) { final Character elem1 = list1.hasNext() ? list1.next() : thisElem; final U elem2 = list2.hasNext() ? list2.next() : thatElem; result = result.append(Tuple.of(elem1, elem2)); } return result; } @Override public IndexedSeq> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public IndexedSeq zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); IndexedSeq result = Vector.empty(); for (int i = 0; i < length(); i++) { result = result.append(mapper.apply(get(i), i)); } return result; } @Override public Character get(int index) { return back.charAt(index); } @Override public int indexOf(Character element, int from) { return back.indexOf(element, from); } @Override public int lastIndexOf(Character element, int end) { return back.lastIndexOf(element, end); } @Override public Tuple2 splitAt(int n) { if (n <= 0) { return Tuple.of(EMPTY, this); } else if (n >= length()) { return Tuple.of(this, EMPTY); } else { return Tuple.of(of(back.substring(0, n)), of(back.substring(n))); } } @Override public Tuple2 splitAt(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Tuple.of(EMPTY, EMPTY); } final StringBuilder left = new StringBuilder(); for (int i = 0; i < length(); i++) { final Character t = get(i); if (!predicate.test(t)) { left.append(t); } else { break; } } return splitByBuilder(left); } @Override public Tuple2 splitAtInclusive(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Tuple.of(EMPTY, EMPTY); } final StringBuilder left = new StringBuilder(); for (int i = 0; i < length(); i++) { final Character t = get(i); left.append(t); if (predicate.test(t)) { break; } } return splitByBuilder(left); } @Override public boolean startsWith(Iterable that, int offset) { return startsWith(CharSeq.ofAll(that), offset); } @Override public Character head() { if (isEmpty()) { throw new NoSuchElementException("head of empty string"); } else { return get(0); } } /** * A {@code CharSeq} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return back.isEmpty(); } /** * A {@code CharSeq} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } private Object readResolve() { return isEmpty() ? EMPTY : this; } @Override public boolean equals(Object o) { return io.vavr.collection.Collections.equals(this, o); } @Override public int hashCode() { return io.vavr.collection.Collections.hashOrdered(this); } // // // CharSequence // // /** * Returns the {@code char} value at the * specified index. An index ranges from {@code 0} to * {@code length() - 1}. The first {@code char} value of the sequence * is at index {@code 0}, the next at index {@code 1}, * and so on, as for array indexing. *

* If the {@code char} value specified by the index is a * surrogate, the surrogate * value is returned. * * @param index the index of the {@code char} value. * @return the {@code char} value at the specified index of this string. * The first {@code char} value is at index {@code 0}. * @throws IndexOutOfBoundsException if the {@code index} * argument is negative or not less than the length of this * string. */ @Override public char charAt(int index) { return get(index); } /** * Returns the length of this string. * The length is equal to the number of Unicode * code units in the string. * * @return the length of the sequence of characters represented by this * object. */ @Override public int length() { return back.length(); } // // // String // // /** * Returns the character (Unicode code point) at the specified * index. The index refers to {@code char} values * (Unicode code units) and ranges from {@code 0} to * {@link #length()}{@code - 1}. *

* If the {@code char} value specified at the given index * is in the high-surrogate range, the following index is less * than the length of this {@code CharSeq}, and the * {@code char} value at the following index is in the * low-surrogate range, then the supplementary code point * corresponding to this surrogate pair is returned. Otherwise, * the {@code char} value at the given index is returned. * * @param index the index to the {@code char} values * @return the code point value of the character at the * {@code index} * @throws IndexOutOfBoundsException if the {@code index} * argument is negative or not less than the length of this * string. */ public int codePointAt(int index) { return back.codePointAt(index); } /** * Returns the character (Unicode code point) before the specified * index. The index refers to {@code char} values * (Unicode code units) and ranges from {@code 1} to {@link * CharSequence#length() length}. *

* If the {@code char} value at {@code (index - 1)} * is in the low-surrogate range, {@code (index - 2)} is not * negative, and the {@code char} value at {@code (index - * 2)} is in the high-surrogate range, then the * supplementary code point value of the surrogate pair is * returned. If the {@code char} value at {@code index - * 1} is an unpaired low-surrogate or a high-surrogate, the * surrogate value is returned. * * @param index the index following the code point that should be returned * @return the Unicode code point value before the given index. * @throws IndexOutOfBoundsException if the {@code index} * argument is less than 1 or greater than the length * of this string. */ public int codePointBefore(int index) { return back.codePointBefore(index); } /** * Returns the number of Unicode code points in the specified text * range of this {@code CharSeq}. The text range begins at the * specified {@code beginIndex} and extends to the * {@code char} at index {@code endIndex - 1}. Thus the * length (in {@code char}s) of the text range is * {@code endIndex-beginIndex}. Unpaired surrogates within * the text range count as one code point each. * * @param beginIndex the index to the first {@code char} of * the text range. * @param endIndex the index after the last {@code char} of * the text range. * @return the number of Unicode code points in the specified text * range * @throws IndexOutOfBoundsException if the * {@code beginIndex} is negative, or {@code endIndex} * is larger than the length of this {@code CharSeq}, or * {@code beginIndex} is larger than {@code endIndex}. */ public int codePointCount(int beginIndex, int endIndex) { return back.codePointCount(beginIndex, endIndex); } /** * Returns the index within this {@code CharSeq} that is * offset from the given {@code index} by * {@code codePointOffset} code points. Unpaired surrogates * within the text range given by {@code index} and * {@code codePointOffset} count as one code point each. * * @param index the index to be offset * @param codePointOffset the offset in code points * @return the index within this {@code CharSeq} * @throws IndexOutOfBoundsException if {@code index} * is negative or larger then the length of this * {@code CharSeq}, or if {@code codePointOffset} is positive * and the substring starting with {@code index} has fewer * than {@code codePointOffset} code points, * or if {@code codePointOffset} is negative and the substring * before {@code index} has fewer than the absolute value * of {@code codePointOffset} code points. */ public int offsetByCodePoints(int index, int codePointOffset) { return back.offsetByCodePoints(index, codePointOffset); } /** * Copies characters from this string into the destination character * array. *

* The first character to be copied is at index {@code srcBegin}; * the last character to be copied is at index {@code srcEnd-1} * (thus the total number of characters to be copied is * {@code srcEnd-srcBegin}). The characters are copied into the * subarray of {@code dst} starting at index {@code dstBegin} * and ending at index: *

     *     dstbegin + (srcEnd-srcBegin) - 1
     * 
* * @param srcBegin index of the first character in the string * to copy. * @param srcEnd index after the last character in the string * to copy. * @param dst the destination array. * @param dstBegin the start offset in the destination array. * @throws IndexOutOfBoundsException If any of the following * is true: *
  • {@code srcBegin} is negative. *
  • {@code srcBegin} is greater than {@code srcEnd} *
  • {@code srcEnd} is greater than the length of this * string *
  • {@code dstBegin} is negative *
  • {@code dstBegin+(srcEnd-srcBegin)} is larger than * {@code dst.length}
*/ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { back.getChars(srcBegin, srcEnd, dst, dstBegin); } /** * Encodes this {@code CharSeq} into a sequence of bytes using the named * charset, storing the result into a new byte array. *

* The behavior of this method when this string cannot be encoded in * the given charset is unspecified. The {@link * java.nio.charset.CharsetEncoder} class should be used when more control * over the encoding process is required. * * @param charsetName The name of a supported {@linkplain java.nio.charset.Charset * charset} * @return The resultant byte array * @throws UnsupportedEncodingException If the named charset is not supported */ public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { return back.getBytes(charsetName); } /** * Encodes this {@code CharSeq} into a sequence of bytes using the given * {@linkplain java.nio.charset.Charset charset}, storing the result into a * new byte array. *

* This method always replaces malformed-input and unmappable-character * sequences with this charset's default replacement byte array. The * {@link java.nio.charset.CharsetEncoder} class should be used when more * control over the encoding process is required. * * @param charset The {@linkplain java.nio.charset.Charset} to be used to encode * the {@code CharSeq} * @return The resultant byte array */ public byte[] getBytes(Charset charset) { return back.getBytes(charset); } /** * Encodes this {@code CharSeq} into a sequence of bytes using the * platform's default charset, storing the result into a new byte array. *

* The behavior of this method when this string cannot be encoded in * the default charset is unspecified. The {@link * java.nio.charset.CharsetEncoder} class should be used when more control * over the encoding process is required. * * @return The resultant byte array */ public byte[] getBytes() { return back.getBytes(); } /** * Compares this string to the specified {@code StringBuffer}. The result * is {@code true} if and only if this {@code CharSeq} represents the same * sequence of characters as the specified {@code StringBuffer}. This method * synchronizes on the {@code StringBuffer}. * * @param sb The {@code StringBuffer} to compare this {@code CharSeq} against * @return {@code true} if this {@code CharSeq} represents the same * sequence of characters as the specified {@code StringBuffer}, * {@code false} otherwise */ public boolean contentEquals(StringBuffer sb) { return back.contentEquals(sb); } /** * Compares this string to the specified {@code CharSequence}. The * result is {@code true} if and only if this {@code CharSeq} represents the * same sequence of char values as the specified sequence. Note that if the * {@code CharSequence} is a {@code StringBuffer} then the method * synchronizes on it. * * @param cs The sequence to compare this {@code CharSeq} against * @return {@code true} if this {@code CharSeq} represents the same * sequence of char values as the specified sequence, {@code * false} otherwise */ public boolean contentEquals(CharSequence cs) { return back.contentEquals(cs); } /** * Compares this {@code CharSeq} to another {@code CharSeq}, ignoring case * considerations. Two strings are considered equal ignoring case if they * are of the same length and corresponding characters in the two strings * are equal ignoring case. *

* Two characters {@code c1} and {@code c2} are considered the same * ignoring case if at least one of the following is true: *

    *
  • The two characters are the same (as compared by the * {@code ==} operator) *
  • Applying the method {@link * Character#toUpperCase(char)} to each character * produces the same result *
  • Applying the method {@link * Character#toLowerCase(char)} to each character * produces the same result *
* * @param anotherString The {@code CharSeq} to compare this {@code CharSeq} against * @return {@code true} if the argument is not {@code null} and it * represents an equivalent {@code CharSeq} ignoring case; {@code * false} otherwise * @see #equals(Object) */ public boolean equalsIgnoreCase(CharSeq anotherString) { return back.equalsIgnoreCase(anotherString.back); } /** * Compares two strings lexicographically. * The comparison is based on the Unicode value of each character in * the strings. The character sequence represented by this * {@code CharSeq} object is compared lexicographically to the * character sequence represented by the argument string. The result is * a negative integer if this {@code CharSeq} object * lexicographically precedes the argument string. The result is a * positive integer if this {@code CharSeq} object lexicographically * follows the argument string. The result is zero if the strings * are equal; {@code compareTo} returns {@code 0} exactly when * the {@link #equals(Object)} method would return {@code true}. *

* This is the definition of lexicographic ordering. If two strings are * different, then either they have different characters at some index * that is a valid index for both strings, or their lengths are different, * or both. If they have different characters at one or more index * positions, let k be the smallest such index; then the string * whose character at position k has the smaller value, as * determined by using the < operator, lexicographically precedes the * other string. In this case, {@code compareTo} returns the * difference of the two character values at position {@code k} in * the two string -- that is, the value: *

     * this.charAt(k)-anotherString.charAt(k)
     * 
* If there is no index position at which they differ, then the shorter * string lexicographically precedes the longer string. In this case, * {@code compareTo} returns the difference of the lengths of the * strings -- that is, the value: *
     * this.length()-anotherString.length()
     * 
* * @param anotherString the {@code CharSeq} to be compared. * @return the value {@code 0} if the argument string is equal to * this string; a value less than {@code 0} if this string * is lexicographically less than the string argument; and a * value greater than {@code 0} if this string is * lexicographically greater than the string argument. */ public int compareTo(CharSeq anotherString) { return back.compareTo(anotherString.back); } /** * Compares two strings lexicographically, ignoring case * differences. This method returns an integer whose sign is that of * calling {@code compareTo} with normalized versions of the strings * where case differences have been eliminated by calling * {@code Character.toLowerCase(Character.toUpperCase(character))} on * each character. *

* Note that this method does not take locale into account, * and will result in an unsatisfactory ordering for certain locales. * The java.text package provides collators to allow * locale-sensitive ordering. * * @param str the {@code CharSeq} to be compared. * @return a negative integer, zero, or a positive integer as the * specified String is greater than, equal to, or less * than this String, ignoring case considerations. */ public int compareToIgnoreCase(CharSeq str) { return back.compareToIgnoreCase(str.back); } /** * Tests if two string regions are equal. *

* A substring of this {@code CharSeq} object is compared to a substring * of the argument other. The result is true if these substrings * represent identical character sequences. The substring of this * {@code CharSeq} object to be compared begins at index {@code toffset} * and has length {@code len}. The substring of other to be compared * begins at index {@code ooffset} and has length {@code len}. The * result is {@code false} if and only if at least one of the following * is true: *

  • {@code toffset} is negative. *
  • {@code ooffset} is negative. *
  • {@code toffset+len} is greater than the length of this * {@code CharSeq} object. *
  • {@code ooffset+len} is greater than the length of the other * argument. *
  • There is some nonnegative integer k less than {@code len} * such that: * {@code this.charAt(toffset + }k{@code ) != other.charAt(ooffset + } * k{@code )} *
* * @param toffset the starting offset of the subregion in this string. * @param other the string argument. * @param ooffset the starting offset of the subregion in the string * argument. * @param len the number of characters to compare. * @return {@code true} if the specified subregion of this string * exactly matches the specified subregion of the string argument; * {@code false} otherwise. */ public boolean regionMatches(int toffset, CharSeq other, int ooffset, int len) { return back.regionMatches(toffset, other.back, ooffset, len); } /** * Tests if two string regions are equal. *

* A substring of this {@code CharSeq} object is compared to a substring * of the argument {@code other}. The result is {@code true} if these * substrings represent character sequences that are the same, ignoring * case if and only if {@code ignoreCase} is true. The substring of * this {@code CharSeq} object to be compared begins at index * {@code toffset} and has length {@code len}. The substring of * {@code other} to be compared begins at index {@code ooffset} and * has length {@code len}. The result is {@code false} if and only if * at least one of the following is true: *

  • {@code toffset} is negative. *
  • {@code ooffset} is negative. *
  • {@code toffset+len} is greater than the length of this * {@code CharSeq} object. *
  • {@code ooffset+len} is greater than the length of the other * argument. *
  • {@code ignoreCase} is {@code false} and there is some nonnegative * integer k less than {@code len} such that: *
         * this.charAt(toffset+k) != other.charAt(ooffset+k)
         * 
    *
  • {@code ignoreCase} is {@code true} and there is some nonnegative * integer k less than {@code len} such that: *
         * Character.toLowerCase(this.charAt(toffset+k)) !=
         * Character.toLowerCase(other.charAt(ooffset+k))
         * 
    * and: *
         * Character.toUpperCase(this.charAt(toffset+k)) !=
         *         Character.toUpperCase(other.charAt(ooffset+k))
         * 
    *
* * @param ignoreCase if {@code true}, ignore case when comparing * characters. * @param toffset the starting offset of the subregion in this * string. * @param other the string argument. * @param ooffset the starting offset of the subregion in the string * argument. * @param len the number of characters to compare. * @return {@code true} if the specified subregion of this string * matches the specified subregion of the string argument; * {@code false} otherwise. Whether the matching is exact * or case insensitive depends on the {@code ignoreCase} * argument. */ public boolean regionMatches(boolean ignoreCase, int toffset, CharSeq other, int ooffset, int len) { return back.regionMatches(ignoreCase, toffset, other.back, ooffset, len); } @Override public CharSeq subSequence(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new IndexOutOfBoundsException("begin index " + beginIndex + " < 0"); } if (endIndex > length()) { throw new IndexOutOfBoundsException("endIndex " + endIndex + " > length " + length()); } final int subLen = endIndex - beginIndex; if (subLen < 0) { throw new IllegalArgumentException("beginIndex " + beginIndex + " > endIndex " + endIndex); } if (beginIndex == 0 && endIndex == length()) { return this; } else { return CharSeq.of(back.subSequence(beginIndex, endIndex)); } } /** * Tests if the substring of this string beginning at the * specified index starts with the specified prefix. * * @param prefix the prefix. * @param toffset where to begin looking in this string. * @return {@code true} if the character sequence represented by the * argument is a prefix of the substring of this object starting * at index {@code toffset}; {@code false} otherwise. * The result is {@code false} if {@code toffset} is * negative or greater than the length of this * {@code CharSeq} object; otherwise the result is the same * as the result of the expression *
     *          this.substring(toffset).startsWith(prefix)
     *          
*/ public boolean startsWith(CharSeq prefix, int toffset) { return back.startsWith(prefix.back, toffset); } /** * Tests if this string starts with the specified prefix. * * @param prefix the prefix. * @return {@code true} if the character sequence represented by the * argument is a prefix of the character sequence represented by * this string; {@code false} otherwise. * Note also that {@code true} will be returned if the * argument is an empty string or is equal to this * {@code CharSeq} object as determined by the * {@link #equals(Object)} method. */ public boolean startsWith(CharSeq prefix) { return back.startsWith(prefix.back); } /** * Tests if this string ends with the specified suffix. * * @param suffix the suffix. * @return {@code true} if the character sequence represented by the * argument is a suffix of the character sequence represented by * this object; {@code false} otherwise. Note that the * result will be {@code true} if the argument is the * empty string or is equal to this {@code CharSeq} object * as determined by the {@link #equals(Object)} method. */ public boolean endsWith(CharSeq suffix) { return back.endsWith(suffix.back); } /** * Returns the index within this string of the first occurrence of * the specified character. If a character with value * {@code ch} occurs in the character sequence represented by * this {@code CharSeq} object, then the index (in Unicode * code units) of the first such occurrence is returned. For * values of {@code ch} in the range from 0 to 0xFFFF * (inclusive), this is the smallest value k such that: *
     * this.charAt(k) == ch
     * 
* is true. For other values of {@code ch}, it is the * smallest value k such that: *
     * this.codePointAt(k) == ch
     * 
* is true. In either case, if no such character occurs in this * string, then {@code -1} is returned. * * @param ch a character (Unicode code point). * @return the index of the first occurrence of the character in the * character sequence represented by this object, or * {@code -1} if the character does not occur. */ public int indexOf(int ch) { return back.indexOf(ch); } /** * Returns the index of the first occurrence of the given element as an {@code Option}. * * @param ch a character (Unicode code point). * @return {@code Some(index)} or {@code None} if not found. */ Option indexOfOption(int ch) { return io.vavr.collection.Collections.indexOption(indexOf(ch)); } /** * Returns the index within this string of the first occurrence of the * specified character, starting the search at the specified index. *

* If a character with value {@code ch} occurs in the * character sequence represented by this {@code CharSeq} * object at an index no smaller than {@code fromIndex}, then * the index of the first such occurrence is returned. For values * of {@code ch} in the range from 0 to 0xFFFF (inclusive), * this is the smallest value k such that: *

     * (this.charAt(k) == ch) {@code &&} (k >= fromIndex)
     * 
* is true. For other values of {@code ch}, it is the * smallest value k such that: *
     * (this.codePointAt(k) == ch) {@code &&} (k >= fromIndex)
     * 
* is true. In either case, if no such character occurs in this * string at or after position {@code fromIndex}, then * {@code -1} is returned. *

* There is no restriction on the value of {@code fromIndex}. If it * is negative, it has the same effect as if it were zero: this entire * string may be searched. If it is greater than the length of this * string, it has the same effect as if it were equal to the length of * this string: {@code -1} is returned. *

* All indices are specified in {@code char} values * (Unicode code units). * * @param ch a character (Unicode code point). * @param fromIndex the index to start the search from. * @return the index of the first occurrence of the character in the * character sequence represented by this object that is greater * than or equal to {@code fromIndex}, or {@code -1} * if the character does not occur. */ public int indexOf(int ch, int fromIndex) { return back.indexOf(ch, fromIndex); } /** * Returns the index of the first occurrence of the given element as an {@code Option}, * starting the search at the specified index. * * @param ch a character (Unicode code point). * @param fromIndex the index to start the search from. * @return {@code Some(index)} or {@code None} if not found. */ Option indexOfOption(int ch, int fromIndex) { return io.vavr.collection.Collections.indexOption(indexOf(ch, fromIndex)); } /** * Returns the index within this string of the last occurrence of * the specified character. For values of {@code ch} in the * range from 0 to 0xFFFF (inclusive), the index (in Unicode code * units) returned is the largest value k such that: *

     * this.charAt(k) == ch
     * 
* is true. For other values of {@code ch}, it is the * largest value k such that: *
     * this.codePointAt(k) == ch
     * 
* is true. In either case, if no such character occurs in this * string, then {@code -1} is returned. The * {@code CharSeq} is searched backwards starting at the last * character. * * @param ch a character (Unicode code point). * @return the index of the last occurrence of the character in the * character sequence represented by this object, or * {@code -1} if the character does not occur. */ public int lastIndexOf(int ch) { return back.lastIndexOf(ch); } /** * Returns the index of the last occurrence of the given element as an {@code Option}. * * @param ch a character (Unicode code point). * @return {@code Some(index)} or {@code None} if not found. */ Option lastIndexOfOption(int ch) { return io.vavr.collection.Collections.indexOption(lastIndexOf(ch)); } /** * Returns the index within this string of the last occurrence of * the specified character, searching backward starting at the * specified index. For values of {@code ch} in the range * from 0 to 0xFFFF (inclusive), the index returned is the largest * value k such that: *
     * (this.charAt(k) == ch) {@code &&} (k <= fromIndex)
     * 
* is true. For other values of {@code ch}, it is the * largest value k such that: *
     * (this.codePointAt(k) == ch) {@code &&} (k <= fromIndex)
     * 
* is true. In either case, if no such character occurs in this * string at or before position {@code fromIndex}, then * {@code -1} is returned. *

* All indices are specified in {@code char} values * (Unicode code units). * * @param ch a character (Unicode code point). * @param fromIndex the index to start the search from. There is no * restriction on the value of {@code fromIndex}. If it is * greater than or equal to the length of this string, it has * the same effect as if it were equal to one less than the * length of this string: this entire string may be searched. * If it is negative, it has the same effect as if it were -1: * -1 is returned. * @return the index of the last occurrence of the character in the * character sequence represented by this object that is less * than or equal to {@code fromIndex}, or {@code -1} * if the character does not occur before that point. */ public int lastIndexOf(int ch, int fromIndex) { return back.lastIndexOf(ch, fromIndex); } /** * Returns the index of the last occurrence of the given element as an {@code Option}, * starting the search at the specified index. * * @param ch a character (Unicode code point). * @param fromIndex the index to start the search from. * @return {@code Some(index)} or {@code None} if not found. */ public Option lastIndexOfOption(int ch, int fromIndex) { return io.vavr.collection.Collections.indexOption(lastIndexOf(ch, fromIndex)); } /** * Returns the index within this string of the first occurrence of the * specified substring. *

* The returned index is the smallest value k for which: *

     * this.startsWith(str, k)
     * 
* If no such value of k exists, then {@code -1} is returned. * * @param str the substring to search for. * @return the index of the first occurrence of the specified substring, * or {@code -1} if there is no such occurrence. */ public int indexOf(CharSeq str) { return back.indexOf(str.back); } /** * Returns the index of the first occurrence of the given element as an {@code Option}. * * @param str the substring to search for. * @return {@code Some(index)} or {@code None} if not found. */ public Option indexOfOption(CharSeq str) { return io.vavr.collection.Collections.indexOption(indexOf(str)); } /** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. *

* The returned index is the smallest value k for which: *

     * k >= fromIndex {@code &&} this.startsWith(str, k)
     * 
* If no such value of k exists, then {@code -1} is returned. * * @param str the substring to search for. * @param fromIndex the index from which to start the search. * @return the index of the first occurrence of the specified substring, * starting at the specified index, * or {@code -1} if there is no such occurrence. */ public int indexOf(CharSeq str, int fromIndex) { return back.indexOf(str.back, fromIndex); } /** * Returns the index of the first occurrence of the given element as an {@code Option}, * starting the search at the specified index. * * @param str the substring to search for. * @param fromIndex the index from which to start the search. * @return {@code Some(index)} or {@code None} if not found. */ public Option indexOfOption(CharSeq str, int fromIndex) { return io.vavr.collection.Collections.indexOption(indexOf(str, fromIndex)); } /** * Returns the index within this string of the last occurrence of the * specified substring. The last occurrence of the empty string "" * is considered to occur at the index value {@code this.length()}. *

* The returned index is the largest value k for which: *

     * this.startsWith(str, k)
     * 
* If no such value of k exists, then {@code -1} is returned. * * @param str the substring to search for. * @return the index of the last occurrence of the specified substring, * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(CharSeq str) { return back.lastIndexOf(str.back); } /** * Returns the index of the last occurrence of the given element as an {@code Option}. * * @param str the substring to search for. * @return {@code Some(index)} or {@code None} if not found. */ public Option lastIndexOfOption(CharSeq str) { return io.vavr.collection.Collections.indexOption(lastIndexOf(str)); } /** * Returns the index within this string of the last occurrence of the * specified substring, searching backward starting at the specified index. *

* The returned index is the largest value k for which: *

     * k {@code <=} fromIndex {@code &&} this.startsWith(str, k)
     * 
* If no such value of k exists, then {@code -1} is returned. * * @param str the substring to search for. * @param fromIndex the index to start the search from. * @return the index of the last occurrence of the specified substring, * searching backward from the specified index, * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(CharSeq str, int fromIndex) { return back.lastIndexOf(str.back, fromIndex); } /** * Returns the index of the last occurrence of the given element as an {@code Option}, * starting the search at the specified index. * * @param str the substring to search for. * @param fromIndex the index to start the search from. * @return {@code Some(index)} or {@code None} if not found. */ public Option lastIndexOfOption(CharSeq str, int fromIndex) { return io.vavr.collection.Collections.indexOption(lastIndexOf(str, fromIndex)); } /** * Returns a string that is a substring of this string. The * substring begins with the character at the specified index and * extends to the end of this string.

* Examples: *

     * "unhappy".substring(2) returns "happy"
     * "Harbison".substring(3) returns "bison"
     * "emptiness".substring(9) returns "" (an empty string)
     * 
* * @param beginIndex the beginning index, inclusive. * @return the specified substring. * @throws IndexOutOfBoundsException if * {@code beginIndex} is negative or larger than the * length of this {@code CharSeq} object. */ public CharSeq substring(int beginIndex) { return CharSeq.of(back.substring(beginIndex)); } /** * Returns a string that is a substring of this string. The * substring begins at the specified {@code beginIndex} and * extends to the character at index {@code endIndex - 1}. * Thus the length of the substring is {@code endIndex-beginIndex}. *

* Examples: *

     * "hamburger".substring(4, 8) returns "urge"
     * "smiles".substring(1, 5) returns "mile"
     * 
* * @param beginIndex the beginning index, inclusive. * @param endIndex the ending index, exclusive. * @return the specified substring. * @throws IndexOutOfBoundsException if the * {@code beginIndex} is negative, or * {@code endIndex} is larger than the length of * this {@code CharSeq} object, or * {@code beginIndex} is larger than * {@code endIndex}. */ public CharSeq substring(int beginIndex, int endIndex) { return CharSeq.of(back.substring(beginIndex, endIndex)); } @Override public String stringPrefix() { return "CharSeq"; } /** * Returns a string containing the characters in this sequence in the same * order as this sequence. The length of the string will be the length of * this sequence. * * @return a string consisting of exactly this sequence of characters */ @Override public String toString() { return back; } /** * Concatenates the specified string to the end of this string. *

* If the length of the argument string is {@code 0}, then this * {@code CharSeq} object is returned. Otherwise, a * {@code CharSeq} object is returned that represents a character * sequence that is the concatenation of the character sequence * represented by this {@code CharSeq} object and the character * sequence represented by the argument string.

* Examples: *

     * "cares".concat("s") returns "caress"
     * "to".concat("get").concat("her") returns "together"
     * 
* * @param str the {@code CharSeq} that is concatenated to the end * of this {@code CharSeq}. * @return a string that represents the concatenation of this object's * characters followed by the string argument's characters. */ public CharSeq concat(CharSeq str) { return CharSeq.of(back.concat(str.back)); } /** * Tells whether or not this string matches the given regular expression. *

* An invocation of this method of the form * str{@code .matches(}regex{@code )} yields exactly the * same result as the expression *

* {@link Pattern}.{@link Pattern#matches(String, CharSequence) * matches(regex, str)} *
* * @param regex the regular expression to which this string is to be matched * @return {@code true} if, and only if, this string matches the * given regular expression * @throws PatternSyntaxException if the regular expression's syntax is invalid * @see Pattern */ public boolean matches(String regex) { return back.matches(regex); } /** * Returns true if and only if this string contains the specified * sequence of char values. * * @param s the sequence to search for * @return true if this string contains {@code s}, false otherwise */ public boolean contains(CharSequence s) { return back.contains(s); } /** * Replaces the first substring of this string that matches the given regular expression with the * given replacement. *

* An invocation of this method of the form * str{@code .replaceFirst(}regex{@code ,} repl{@code )} * yields exactly the same result as the expression *

* * {@link Pattern}.{@link * Pattern#compile compile}(regex).{@link * Pattern#matcher(CharSequence) matcher}(str).{@link * java.util.regex.Matcher#replaceFirst replaceFirst}(repl) * *
* Note that backslashes ({@code \}) and dollar signs ({@code $}) in the * replacement string may cause the results to be different than if it were * being treated as a literal replacement string; see * {@link java.util.regex.Matcher#replaceFirst}. * Use {@link java.util.regex.Matcher#quoteReplacement} to suppress the special * meaning of these characters, if desired. * * @param regex the regular expression to which this string is to be matched * @param replacement the string to be substituted for the first match * @return The resulting {@code CharSeq} * @throws PatternSyntaxException if the regular expression's syntax is invalid * @see Pattern */ public CharSeq replaceFirst(String regex, String replacement) { return CharSeq.of(back.replaceFirst(regex, replacement)); } /** * Replaces each substring of this string that matches the given regular expression with the * given replacement. *

* An invocation of this method of the form * str{@code .replaceAll(}regex{@code ,} repl{@code )} * yields exactly the same result as the expression *

* * {@link Pattern}.{@link * Pattern#compile compile}(regex).{@link * Pattern#matcher(CharSequence) matcher}(str).{@link * java.util.regex.Matcher#replaceAll replaceAll}(repl) * *
* Note that backslashes ({@code \}) and dollar signs ({@code $}) in the * replacement string may cause the results to be different than if it were * being treated as a literal replacement string; see * {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}. * Use {@link java.util.regex.Matcher#quoteReplacement} to suppress the special * meaning of these characters, if desired. * * @param regex the regular expression to which this string is to be matched * @param replacement the string to be substituted for each match * @return The resulting {@code CharSeq} * @throws PatternSyntaxException if the regular expression's syntax is invalid * @see Pattern */ public CharSeq replaceAll(String regex, String replacement) { return CharSeq.of(back.replaceAll(regex, replacement)); } /** * Replaces each substring of this string that matches the literal target * sequence with the specified literal replacement sequence. The * replacement proceeds from the beginning of the string to the end, for * example, replacing "aa" with "b" in the string "aaa" will result in * "ba" rather than "ab". * * @param target The sequence of char values to be replaced * @param replacement The replacement sequence of char values * @return The resulting string */ public CharSeq replace(CharSequence target, CharSequence replacement) { return CharSeq.of(back.replace(target, replacement)); } /** * Splits this string around matches of the given * regular expression. *

* This method works as if by invoking the two-argument {@link #split(String, int)} * method with the given expression and a limit argument of zero. * Trailing empty strings are therefore not included in the resulting {@link Seq}. *

* The string {@code "boo:and:foo"}, for example, yields the following results with these expressions: *

* * * * * * * * * * * * * *
RegexResult
:{@code { "boo", "and", "foo" }}
o{@code { "b", "", ":and:f" }}
*
* * @param regex the delimiting regular expression * @return the Seq of strings computed by splitting this string around matches of the given regular expression * @throws PatternSyntaxException if the regular expression's syntax is invalid * @see Pattern */ public Seq split(String regex) { return split(regex, 0); } /** * Splits this string around matches of the given * regular expression. *

* The array returned by this method contains each substring of this * string that is terminated by another substring that matches the given * expression or is terminated by the end of the string. The substrings in * the array are in the order in which they occur in this string. If the * expression does not match any part of the input then the resulting array * has just one element, namely this string. *

* When there is a positive-width match at the beginning of this * string then an empty leading substring is included at the beginning * of the resulting array. A zero-width match at the beginning however * never produces such empty leading substring. *

* The {@code limit} parameter controls the number of times the * pattern is applied and therefore affects the length of the resulting * array. If the limit n is greater than zero then the pattern * will be applied at most n - 1 times, the array's * length will be no greater than n, and the array's last entry * will contain all input beyond the last matched delimiter. If n * is non-positive then the pattern will be applied as many times as * possible and the array can have any length. If n is zero then * the pattern will be applied as many times as possible, the array can * have any length, and trailing empty strings will be discarded. *

* The string {@code "boo:and:foo"}, for example, yields the * following results with these parameters: *

* * * * * * * * * * * * * * * * * * * * * * * *
RegexLimitResult
:2{@code { "boo", "and:foo" }}
:5{@code { "boo", "and", "foo" }}
:-2{@code { "boo", "and", "foo" }}
o5{@code { "b", "", ":and:f", "", "" }}
o-2{@code { "b", "", ":and:f", "", "" }}
o0{@code { "b", "", ":and:f" }}
* An invocation of this method of the form * str.{@code split(}regex{@code ,} n{@code )} * yields the same result as the expression *
* * {@link Pattern}.{@link * Pattern#compile compile}(regex).{@link * Pattern#split(CharSequence, int) split}(strn) * *
* * @param regex the delimiting regular expression * @param limit the result threshold, as described above * @return the Seq of strings computed by splitting this string around matches of the given regular expression * @throws PatternSyntaxException if the regular expression's syntax is invalid * @see Pattern */ public Seq split(String regex, int limit) { final Seq split = Array.wrap(back.split(regex, limit)); return split.map(CharSeq::of); } /** * Converts all of the characters in this {@code CharSeq} to lower * case using the rules of the given {@code Locale}. Case mapping is based * on the Unicode Standard version specified by the {@link Character Character} * class. Since case mappings are not always 1:1 char mappings, the resulting * {@code CharSeq} may be a different length than the original {@code CharSeq}. *

* Examples of lowercase mappings are in the following table: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Language Code of LocaleUpper CaseLower CaseDescription
tr (Turkish)\u0130\u0069capital letter I with dot above -> small letter i
tr (Turkish)\u0049\u0131capital letter I -> small letter dotless i
(all)French Friesfrench frieslowercased all chars in String
(all)capiotacapchi * capthetacapupsil * capsigmaiotachi * thetaupsilon * sigmalowercased all chars in String
* * @param locale use the case transformation rules for this locale * @return the {@code CharSeq}, converted to lowercase. * @see String#toLowerCase() * @see String#toUpperCase() * @see String#toUpperCase(Locale) */ public CharSeq toLowerCase(Locale locale) { return CharSeq.of(back.toLowerCase(locale)); } /** * Converts all of the characters in this {@code CharSeq} to lower * case using the rules of the default locale. This is equivalent to calling * {@code toLowerCase(Locale.getDefault())}. *

* Note: This method is locale sensitive, and may produce unexpected * results if used for strings that are intended to be interpreted locale * independently. * Examples are programming language identifiers, protocol keys, and HTML * tags. * For instance, {@code "TITLE".toLowerCase()} in a Turkish locale * returns {@code "t\u005Cu0131tle"}, where '\u005Cu0131' is the * LATIN SMALL LETTER DOTLESS I character. * To obtain correct results for locale insensitive strings, use * {@code toLowerCase(Locale.ROOT)}. *

* * @return the {@code CharSeq}, converted to lowercase. * @see String#toLowerCase(Locale) */ public CharSeq toLowerCase() { return CharSeq.of(back.toLowerCase(Locale.getDefault())); } /** * Converts all of the characters in this {@code CharSeq} to upper * case using the rules of the given {@code Locale}. Case mapping is based * on the Unicode Standard version specified by the {@link Character Character} * class. Since case mappings are not always 1:1 char mappings, the resulting * {@code CharSeq} may be a different length than the original {@code CharSeq}. *

* Examples of locale-sensitive and 1:M case mappings are in the following table. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Language Code of LocaleLower CaseUpper CaseDescription
tr (Turkish)\u0069\u0130small letter i -> capital letter I with dot above
tr (Turkish)\u0131\u0049small letter dotless i -> capital letter I
(all)\u00df\u0053 \u0053small letter sharp s -> two letters: SS
(all)FahrvergnügenFAHRVERGNÜGEN
* * @param locale use the case transformation rules for this locale * @return the {@code CharSeq}, converted to uppercase. * @see String#toUpperCase() * @see String#toLowerCase() * @see String#toLowerCase(Locale) */ public CharSeq toUpperCase(Locale locale) { return CharSeq.of(back.toUpperCase(locale)); } /** * Converts all of the characters in this {@code CharSeq} to upper * case using the rules of the default locale. This method is equivalent to * {@code toUpperCase(Locale.getDefault())}. *

* Note: This method is locale sensitive, and may produce unexpected * results if used for strings that are intended to be interpreted locale * independently. * Examples are programming language identifiers, protocol keys, and HTML * tags. * For instance, {@code "title".toUpperCase()} in a Turkish locale * returns {@code "T\u005Cu0130TLE"}, where '\u005Cu0130' is the * LATIN CAPITAL LETTER I WITH DOT ABOVE character. * To obtain correct results for locale insensitive strings, use * {@code toUpperCase(Locale.ROOT)}. *

* * @return the {@code CharSeq}, converted to uppercase. * @see String#toUpperCase(Locale) */ public CharSeq toUpperCase() { return CharSeq.of(back.toUpperCase(Locale.getDefault())); } /** * Converts the first character in this {@code CharSeq} to upper * case using the rules of the given {@code Locale}. If the {@code CharSeq} is * empty, it won't have any effect. Case mapping is based * on the Unicode Standard version specified by the {@link Character Character} * class. Since case mappings are not always 1:1 char mappings, the resulting * {@code CharSeq} may be a different length than the original {@code CharSeq}. *

* Examples of locale-sensitive and 1:M case mappings are in the following table. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Language Code of LocaleLower CaseUpper CaseDescription
tr (Turkish)\u0069\u0130small letter i -> capital letter I with dot above
tr (Turkish)\u0131\u0049small letter dotless i -> capital letter I
(all)\u00df\u0053 \u0053small letter sharp s -> two letters: SS
(all)FahrvergnügenFAHRVERGNÜGEN
* * @param locale use the case transformation rules for this locale * @return the {@code CharSeq}, capitalized. */ public CharSeq capitalize(Locale locale) { if (back.isEmpty()) { return this; } return CharSeq.of(back.substring(0, 1).toUpperCase(locale) + back.substring(1)); } /** * Converts the first character in this {@code CharSeq} to upper * case using the rules of the default locale. If the {@code CharSeq} is * empty, it won't have any effect. This method is equivalent to * {@code capitalize(Locale.getDefault())}. *

* Note: This method is locale sensitive, and may produce unexpected * results if used for strings that are intended to be interpreted locale * independently. * Examples are programming language identifiers, protocol keys, and HTML * tags. * For instance, {@code "title".toUpperCase()} in a Turkish locale * returns {@code "T\u005Cu0130TLE"}, where '\u005Cu0130' is the * LATIN CAPITAL LETTER I WITH DOT ABOVE character. * To obtain correct results for locale insensitive strings, use * {@code toUpperCase(Locale.ROOT)}. *

* * @return the {@code CharSeq}, capitalized. */ public CharSeq capitalize() { return capitalize(Locale.getDefault()); } /** * Returns a string whose value is this string, with any leading and trailing * whitespace removed. *

* If this {@code CharSeq} object represents an empty character * sequence, or the first and last characters of character sequence * represented by this {@code CharSeq} object both have codes * greater than {@code '\u005Cu0020'} (the space character), then a * reference to this {@code CharSeq} object is returned. *

* Otherwise, if there is no character with a code greater than * {@code '\u005Cu0020'} in the string, then a * {@code CharSeq} object representing an empty string is * returned. *

* Otherwise, let k be the index of the first character in the * string whose code is greater than {@code '\u005Cu0020'}, and let * m be the index of the last character in the string whose code * is greater than {@code '\u005Cu0020'}. A {@code CharSeq} * object is returned, representing the substring of this string that * begins with the character at index k and ends with the * character at index m-that is, the result of * {@code this.substring(k, m + 1)}. *

* This method may be used to trim whitespace (as defined above) from * the beginning and end of a string. * * @return A string whose value is this string, with any leading and trailing white * space removed, or this string if it has no leading or * trailing white space. */ public CharSeq trim() { return of(back.trim()); } /** * Converts this string to a new character array. * * @return a newly allocated character array whose length is the length * of this string and whose contents are initialized to contain * the character sequence represented by this string. */ public char[] toCharArray() { return back.toCharArray(); } // -- number conversion /** * Decodes this {@code CharSeq} into a {@code Byte} by calling {@link Byte#decode(String)}. *

* We write * *


     * Byte value = charSeq.decodeByte();
     * 
* * instead of * *

     * Byte value = Byte.decode(charSeq.mkString());
     * 
* * @return a {@code Byte} object holding the byte value represented by this {@code CharSeq} * @throws NumberFormatException if this {@code CharSeq} does not contain a parsable byte. */ public Byte decodeByte() { return Byte.decode(back); } /** * Decodes this {@code CharSeq} into an {@code Integer} by calling {@link Integer#decode(String)}. *

* We write * *


     * Integer value = charSeq.decodeInteger();
     * 
* * instead of * *

     * Integer value = Integer.decode(charSeq.mkString());
     * 
* * @return an {@code Integer} object holding the int value represented by this {@code CharSeq} * @throws NumberFormatException if this {@code CharSeq} does not contain a parsable int. */ public Integer decodeInteger() { return Integer.decode(back); } /** * Decodes this {@code CharSeq} into a {@code Long} by calling {@link Long#decode(String)}. *

* We write * *


     * Long value = charSeq.decodeLong();
     * 
* * instead of * *

     * Long value = Long.decode(charSeq.mkString());
     * 
* * @return a {@code Long} object holding the long value represented by this {@code CharSeq} * @throws NumberFormatException if this {@code CharSeq} does not contain a parsable long. */ public Long decodeLong() { return Long.decode(back); } /** * Decodes this {@code CharSeq} into a {@code Short} by calling {@link Short#decode(String)}. *

* We write * *


     * Short value = charSeq.decodeShort();
     * 
* * instead of * *

     * Short value = Short.decode(charSeq.mkString());
     * 
* * @return a {@code Short} object holding the short value represented by this {@code CharSeq} * @throws NumberFormatException if this {@code CharSeq} does not contain a parsable short. */ public Short decodeShort() { return Short.decode(back); } /** * Parses this {@code CharSeq} as a boolean by calling {@link Boolean#parseBoolean(String)}. *

* We write * *


     * boolean value = charSeq.parseBoolean();
     * 
* * instead of * *

     * boolean value = Boolean.parseBoolean(charSeq.mkString());
     * 
* * @return the boolean represented by this {@code CharSeq} */ public boolean parseBoolean() { return Boolean.parseBoolean(back); } /** * Parses this {@code CharSeq} as a signed decimal byte by calling {@link Byte#parseByte(String)}. *

* We write * *


     * byte value = charSeq.parseByte();
     * 
* * instead of * *

     * byte value = Byte.parseByte(charSeq.mkString());
     * 
* * @return the byte value represented by this {@code CharSeq} in decimal * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable byte. */ public byte parseByte() { return Byte.parseByte(back); } /** * Parses this {@code CharSeq} as a signed byte in the specified radix * by calling {@link Byte#parseByte(String, int)}. *

* We write * *


     * byte value = charSeq.parseByte(radix);
     * 
* * instead of * *

     * byte value = Byte.parseByte(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this {@code CharSeq} * @return the byte value represented by this {@code CharSeq} in the specified radix * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable byte. */ public byte parseByte(int radix) { return Byte.parseByte(back, radix); } /** * Parses this {@code CharSeq} as a double by calling {@link Double#parseDouble(String)}. *

* We write * *


     * double value = charSeq.parseDouble();
     * 
* * instead of * *

     * double value = Double.parseDouble(charSeq.mkString());
     * 
* * @return the double value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable double. */ public double parseDouble() { return Double.parseDouble(back); } /** * Parses this {@code CharSeq} as a float by calling {@link Float#parseFloat(String)}. *

* We write * *


     * float value = charSeq.parseFloat();
     * 
* * instead of * *

     * float value = Double.parseFloat(charSeq.mkString());
     * 
* * @return the float value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable float. */ public float parseFloat() { return Float.parseFloat(back); } /** * Parses this {@code CharSeq} as a signed decimal int by calling {@link Integer#parseInt(String)}. *

* We write * *


     * int value = charSeq.parseInt();
     * 
* * instead of * *

     * int value = Integer.parseInt(charSeq.mkString());
     * 
* * @return the int value represented by this {@code CharSeq} in decimal * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable int. */ public int parseInt() { return Integer.parseInt(back); } /** * Parses this {@code CharSeq} as a signed int in the specified radix * by calling {@link Integer#parseInt(String, int)}. *

* We write * *


     * int value = charSeq.parseInt(radix);
     * 
* * instead of * *

     * int value = Integer.parseInt(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this {@code CharSeq} * @return the int value represented by this {@code CharSeq} in the specified radix * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable int. */ public int parseInt(int radix) { return Integer.parseInt(back, radix); } /** * Parses this {@code CharSeq} as a unsigned decimal int by calling {@link Integer#parseUnsignedInt(String)}. *

* We write * *


     * int value = charSeq.parseUnsignedInt();
     * 
* * instead of * *

     * int value = Integer.parseUnsignedInt(charSeq.mkString());
     * 
* * @return the unsigned int value represented by this {@code CharSeq} in decimal * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable unsigned int. */ @GwtIncompatible public int parseUnsignedInt() { return Integer.parseUnsignedInt(back); } /** * Parses this {@code CharSeq} as a unsigned int in the specified radix * by calling {@link Integer#parseUnsignedInt(String, int)}. *

* We write * *


     * int value = charSeq.parseUnsignedInt(radix);
     * 
* * instead of * *

     * int value = Integer.parseUnsignedInt(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this {@code CharSeq} * @return the unsigned int value represented by this {@code CharSeq} in the specified radix * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable unsigned int. */ @GwtIncompatible public int parseUnsignedInt(int radix) { return Integer.parseUnsignedInt(back, radix); } /** * Parses this {@code CharSeq} as a signed decimal long by calling {@link Long#parseLong(String)}. *

* We write * *


     * long value = charSeq.parseLong();
     * 
* * instead of * *

     * long value = Long.parseLong(charSeq.mkString());
     * 
* * @return the long value represented by this {@code CharSeq} in decimal * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable long. */ public long parseLong() { return Long.parseLong(back); } /** * Parses this {@code CharSeq} as a signed long in the specified radix * by calling {@link Long#parseLong(String, int)}. *

* We write * *


     * long value = charSeq.parseLong(radix);
     * 
* * instead of * *

     * long value = Long.parseLong(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this {@code CharSeq} * @return the long value represented by this {@code CharSeq} in the specified radix * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable long. */ public long parseLong(int radix) { return Long.parseLong(back, radix); } /** * Parses this {@code CharSeq} as a unsigned decimal long by calling {@link Long#parseUnsignedLong(String)}. *

* We write * *


     * long value = charSeq.parseUnsignedLong();
     * 
* * instead of * *

     * long value = Long.parseUnsignedLong(charSeq.mkString());
     * 
* * @return the unsigned long value represented by this {@code CharSeq} in decimal * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable unsigned long. */ @GwtIncompatible public long parseUnsignedLong() { return Long.parseUnsignedLong(back); } /** * Parses this {@code CharSeq} as a unsigned long in the specified radix * by calling {@link Long#parseUnsignedLong(String, int)}. *

* We write * *


     * long value = charSeq.parseUnsignedLong(radix);
     * 
* * instead of * *

     * long value = Long.parseUnsignedLong(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this {@code CharSeq} * @return the unsigned long value represented by this {@code CharSeq} in the specified radix * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable unsigned long. */ @GwtIncompatible public long parseUnsignedLong(int radix) { return Long.parseUnsignedLong(back, radix); } /** * Parses this {@code CharSeq} as a signed decimal short by calling {@link Short#parseShort(String)}. *

* We write * *


     * short value = charSeq.parseShort();
     * 
* * instead of * *

     * short value = Short.parseShort(charSeq.mkString());
     * 
* * @return the short value represented by this {@code CharSeq} in decimal * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable short. */ public short parseShort() { return Short.parseShort(back); } /** * Parses this {@code CharSeq} as a signed short in the specified radix * by calling {@link Short#parseShort(String, int)}. *

* We write * *


     * short value = charSeq.parseShort(radix);
     * 
* * instead of * *

     * short value = Short.parseShort(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this {@code CharSeq} * @return the short value represented by this {@code CharSeq} in the specified radix * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable short. */ public short parseShort(int radix) { return Short.parseShort(back, radix); } /** * Converts this {@code CharSeq} to a {@code Boolean} by calling {@link Boolean#valueOf(String)}. *

* We write * *


     * Boolean value = charSeq.toBoolean();
     * 
* * instead of * *

     * Boolean value = Boolean.valueOf(charSeq.mkString());
     * 
* * @return the {@code Boolean} value represented by this {@code CharSeq} */ public Boolean toBoolean() { return Boolean.valueOf(back); } /** * Converts this {@code CharSeq} to a {@code Byte} by calling {@link Byte#valueOf(String)}. *

* We write * *


     * Byte value = charSeq.toByte();
     * 
* * instead of * *

     * Byte value = Byte.valueOf(charSeq.mkString());
     * 
* * @return a {@code Byte} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable byte. */ public Byte toByte() { return Byte.valueOf(back); } /** * Converts this {@code CharSeq} to a {@code Byte} in the specified radix * by calling {@link Byte#valueOf(String, int)}. *

* We write * *


     * Byte value = charSeq.toByte(radix);
     * 
* * instead of * *

     * Byte value = Byte.valueOf(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this char sequence * @return a {@code Byte} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable byte. */ public Byte toByte(int radix) { return Byte.valueOf(back, radix); } /** * Converts this {@code CharSeq} to a {@code Double} by calling {@link Double#valueOf(String)}. *

* We write * *


     * Double value = charSeq.toDouble();
     * 
* * instead of * *

     * Double value = Double.valueOf(charSeq.mkString());
     * 
* * @return a {@code Double} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable double. */ public Double toDouble() { return Double.valueOf(back); } /** * Converts this {@code CharSeq} to a {@code Float} by calling {@link Float#valueOf(String)}. *

* We write * *


     * Float value = charSeq.toFloat();
     * 
* * instead of * *

     * Float value = Float.valueOf(charSeq.mkString());
     * 
* * @return a {@code Float} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable float. */ public Float toFloat() { return Float.valueOf(back); } /** * Converts this {@code CharSeq} to an {@code Integer} by calling {@link Integer#valueOf(String)}. *

* We write * *


     * Integer value = charSeq.toInteger();
     * 
* * instead of * *

     * Integer value = Integer.valueOf(charSeq.mkString());
     * 
* * @return an {@code Integer} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable int. */ public Integer toInteger() { return Integer.valueOf(back); } /** * Converts this {@code CharSeq} to an {@code Integer} in the specified radix * by calling {@link Integer#valueOf(String, int)}. *

* We write * *


     * Integer value = charSeq.toInteger(radix);
     * 
* * instead of * *

     * Integer value = Integer.valueOf(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this char sequence * @return an {@code Integer} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable int. */ public Integer toInteger(int radix) { return Integer.valueOf(back, radix); } /** * Converts this {@code CharSeq} to a {@code Long} by calling {@link Long#valueOf(String)}. *

* We write * *


     * Long value = charSeq.toLong();
     * 
* * instead of * *

     * Long value = Long.valueOf(charSeq.mkString());
     * 
* * @return a {@code Long} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable long. */ public Long toLong() { return Long.valueOf(back); } /** * Converts this {@code CharSeq} to a {@code Long} in the specified radix * by calling {@link Long#valueOf(String, int)}. *

* We write * *


     * Long value = charSeq.toLong(radix);
     * 
* * instead of * *

     * Long value = Long.valueOf(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this char sequence * @return a {@code Long} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable long. */ public Long toLong(int radix) { return Long.valueOf(back, radix); } /** * Converts this {@code CharSeq} to a {@code Short} by calling {@link Short#valueOf(String)}. *

* We write * *


     * Short value = charSeq.toShort();
     * 
* * instead of * *

     * Short value = Short.valueOf(charSeq.mkString());
     * 
* * @return a {@code Short} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable short. */ public Short toShort() { return Short.valueOf(back); } /** * Converts this {@code CharSeq} to a {@code Short} in the specified radix * by calling {@link Short#valueOf(String, int)}. *

* We write * *


     * Short value = charSeq.toShort(radix);
     * 
* * instead of * *

     * Short value = Short.valueOf(charSeq.mkString(), radix);
     * 
* * @param radix the radix to be used in interpreting this char sequence * @return a {@code Short} object holding the value represented by this {@code CharSeq} * @throws NumberFormatException If this {@code CharSeq} does not contain a parsable short. */ public Short toShort(int radix) { return Short.valueOf(back, radix); } // -- conversion overrides @Override public Character[] toJavaArray() { return toJavaList().toArray(new Character[0]); } // -- functional interfaces @FunctionalInterface public interface CharUnaryOperator { char apply(char c); } @FunctionalInterface public interface CharFunction { R apply(char c); } } interface CharSeqModule { interface Combinations { static IndexedSeq apply(CharSeq elements, int k) { if (k == 0) { return Vector.of(CharSeq.empty()); } else { return elements.zipWithIndex().flatMap( t -> apply(elements.drop(t._2 + 1), (k - 1)).map((CharSeq c) -> c.prepend(t._1)) ); } } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Collections.java000066400000000000000000000513251342074374400250370ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.collection.JavaConverters.ChangePolicy; import io.vavr.collection.JavaConverters.ListView; import io.vavr.control.Option; import java.util.*; import java.util.function.*; import java.util.stream.Collector; /** * Internal class, containing helpers. * * @author Daniel Dietrich */ final class Collections { // checks, if the *elements* of the given iterables are equal static boolean areEqual(Iterable iterable1, Iterable iterable2) { final java.util.Iterator iter1 = iterable1.iterator(); final java.util.Iterator iter2 = iterable2.iterator(); while (iter1.hasNext() && iter2.hasNext()) { if (!Objects.equals(iter1.next(), iter2.next())) { return false; } } return iter1.hasNext() == iter2.hasNext(); } @GwtIncompatible static > C asJava(C source, Consumer> action, ChangePolicy changePolicy) { Objects.requireNonNull(action, "action is null"); final ListView view = JavaConverters.asJava(source, changePolicy); action.accept(view); return view.getDelegate(); } @SuppressWarnings("unchecked") static > Iterator crossProduct(S empty, S seq, int power) { if (power < 0) { return Iterator.empty(); } else { return Iterator.range(0, power) .foldLeft(Iterator.of(empty), (product, ignored) -> product.flatMap(el -> seq.map(t -> (S) el.append(t)))); } } // DEV-NOTE: Use this method for non-infinite and direct-access collection only // because of O(N) complexity of get() and infinite loop in size() // see https://github.com/vavr-io/vavr/issues/2007 @SuppressWarnings("unchecked") static > S dropRightUntil(S seq, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = seq.length() - 1; i >= 0; i--) { if (predicate.test(seq.get(i))) { return (S) seq.take(i + 1); } } return (S) seq.take(0); } // DEV-NOTE: Use this method for non-infinite and direct-access collection only // because of O(N) complexity of get() and infinite loop in size() // see https://github.com/vavr-io/vavr/issues/2007 @SuppressWarnings("unchecked") static > S dropUntil(S seq, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = 0; i < seq.length(); i++) { if (predicate.test(seq.get(i))) { return (S) seq.drop(i); } } return (S) seq.take(0); } @SuppressWarnings("unchecked") static boolean equals(Map source, Object object) { if (source == object) { return true; } else if (source != null && object instanceof Map) { final Map map = (Map) object; if (source.size() != map.size()) { return false; } else { try { return source.forAll(map::contains); } catch (ClassCastException e) { return false; } } } else { return false; } } @SuppressWarnings("unchecked") static boolean equals(Multimap source, Object object) { if (source == object) { return true; } else if (source != null && object instanceof Multimap) { final Multimap multimap = (Multimap) object; if (source.size() != multimap.size()) { return false; } else { try { return source.forAll(multimap::contains); } catch (ClassCastException e) { return false; } } } else { return false; } } @SuppressWarnings("unchecked") static boolean equals(Seq source, Object object) { if (object == source) { return true; } else if (source != null && object instanceof Seq) { final Seq seq = (Seq) object; return seq.size() == source.size() && areEqual(source, seq); } else { return false; } } @SuppressWarnings("unchecked") static boolean equals(Set source, Object object) { if (source == object) { return true; } else if (source != null && object instanceof Set) { final Set set = (Set) object; if (source.size() != set.size()) { return false; } else { try { return source.forAll(set::contains); } catch (ClassCastException e) { return false; } } } else { return false; } } static Iterator fill(int n, Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return tabulate(n, ignored -> supplier.get()); } static Iterator fillObject(int n, T element) { if (n <= 0) { return Iterator.empty(); } else { return Iterator.continually(element).take(n); } } static , T> C fill(int n, Supplier s, C empty, Function of) { Objects.requireNonNull(s, "s is null"); Objects.requireNonNull(empty, "empty is null"); Objects.requireNonNull(of, "of is null"); return tabulate(n, anything -> s.get(), empty, of); } static , T> C fillObject(int n, T element, C empty, Function of) { Objects.requireNonNull(empty, "empty is null"); Objects.requireNonNull(of, "of is null"); if (n <= 0) { return empty; } else { @SuppressWarnings("unchecked") final T[] elements = (T[]) new Object[n]; Arrays.fill(elements, element); return of.apply(elements); } } static > Map groupBy(Traversable source, Function classifier, Function, R> mapper) { Objects.requireNonNull(classifier, "classifier is null"); Objects.requireNonNull(mapper, "mapper is null"); Map results = LinkedHashMap.empty(); for (java.util.Map.Entry> entry : groupBy(source, classifier)) { results = results.put(entry.getKey(), mapper.apply(entry.getValue())); } return results; } private static java.util.Set>> groupBy(Traversable source, Function classifier) { final java.util.Map> results = new java.util.LinkedHashMap<>(source.isTraversableAgain() ? source.size() : 16); for (T value : source) { final C key = classifier.apply(value); results.computeIfAbsent(key, k -> new ArrayList<>()).add(value); } return results.entrySet(); } // hashes the elements respecting their order static int hashOrdered(Iterable iterable) { return hash(iterable, (acc, hash) -> acc * 31 + hash); } // hashes the elements regardless of their order static int hashUnordered(Iterable iterable) { return hash(iterable, (acc, hash) -> acc + hash); } private static int hash(Iterable iterable, IntBinaryOperator accumulator) { if (iterable == null) { return 0; } else { int hashCode = 1; for (Object o : iterable) { hashCode = accumulator.applyAsInt(hashCode, Objects.hashCode(o)); } return hashCode; } } static Option indexOption(int index) { return Option.when(index >= 0, index); } // @param iterable may not be null static boolean isEmpty(Iterable iterable) { return iterable instanceof Traversable && ((Traversable) iterable).isEmpty() || iterable instanceof Collection && ((Collection) iterable).isEmpty() || !iterable.iterator().hasNext(); } static boolean isTraversableAgain(Iterable iterable) { return (iterable instanceof Collection) || (iterable instanceof Traversable && ((Traversable) iterable).isTraversableAgain()); } static T last(Traversable source){ if (source.isEmpty()) { throw new NoSuchElementException("last of empty " + source.stringPrefix()); } else { final Iterator it = source.iterator(); T result = null; while (it.hasNext()) { result = it.next(); } return result; } } @SuppressWarnings("unchecked") static > U mapKeys(Map source, U zero, Function keyMapper, BiFunction valueMerge) { Objects.requireNonNull(zero, "zero is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMerge, "valueMerge is null"); return source.foldLeft(zero, (acc, entry) -> { final K2 k2 = keyMapper.apply(entry._1); final V v2 = entry._2; final Option v1 = acc.get(k2); final V v = v1.isDefined() ? valueMerge.apply(v1.get(), v2) : v2; return (U) acc.put(k2, v); }); } @SuppressWarnings("unchecked") static , T> C removeAll(C source, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (source.isEmpty()) { return source; } else { final Set removed = HashSet.ofAll(elements); return removed.isEmpty() ? source : (C) source.filter(e -> !removed.contains(e)); } } @SuppressWarnings("unchecked") static , T> C reject(C source, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (source.isEmpty()) { return source; } else { return (C) source.filter(predicate.negate()); } } @SuppressWarnings("unchecked") static , T> C removeAll(C source, T element) { if (source.isEmpty()) { return source; } else { return (C) source.filter(e -> !Objects.equals(e, element)); } } @SuppressWarnings("unchecked") static , T> C retainAll(C source, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (source.isEmpty()) { return source; } else { final Set retained = HashSet.ofAll(elements); return (C) source.filter(retained::contains); } } static Iterator reverseIterator(Iterable iterable) { if (iterable instanceof java.util.List) { return reverseListIterator((java.util.List) iterable); } else if (iterable instanceof Seq) { return ((Seq) iterable).reverseIterator(); } else { return List.empty().pushAll(iterable).iterator(); } } private static Iterator reverseListIterator(java.util.List list) { return new Iterator() { private final java.util.ListIterator delegate = list.listIterator(list.size()); @Override public boolean hasNext() { return delegate.hasPrevious(); } @Override public T next() { return delegate.previous(); } }; } @SuppressWarnings("unchecked") static > C rotateLeft(C source, int n) { if (source.isEmpty() || n == 0) { return source; } else if (n < 0) { return rotateRight(source, -n); } else { int len = source.length(); int m = n % len; if (m == 0) { return source; } else { return (C) source.drop(m).appendAll(source.take(m)); } } } @SuppressWarnings("unchecked") static > C rotateRight(C source, int n) { if (source.isEmpty() || n == 0) { return source; } else if (n < 0) { return rotateLeft(source, -n); } else { int len = source.length(); int m = n % len; if (m == 0) { return source; } else { return (C) source.takeRight(m).appendAll(source.dropRight(m)); } } } static > R scanLeft(Traversable source, U zero, BiFunction operation, Function, R> finisher) { Objects.requireNonNull(operation, "operation is null"); final Iterator iterator = source.iterator().scanLeft(zero, operation); return finisher.apply(iterator); } static > R scanRight(Traversable source, U zero, BiFunction operation, Function, R> finisher) { Objects.requireNonNull(operation, "operation is null"); final Iterator reversedElements = reverseIterator(source); return scanLeft(reversedElements, zero, (u, t) -> operation.apply(t, u), us -> finisher.apply(reverseIterator(us))); } static > R sortBy(Seq source, Comparator comparator, Function mapper, Collector collector) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(mapper, "mapper is null"); return source.toJavaStream() .sorted((e1, e2) -> comparator.compare(mapper.apply(e1), mapper.apply(e2))) .collect(collector); } static > S shuffle(S source, Function, S> ofAll) { if (source.length() <= 1) { return source; } final java.util.List list = source.toJavaList(); java.util.Collections.shuffle(list); return ofAll.apply(list); } static void subSequenceRangeCheck(int beginIndex, int endIndex, int length) { if (beginIndex < 0 || endIndex > length) { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ", " + endIndex + "), length = " + length); } else if (beginIndex > endIndex) { throw new IllegalArgumentException("subSequence(" + beginIndex + ", " + endIndex + ")"); } } static Iterator tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); if (n <= 0) { return Iterator.empty(); } else { return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < n; } @Override protected T getNext() { return f.apply(i++); } }; } } static , T> C tabulate(int n, Function f, C empty, Function of) { Objects.requireNonNull(f, "f is null"); Objects.requireNonNull(empty, "empty is null"); Objects.requireNonNull(of, "of is null"); if (n <= 0) { return empty; } else { @SuppressWarnings("unchecked") final T[] elements = (T[]) new Object[n]; for (int i = 0; i < n; i++) { elements[i] = f.apply(i); } return of.apply(elements); } } // DEV-NOTE: Use this method for non-infinite and direct-access collection only // because of O(N) complexity of get() and infinite loop in size() // see https://github.com/vavr-io/vavr/issues/2007 @SuppressWarnings("unchecked") static > S takeRightUntil(S seq, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = seq.length() - 1; i >= 0; i--) { if (predicate.test(seq.get(i))) { return (S) seq.drop(i + 1); } } return seq; } // DEV-NOTE: Use this method for non-infinite and direct-access collection only // because of O(N) complexity of get() and infinite loop in size() // see https://github.com/vavr-io/vavr/issues/2007 @SuppressWarnings("unchecked") static > S takeUntil(S seq, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = 0; i < seq.length(); i++) { if (predicate.test(seq.get(i))) { return (S) seq.take(i); } } return seq; } static , V extends Seq> V transpose(V matrix, Function, V> rowFactory, Function columnFactory) { Objects.requireNonNull(matrix, "matrix is null"); if (matrix.isEmpty() || (matrix.length() == 1 && matrix.head().length() <= 1)) { return matrix; } else { return transposeNonEmptyMatrix(matrix, rowFactory, columnFactory); } } private static , V extends Seq> V transposeNonEmptyMatrix(V matrix, Function, V> rowFactory, Function columnFactory) { final int newHeight = matrix.head().size(), newWidth = matrix.size(); @SuppressWarnings("unchecked") final T[][] results = (T[][]) new Object[newHeight][newWidth]; if (matrix.exists(r -> r.size() != newHeight)) { throw new IllegalArgumentException("the parameter `matrix` is invalid!"); } int rowIndex = 0; for (U row : matrix) { int columnIndex = 0; for (T element : row) { results[columnIndex][rowIndex] = element; columnIndex++; } rowIndex++; } return rowFactory.apply(Iterator.of(results).map(columnFactory)); } static IterableWithSize withSize(Iterable iterable) { return isTraversableAgain(iterable) ? withSizeTraversable(iterable) : withSizeTraversable(List.ofAll(iterable)); } private static IterableWithSize withSizeTraversable(Iterable iterable) { if (iterable instanceof Collection) { return new IterableWithSize<>(iterable, ((Collection) iterable).size()); } else { return new IterableWithSize<>(iterable, ((Traversable) iterable).size()); } } static class IterableWithSize { private final Iterable iterable; private final int size; IterableWithSize(Iterable iterable, int size) { this.iterable = iterable; this.size = size; } java.util.Iterator iterator() { return iterable.iterator(); } java.util.Iterator reverseIterator() { return Collections.reverseIterator(iterable); } int size() { return size; } Object[] toArray() { if (iterable instanceof Collection) { return ((Collection) iterable).toArray(); } else { return ArrayType.asArray(iterator(), size()); } } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Comparators.java000066400000000000000000000047001342074374400250460ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import java.io.Serializable; import java.util.Comparator; /** * INTERNAL: Common {@code Comparator} related functions (not intended to be public). * * @author Daniel Dietrich */ final class Comparators { private Comparators() { } /** * Returns the natural comparator for type U, i.e. treating it as {@code Comparable}. * The returned comparator is also {@code java.io.Serializable}. *

* Please note that this will lead to runtime exceptions, if U is not Comparable. * * @param The type * @return The natural Comparator of type U */ @SuppressWarnings("unchecked") static Comparator naturalComparator() { return NaturalComparator.instance(); } } final class NaturalComparator implements Comparator, Serializable { private static final long serialVersionUID = 1L; private static final NaturalComparator INSTANCE = new NaturalComparator<>(); private NaturalComparator() { } @SuppressWarnings("unchecked") static NaturalComparator instance() { return (NaturalComparator) INSTANCE; } @SuppressWarnings("unchecked") @Override public int compare(T o1, T o2) { return ((Comparable) o1).compareTo(o2); } /** @see Comparator#equals(Object) */ @Override public boolean equals(Object obj) { return obj instanceof NaturalComparator; } @Override public int hashCode() { return 1; } /** * Instance control for object serialization. * * @return The singleton instance of NaturalComparator. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Foldable.java000066400000000000000000000151521342074374400242670ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.control.Option; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.BiFunction; /** * Interface of foldable data structures. *

* Example: * *


 * // = "123"
 * Stream.of("1", "2", "3").fold("", (a1, a2) -> a1 + a2);
 * 
* * @param Component type of this foldable * @author Daniel Dietrich */ public interface Foldable { /** * Folds this elements using the given associative binary operator, starting with {@code zero} and * successively calling {@code combine}. The order in which the elements are combined is * non-deterministic. *

* The methods {@code fold}, {@code foldLeft} and {@code foldRight} differ in how the elements are combined: * *

    *
  • {@link #foldLeft(Object, BiFunction)} associates to the left
  • *
  • {@link #foldRight(Object, BiFunction)} associates to the right
  • *
  • * {@code fold} takes an associative combine operation because the traversal of elements is * unordered/non-deterministic. The associativity guarantees that in each case the result will * be the same, it does not matter in which order the elements are combined. Generally binary * operators aren't associative, i.e. the result may differ if elements are combined in a different * order. *

    * We say that this Foldable and the associative combine operation form a * Monoid. *

  • *
* * Example: * *
 {@code
     * // = 6
     * Set(1, 2, 3).fold(0, (a, b) -> a + b);
     * } 
* * @param zero A zero element to start with. * @param combine A function which combines elements. * @return a folded value * @throws NullPointerException if {@code combine} is null */ default T fold(T zero, BiFunction combine) { Objects.requireNonNull(combine, "combine is null"); return foldLeft(zero, combine); } /** * Folds this elements from the left, starting with {@code zero} and successively calling {@code combine}. *

* Example: * *

 {@code
     * // = "cba!"
     * List("a", "b", "c").foldLeft("!", (xs, x) -> x + xs)
     * } 
* * @param the type to fold over * @param zero A zero element to start with. * @param combine A function which combines elements. * @return a folded value * @throws NullPointerException if {@code combine} is null */ U foldLeft(U zero, BiFunction combine); /** * Folds this elements from the right, starting with {@code zero} and successively calling {@code combine}. *

* Example: * *

 {@code
     * // = "!cba"
     * List("a", "b", "c").foldRight("!", (x, xs) -> xs + x)
     * } 
* * @param the type of the folded value * @param zero A zero element to start with. * @param combine A function which combines elements. * @return a folded value * @throws NullPointerException if {@code combine} is null */ U foldRight(U zero, BiFunction combine); /** * Accumulates the elements of this Foldable by successively calling the given operation {@code op}. * The order of element iteration is undetermined. * * @param op A BiFunction of type T * @return the reduced value. * @throws NoSuchElementException if this is empty * @throws NullPointerException if {@code op} is null */ default T reduce(BiFunction op) { Objects.requireNonNull(op, "op is null"); return reduceLeft(op); } /** * Accumulates the elements of this Foldable by successively calling the given operation {@code op}. * The order of element iteration is undetermined. * * @param op A BiFunction of type T * @return Some of reduced value or None if the Foldable is empty. * @throws NullPointerException if {@code op} is null */ default Option reduceOption(BiFunction op) { Objects.requireNonNull(op, "op is null"); return reduceLeftOption(op); } /** * Accumulates the elements of this Foldable by successively calling the given operation {@code op} from the left. * * @param op A BiFunction of type T * @return the reduced value. * @throws NoSuchElementException if this is empty * @throws NullPointerException if {@code op} is null */ T reduceLeft(BiFunction op); /** * Accumulates the elements of this Foldable by successively calling the given operation {@code op} from the left. * * @param op A BiFunction of type T * @return Some of reduced value or None if the Foldable is empty. * @throws NullPointerException if {@code op} is null */ Option reduceLeftOption(BiFunction op); /** * Accumulates the elements of this Foldable by successively calling the given operation {@code op} from the right. * * @param op An operation of type T * @return the reduced value. * @throws NoSuchElementException if this is empty * @throws NullPointerException if {@code op} is null */ T reduceRight(BiFunction op); /** * Accumulates the elements of this Foldable by successively calling the given operation {@code op} from the right. * * @param op An operation of type T * @return Some of reduced value or None. * @throws NullPointerException if {@code op} is null */ Option reduceRightOption(BiFunction op); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/GwtIncompatible.java000066400000000000000000000017441342074374400256510ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import java.lang.annotation.*; @Retention(RetentionPolicy.CLASS) @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD }) @Documented @interface GwtIncompatible { String value() default ""; } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/HashArrayMappedTrie.java000066400000000000000000000612541342074374400264200ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.collection.HashArrayMappedTrieModule.EmptyNode; import io.vavr.control.Option; import java.io.Serializable; import java.util.Objects; import static java.lang.Integer.bitCount; import static java.util.Arrays.copyOf; import static io.vavr.collection.HashArrayMappedTrieModule.Action.PUT; import static io.vavr.collection.HashArrayMappedTrieModule.Action.REMOVE; /** * An immutable Hash array mapped trie (HAMT). * * @author Ruslan Sennov */ interface HashArrayMappedTrie extends Iterable> { static HashArrayMappedTrie empty() { return EmptyNode.instance(); } boolean isEmpty(); int size(); Option get(K key); V getOrElse(K key, V defaultValue); boolean containsKey(K key); HashArrayMappedTrie put(K key, V value); HashArrayMappedTrie remove(K key); @Override Iterator> iterator(); /** * Provide unboxed access to the keys in the trie. */ Iterator keysIterator(); /** * Provide unboxed access to the values in the trie. */ Iterator valuesIterator(); } interface HashArrayMappedTrieModule { enum Action { PUT, REMOVE } class LeafNodeIterator extends AbstractIterator> { // buckets levels + leaf level = (Integer.SIZE / AbstractNode.SIZE + 1) + 1 private final static int MAX_LEVELS = Integer.SIZE / AbstractNode.SIZE + 2; private final int total; private final Object[] nodes = new Object[MAX_LEVELS]; private final int[] indexes = new int[MAX_LEVELS]; private int level; private int ptr = 0; LeafNodeIterator(AbstractNode root) { total = root.size(); level = downstairs(nodes, indexes, root, 0); } @Override public boolean hasNext() { return ptr < total; } @SuppressWarnings("unchecked") @Override protected LeafNode getNext() { Object node = nodes[level]; while (!(node instanceof LeafNode)) { node = findNextLeaf(); } ptr++; if (node instanceof LeafList) { final LeafList leaf = (LeafList) node; nodes[level] = leaf.tail; return leaf; } else { nodes[level] = EmptyNode.instance(); return (LeafSingleton) node; } } @SuppressWarnings("unchecked") private Object findNextLeaf() { AbstractNode node = null; while (level > 0) { level--; indexes[level]++; node = getChild((AbstractNode) nodes[level], indexes[level]); if (node != null) { break; } } level = downstairs(nodes, indexes, node, level + 1); return nodes[level]; } private static int downstairs(Object[] nodes, int[] indexes, AbstractNode root, int level) { while (true) { nodes[level] = root; indexes[level] = 0; root = getChild(root, 0); if (root == null) { break; } else { level++; } } return level; } @SuppressWarnings("unchecked") private static AbstractNode getChild(AbstractNode node, int index) { if (node instanceof IndexedNode) { final Object[] subNodes = ((IndexedNode) node).subNodes; return index < subNodes.length ? (AbstractNode) subNodes[index] : null; } else if (node instanceof ArrayNode) { final ArrayNode arrayNode = (ArrayNode) node; return index < AbstractNode.BUCKET_SIZE ? (AbstractNode) arrayNode.subNodes[index] : null; } return null; } } /** * An abstract base class for nodes of a HAMT. * * @param Key type * @param Value type */ abstract class AbstractNode implements HashArrayMappedTrie { static final int SIZE = 5; static final int BUCKET_SIZE = 1 << SIZE; static final int MAX_INDEX_NODE = BUCKET_SIZE >> 1; static final int MIN_ARRAY_NODE = BUCKET_SIZE >> 2; static int hashFragment(int shift, int hash) { return (hash >>> shift) & (BUCKET_SIZE - 1); } static int toBitmap(int hash) { return 1 << hash; } static int fromBitmap(int bitmap, int bit) { return bitCount(bitmap & (bit - 1)); } static Object[] update(Object[] arr, int index, Object newElement) { final Object[] newArr = copyOf(arr, arr.length); newArr[index] = newElement; return newArr; } static Object[] remove(Object[] arr, int index) { final Object[] newArr = new Object[arr.length - 1]; System.arraycopy(arr, 0, newArr, 0, index); System.arraycopy(arr, index + 1, newArr, index, arr.length - index - 1); return newArr; } static Object[] insert(Object[] arr, int index, Object newElem) { final Object[] newArr = new Object[arr.length + 1]; System.arraycopy(arr, 0, newArr, 0, index); newArr[index] = newElem; System.arraycopy(arr, index, newArr, index + 1, arr.length - index); return newArr; } abstract Option lookup(int shift, int keyHash, K key); abstract V lookup(int shift, int keyHash, K key, V defaultValue); abstract AbstractNode modify(int shift, int keyHash, K key, V value, Action action); Iterator> nodes() { return new LeafNodeIterator<>(this); } @Override public Iterator> iterator() { return nodes().map(node -> Tuple.of(node.key(), node.value())); } @Override public Iterator keysIterator() { return nodes().map(LeafNode::key); } @Override public Iterator valuesIterator() { return nodes().map(LeafNode::value); } @Override public Option get(K key) { return lookup(0, Objects.hashCode(key), key); } @Override public V getOrElse(K key, V defaultValue) { return lookup(0, Objects.hashCode(key), key, defaultValue); } @Override public boolean containsKey(K key) { return get(key).isDefined(); } @Override public HashArrayMappedTrie put(K key, V value) { return modify(0, Objects.hashCode(key), key, value, PUT); } @Override public HashArrayMappedTrie remove(K key) { return modify(0, Objects.hashCode(key), key, null, REMOVE); } @Override public final String toString() { return iterator().map(t -> t._1 + " -> " + t._2).mkString("HashArrayMappedTrie(", ", ", ")"); } } /** * The empty node. * * @param Key type * @param Value type */ final class EmptyNode extends AbstractNode implements Serializable { private static final long serialVersionUID = 1L; private static final EmptyNode INSTANCE = new EmptyNode<>(); private EmptyNode() { } @SuppressWarnings("unchecked") static EmptyNode instance() { return (EmptyNode) INSTANCE; } @Override Option lookup(int shift, int keyHash, K key) { return Option.none(); } @Override V lookup(int shift, int keyHash, K key, V defaultValue) { return defaultValue; } @Override AbstractNode modify(int shift, int keyHash, K key, V value, Action action) { return (action == REMOVE) ? this : new LeafSingleton<>(keyHash, key, value); } @Override public boolean isEmpty() { return true; } @Override public int size() { return 0; } @Override public Iterator> nodes() { return Iterator.empty(); } /** * Instance control for object serialization. * * @return The singleton instance of EmptyNode. * @see Serializable */ private Object readResolve() { return INSTANCE; } } /** * Representation of a HAMT leaf. * * @param Key type * @param Value type */ abstract class LeafNode extends AbstractNode { abstract K key(); abstract V value(); abstract int hash(); static AbstractNode mergeLeaves(int shift, LeafNode leaf1, LeafSingleton leaf2) { final int h1 = leaf1.hash(); final int h2 = leaf2.hash(); if (h1 == h2) { return new LeafList<>(h1, leaf2.key(), leaf2.value(), leaf1); } final int subH1 = hashFragment(shift, h1); final int subH2 = hashFragment(shift, h2); final int newBitmap = toBitmap(subH1) | toBitmap(subH2); if (subH1 == subH2) { final AbstractNode newLeaves = mergeLeaves(shift + SIZE, leaf1, leaf2); return new IndexedNode<>(newBitmap, newLeaves.size(), new Object[] { newLeaves }); } else { return new IndexedNode<>(newBitmap, leaf1.size() + leaf2.size(), subH1 < subH2 ? new Object[] { leaf1, leaf2 } : new Object[] { leaf2, leaf1 }); } } @Override public boolean isEmpty() { return false; } } /** * Representation of a HAMT leaf node with single element. * * @param Key type * @param Value type */ final class LeafSingleton extends LeafNode implements Serializable { private static final long serialVersionUID = 1L; private final int hash; private final K key; private final V value; LeafSingleton(int hash, K key, V value) { this.hash = hash; this.key = key; this.value = value; } private boolean equals(int keyHash, K key) { return keyHash == hash && Objects.equals(key, this.key); } @Override Option lookup(int shift, int keyHash, K key) { return Option.when(equals(keyHash, key), value); } @Override V lookup(int shift, int keyHash, K key, V defaultValue) { return equals(keyHash, key) ? value : defaultValue; } @Override AbstractNode modify(int shift, int keyHash, K key, V value, Action action) { if (keyHash == hash && Objects.equals(key, this.key)) { return (action == REMOVE) ? EmptyNode.instance() : new LeafSingleton<>(hash, key, value); } else { return (action == REMOVE) ? this : mergeLeaves(shift, this, new LeafSingleton<>(keyHash, key, value)); } } @Override public int size() { return 1; } @Override public Iterator> nodes() { return Iterator.of(this); } @Override int hash() { return hash; } @Override K key() { return key; } @Override V value() { return value; } } /** * Representation of a HAMT leaf node with more than one element. * * @param Key type * @param Value type */ final class LeafList extends LeafNode implements Serializable { private static final long serialVersionUID = 1L; private final int hash; private final K key; private final V value; private final int size; private final LeafNode tail; LeafList(int hash, K key, V value, LeafNode tail) { this.hash = hash; this.key = key; this.value = value; this.size = 1 + tail.size(); this.tail = tail; } @Override Option lookup(int shift, int keyHash, K key) { if (hash != keyHash) { return Option.none(); } return nodes().find(node -> Objects.equals(node.key(), key)).map(LeafNode::value); } @Override V lookup(int shift, int keyHash, K key, V defaultValue) { if (hash != keyHash) { return defaultValue; } V result = defaultValue; final Iterator> iterator = nodes(); while (iterator.hasNext()) { final LeafNode node = iterator.next(); if (Objects.equals(node.key(), key)) { result = node.value(); break; } } return result; } @Override AbstractNode modify(int shift, int keyHash, K key, V value, Action action) { if (keyHash == hash) { final AbstractNode filtered = removeElement(key); if (action == REMOVE) { return filtered; } else { return new LeafList<>(hash, key, value, (LeafNode) filtered); } } else { return (action == REMOVE) ? this : mergeLeaves(shift, this, new LeafSingleton<>(keyHash, key, value)); } } private static AbstractNode mergeNodes(LeafNode leaf1, LeafNode leaf2) { if (leaf2 == null) { return leaf1; } if (leaf1 instanceof LeafSingleton) { return new LeafList<>(leaf1.hash(), leaf1.key(), leaf1.value(), leaf2); } if (leaf2 instanceof LeafSingleton) { return new LeafList<>(leaf2.hash(), leaf2.key(), leaf2.value(), leaf1); } LeafNode result = leaf1; LeafNode tail = leaf2; while (tail instanceof LeafList) { final LeafList list = (LeafList) tail; result = new LeafList<>(list.hash, list.key, list.value, result); tail = list.tail; } return new LeafList<>(tail.hash(), tail.key(), tail.value(), result); } private AbstractNode removeElement(K k) { if (Objects.equals(k, this.key)) { return tail; } LeafNode leaf1 = new LeafSingleton<>(hash, key, value); LeafNode leaf2 = tail; boolean found = false; while (!found && leaf2 != null) { if (Objects.equals(k, leaf2.key())) { found = true; } else { leaf1 = new LeafList<>(leaf2.hash(), leaf2.key(), leaf2.value(), leaf1); } leaf2 = leaf2 instanceof LeafList ? ((LeafList) leaf2).tail : null; } return mergeNodes(leaf1, leaf2); } @Override public int size() { return size; } @Override public Iterator> nodes() { return new AbstractIterator>() { LeafNode node = LeafList.this; @Override public boolean hasNext() { return node != null; } @Override public LeafNode getNext() { final LeafNode result = node; if (node instanceof LeafSingleton) { node = null; } else { node = ((LeafList) node).tail; } return result; } }; } @Override int hash() { return hash; } @Override K key() { return key; } @Override V value() { return value; } } /** * Representation of a HAMT indexed node. * * @param Key type * @param Value type */ final class IndexedNode extends AbstractNode implements Serializable { private static final long serialVersionUID = 1L; private final int bitmap; private final int size; private final Object[] subNodes; IndexedNode(int bitmap, int size, Object[] subNodes) { this.bitmap = bitmap; this.size = size; this.subNodes = subNodes; } @SuppressWarnings("unchecked") @Override Option lookup(int shift, int keyHash, K key) { final int frag = hashFragment(shift, keyHash); final int bit = toBitmap(frag); if ((bitmap & bit) != 0) { final AbstractNode n = (AbstractNode) subNodes[fromBitmap(bitmap, bit)]; return n.lookup(shift + SIZE, keyHash, key); } else { return Option.none(); } } @SuppressWarnings("unchecked") @Override V lookup(int shift, int keyHash, K key, V defaultValue) { final int frag = hashFragment(shift, keyHash); final int bit = toBitmap(frag); if ((bitmap & bit) != 0) { final AbstractNode n = (AbstractNode) subNodes[fromBitmap(bitmap, bit)]; return n.lookup(shift + SIZE, keyHash, key, defaultValue); } else { return defaultValue; } } @SuppressWarnings("unchecked") @Override AbstractNode modify(int shift, int keyHash, K key, V value, Action action) { final int frag = hashFragment(shift, keyHash); final int bit = toBitmap(frag); final int index = fromBitmap(bitmap, bit); final int mask = bitmap; final boolean exists = (mask & bit) != 0; final AbstractNode atIndx = exists ? (AbstractNode) subNodes[index] : null; final AbstractNode child = exists ? atIndx.modify(shift + SIZE, keyHash, key, value, action) : EmptyNode. instance().modify(shift + SIZE, keyHash, key, value, action); final boolean removed = exists && child.isEmpty(); final boolean added = !exists && !child.isEmpty(); final int newBitmap = removed ? mask & ~bit : added ? mask | bit : mask; if (newBitmap == 0) { return EmptyNode.instance(); } else if (removed) { if (subNodes.length <= 2 && subNodes[index ^ 1] instanceof LeafNode) { return (AbstractNode) subNodes[index ^ 1]; // collapse } else { return new IndexedNode<>(newBitmap, size - atIndx.size(), remove(subNodes, index)); } } else if (added) { if (subNodes.length >= MAX_INDEX_NODE) { return expand(frag, child, mask, subNodes); } else { return new IndexedNode<>(newBitmap, size + child.size(), insert(subNodes, index, child)); } } else { if (!exists) { return this; } else { return new IndexedNode<>(newBitmap, size - atIndx.size() + child.size(), update(subNodes, index, child)); } } } private ArrayNode expand(int frag, AbstractNode child, int mask, Object[] subNodes) { int bit = mask; int count = 0; int ptr = 0; final Object[] arr = new Object[BUCKET_SIZE]; for (int i = 0; i < BUCKET_SIZE; i++) { if ((bit & 1) != 0) { arr[i] = subNodes[ptr++]; count++; } else if (i == frag) { arr[i] = child; count++; } else { arr[i] = EmptyNode.instance(); } bit = bit >>> 1; } return new ArrayNode<>(count, size + child.size(), arr); } @Override public boolean isEmpty() { return false; } @Override public int size() { return size; } } /** * Representation of a HAMT array node. * * @param Key type * @param Value type */ final class ArrayNode extends AbstractNode implements Serializable { private static final long serialVersionUID = 1L; private final Object[] subNodes; private final int count; private final int size; ArrayNode(int count, int size, Object[] subNodes) { this.subNodes = subNodes; this.count = count; this.size = size; } @SuppressWarnings("unchecked") @Override Option lookup(int shift, int keyHash, K key) { final int frag = hashFragment(shift, keyHash); final AbstractNode child = (AbstractNode) subNodes[frag]; return child.lookup(shift + SIZE, keyHash, key); } @SuppressWarnings("unchecked") @Override V lookup(int shift, int keyHash, K key, V defaultValue) { final int frag = hashFragment(shift, keyHash); final AbstractNode child = (AbstractNode) subNodes[frag]; return child.lookup(shift + SIZE, keyHash, key, defaultValue); } @SuppressWarnings("unchecked") @Override AbstractNode modify(int shift, int keyHash, K key, V value, Action action) { final int frag = hashFragment(shift, keyHash); final AbstractNode child = (AbstractNode) subNodes[frag]; final AbstractNode newChild = child.modify(shift + SIZE, keyHash, key, value, action); if (child.isEmpty() && !newChild.isEmpty()) { return new ArrayNode<>(count + 1, size + newChild.size(), update(subNodes, frag, newChild)); } else if (!child.isEmpty() && newChild.isEmpty()) { if (count - 1 <= MIN_ARRAY_NODE) { return pack(frag, subNodes); } else { return new ArrayNode<>(count - 1, size - child.size(), update(subNodes, frag, EmptyNode.instance())); } } else { return new ArrayNode<>(count, size - child.size() + newChild.size(), update(subNodes, frag, newChild)); } } @SuppressWarnings("unchecked") private IndexedNode pack(int idx, Object[] elements) { final Object[] arr = new Object[count - 1]; int bitmap = 0; int size = 0; int ptr = 0; for (int i = 0; i < BUCKET_SIZE; i++) { final AbstractNode elem = (AbstractNode) elements[i]; if (i != idx && !elem.isEmpty()) { size += elem.size(); arr[ptr++] = elem; bitmap = bitmap | (1 << i); } } return new IndexedNode<>(bitmap, size, arr); } @Override public boolean isEmpty() { return false; } @Override public int size() { return size; } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/HashMap.java000066400000000000000000001011721342074374400240760ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.*; import java.util.stream.Collector; /** * An immutable {@code HashMap} implementation based on a * Hash array mapped trie (HAMT). * * @author Ruslan Sennov, Patryk Najda, Daniel Dietrich */ public final class HashMap implements Map, Serializable { private static final long serialVersionUID = 1L; private static final HashMap EMPTY = new HashMap<>(HashArrayMappedTrie.empty()); private final HashArrayMappedTrie trie; private HashMap(HashArrayMappedTrie trie) { this.trie = trie; } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link HashMap}. * * @param The key type * @param The value type * @return A {@link HashMap} Collector. */ public static Collector, ArrayList>, HashMap> collector() { final Supplier>> supplier = ArrayList::new; final BiConsumer>, Tuple2> accumulator = ArrayList::add; final BinaryOperator>> combiner = (left, right) -> { left.addAll(right); return left; }; final Function>, HashMap> finisher = HashMap::ofEntries; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link HashMap}. * * @param keyMapper The key mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @return A {@link HashMap} Collector. */ public static Collector, HashMap> collector(Function keyMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); return HashMap.collector(keyMapper, v -> v); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link HashMap}. * * @param keyMapper The key mapper * @param valueMapper The value mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @return A {@link HashMap} Collector. */ public static Collector, HashMap> collector( Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, HashMap> finisher = arr -> HashMap.ofEntries(Iterator.ofAll(arr) .map(t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t)))); return Collector.of(supplier, accumulator, combiner, finisher); } @SuppressWarnings("unchecked") public static HashMap empty() { return (HashMap) EMPTY; } /** * Narrows a widened {@code HashMap} to {@code HashMap} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param hashMap A {@code HashMap}. * @param Key type * @param Value type * @return the given {@code hashMap} instance as narrowed type {@code HashMap}. */ @SuppressWarnings("unchecked") public static HashMap narrow(HashMap hashMap) { return (HashMap) hashMap; } /** * Returns a singleton {@code HashMap}, i.e. a {@code HashMap} of one element. * * @param entry A map entry. * @param The key type * @param The value type * @return A new Map containing the given entry */ public static HashMap of(Tuple2 entry) { return new HashMap<>(HashArrayMappedTrie. empty().put(entry._1, entry._2)); } /** * Returns a {@code HashMap}, from a source java.util.Map. * * @param map A map * @param The key type * @param The value type * @return A new Map containing the given map */ public static HashMap ofAll(java.util.Map map) { Objects.requireNonNull(map, "map is null"); HashArrayMappedTrie tree = HashArrayMappedTrie.empty(); for (java.util.Map.Entry entry : map.entrySet()) { tree = tree.put(entry.getKey(), entry.getValue()); } return wrap(tree); } /** * Returns a {@code HashMap}, from entries mapped from stream. * * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static HashMap ofAll(java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Maps.ofStream(empty(), stream, keyMapper, valueMapper); } /** * Returns a {@code HashMap}, from entries mapped from stream. * * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static HashMap ofAll(java.util.stream.Stream stream, Function> entryMapper) { return Maps.ofStream(empty(), stream, entryMapper); } /** * Returns a singleton {@code HashMap}, i.e. a {@code HashMap} of one element. * * @param key A singleton map key. * @param value A singleton map value. * @param The key type * @param The value type * @return A new Map containing the given entry */ public static HashMap of(K key, V value) { return new HashMap<>(HashArrayMappedTrie. empty().put(key, value)); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2) { return of(k1, v1).put(k2, v2); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3) { return of(k1, v1, k2, v2).put(k3, v3); } /** * Creates a HashMap of the given list of key-value pairs. * * @param The key type * @param The value type * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return of(k1, v1, k2, v2, k3, v3).put(k4, v4); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return of(k1, v1, k2, v2, k3, v3, k4, v4).put(k5, v5); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5).put(k6, v6); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6).put(k7, v7); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7).put(k8, v8); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8).put(k9, v9); } /** * Creates a HashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9).put(k10, v10); } /** * Returns an HashMap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param The key type * @param The value type * @param n The number of elements in the HashMap * @param f The Function computing element values * @return An HashMap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ @SuppressWarnings("unchecked") public static HashMap tabulate(int n, Function> f) { Objects.requireNonNull(f, "f is null"); return ofEntries(Collections.tabulate(n, (Function>) f)); } /** * Returns a HashMap containing tuples returned by {@code n} calls to a given Supplier {@code s}. * * @param The key type * @param The value type * @param n The number of elements in the HashMap * @param s The Supplier computing element values * @return An HashMap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ @SuppressWarnings("unchecked") public static HashMap fill(int n, Supplier> s) { Objects.requireNonNull(s, "s is null"); return ofEntries(Collections.fill(n, (Supplier>) s)); } /** * Creates a HashMap of the given entries. * * @param entries Map entries * @param The key type * @param The value type * @return A new Map containing the given entries */ @SafeVarargs public static HashMap ofEntries(java.util.Map.Entry... entries) { Objects.requireNonNull(entries, "entries is null"); HashArrayMappedTrie trie = HashArrayMappedTrie.empty(); for (java.util.Map.Entry entry : entries) { trie = trie.put(entry.getKey(), entry.getValue()); } return wrap(trie); } /** * Creates a HashMap of the given entries. * * @param entries Map entries * @param The key type * @param The value type * @return A new Map containing the given entries */ @SafeVarargs public static HashMap ofEntries(Tuple2... entries) { Objects.requireNonNull(entries, "entries is null"); HashArrayMappedTrie trie = HashArrayMappedTrie.empty(); for (Tuple2 entry : entries) { trie = trie.put(entry._1, entry._2); } return wrap(trie); } /** * Creates a HashMap of the given entries. * * @param entries Map entries * @param The key type * @param The value type * @return A new Map containing the given entries */ @SuppressWarnings("unchecked") public static HashMap ofEntries(Iterable> entries) { Objects.requireNonNull(entries, "entries is null"); if (entries instanceof HashMap) { return (HashMap) entries; } else { HashArrayMappedTrie trie = HashArrayMappedTrie.empty(); for (Tuple2 entry : entries) { trie = trie.put(entry._1, entry._2); } return trie.isEmpty() ? empty() : wrap(trie); } } @Override public HashMap bimap(Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); final Iterator> entries = iterator().map(entry -> Tuple.of(keyMapper.apply(entry._1), valueMapper.apply(entry._2))); return HashMap.ofEntries(entries); } @Override public Tuple2> computeIfAbsent(K key, Function mappingFunction) { return Maps.computeIfAbsent(this, key, mappingFunction); } @Override public Tuple2, HashMap> computeIfPresent(K key, BiFunction remappingFunction) { return Maps.computeIfPresent(this, key, remappingFunction); } @Override public boolean containsKey(K key) { return trie.containsKey(key); } @Override public HashMap distinct() { return Maps.distinct(this); } @Override public HashMap distinctBy(Comparator> comparator) { return Maps.distinctBy(this, this::createFromEntries, comparator); } @Override public HashMap distinctBy(Function, ? extends U> keyExtractor) { return Maps.distinctBy(this, this::createFromEntries, keyExtractor); } @Override public HashMap drop(int n) { return Maps.drop(this, this::createFromEntries, HashMap::empty, n); } @Override public HashMap dropRight(int n) { return Maps.dropRight(this, this::createFromEntries, HashMap::empty, n); } @Override public HashMap dropUntil(Predicate> predicate) { return Maps.dropUntil(this, this::createFromEntries, predicate); } @Override public HashMap dropWhile(Predicate> predicate) { return Maps.dropWhile(this, this::createFromEntries, predicate); } @Override public HashMap filter(BiPredicate predicate) { return Maps.filter(this, this::createFromEntries, predicate); } @Override public HashMap reject(BiPredicate predicate) { return Maps.reject(this, this::createFromEntries, predicate); } @Override public HashMap filter(Predicate> predicate) { return Maps.filter(this, this::createFromEntries, predicate); } @Override public HashMap reject(Predicate> predicate) { return Maps.reject(this, this::createFromEntries, predicate); } @Override public HashMap filterKeys(Predicate predicate) { return Maps.filterKeys(this, this::createFromEntries, predicate); } @Override public HashMap rejectKeys(Predicate predicate) { return Maps.rejectKeys(this, this::createFromEntries, predicate); } @Override public HashMap filterValues(Predicate predicate) { return Maps.filterValues(this, this::createFromEntries, predicate); } @Override public HashMap rejectValues(Predicate predicate) { return Maps.rejectValues(this, this::createFromEntries, predicate); } @Override public HashMap flatMap(BiFunction>> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return foldLeft(HashMap. empty(), (acc, entry) -> { for (Tuple2 mappedEntry : mapper.apply(entry._1, entry._2)) { acc = acc.put(mappedEntry); } return acc; }); } @Override public Option get(K key) { return trie.get(key); } @Override public V getOrElse(K key, V defaultValue) { return trie.getOrElse(key, defaultValue); } @Override public Map> groupBy(Function, ? extends C> classifier) { return Maps.groupBy(this, this::createFromEntries, classifier); } @Override public Iterator> grouped(int size) { return Maps.grouped(this, this::createFromEntries, size); } @Override public Tuple2 head() { if (isEmpty()) { throw new NoSuchElementException("head of empty HashMap"); } else { return iterator().next(); } } @Override public HashMap init() { if (trie.isEmpty()) { throw new UnsupportedOperationException("init of empty HashMap"); } else { return remove(last()._1); } } @Override public Option> initOption() { return Maps.initOption(this); } /** * A {@code HashMap} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return trie.isEmpty(); } /** * A {@code HashMap} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public Iterator> iterator() { return trie.iterator(); } @Override public Set keySet() { return HashSet.ofAll(iterator().map(Tuple2::_1)); } @Override public Iterator keysIterator() { return trie.keysIterator(); } @Override public Tuple2 last() { return Collections.last(this); } @Override public HashMap map(BiFunction> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return foldLeft(HashMap.empty(), (acc, entry) -> acc.put(entry.map(mapper))); } @Override public HashMap mapKeys(Function keyMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); return map((k, v) -> Tuple.of(keyMapper.apply(k), v)); } @Override public HashMap mapKeys(Function keyMapper, BiFunction valueMerge) { return Collections.mapKeys(this, HashMap.empty(), keyMapper, valueMerge); } @Override public HashMap mapValues(Function valueMapper) { Objects.requireNonNull(valueMapper, "valueMapper is null"); return map((k, v) -> Tuple.of(k, valueMapper.apply(v))); } @Override public HashMap merge(Map that) { return Maps.merge(this, this::createFromEntries, that); } @Override public HashMap merge(Map that, BiFunction collisionResolution) { return Maps.merge(this, this::createFromEntries, that, collisionResolution); } @Override public HashMap orElse(Iterable> other) { return isEmpty() ? ofEntries(other) : this; } @Override public HashMap orElse(Supplier>> supplier) { return isEmpty() ? ofEntries(supplier.get()) : this; } @Override public Tuple2, HashMap> partition(Predicate> predicate) { return Maps.partition(this, this::createFromEntries, predicate); } @Override public HashMap peek(Consumer> action) { return Maps.peek(this, action); } @Override public HashMap put(K key, U value, BiFunction merge) { return Maps.put(this, key, value, merge); } @Override public HashMap put(K key, V value) { return new HashMap<>(trie.put(key, value)); } @Override public HashMap put(Tuple2 entry) { return Maps.put(this, entry); } @Override public HashMap put(Tuple2 entry, BiFunction merge) { return Maps.put(this, entry, merge); } @Override public HashMap remove(K key) { final HashArrayMappedTrie result = trie.remove(key); return result.size() == trie.size() ? this : wrap(result); } @Override @Deprecated public HashMap removeAll(BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override public HashMap removeAll(Iterable keys) { Objects.requireNonNull(keys, "keys is null"); HashArrayMappedTrie result = trie; for (K key : keys) { result = result.remove(key); } if (result.isEmpty()) { return empty(); } else if (result.size() == trie.size()) { return this; } else { return wrap(result); } } @Override @Deprecated public HashMap removeKeys(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectKeys(predicate); } @Override @Deprecated public HashMap removeValues(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectValues(predicate); } @Override public HashMap replace(Tuple2 currentElement, Tuple2 newElement) { return Maps.replace(this, currentElement, newElement); } @Override public HashMap replaceAll(Tuple2 currentElement, Tuple2 newElement) { return Maps.replaceAll(this, currentElement, newElement); } @Override public HashMap replaceValue(K key, V value) { return Maps.replaceValue(this, key, value); } @Override public HashMap replace(K key, V oldValue, V newValue) { return Maps.replace(this, key, oldValue, newValue); } @Override public HashMap replaceAll(BiFunction function) { return Maps.replaceAll(this, function); } @Override public HashMap retainAll(Iterable> elements) { Objects.requireNonNull(elements, "elements is null"); HashArrayMappedTrie tree = HashArrayMappedTrie.empty(); for (Tuple2 entry : elements) { if (contains(entry)) { tree = tree.put(entry._1, entry._2); } } return wrap(tree); } @Override public HashMap scan( Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation) { return Maps.scan(this, zero, operation, this::createFromEntries); } @Override public int size() { return trie.size(); } @Override public Iterator> slideBy(Function, ?> classifier) { return Maps.slideBy(this, this::createFromEntries, classifier); } @Override public Iterator> sliding(int size) { return Maps.sliding(this, this::createFromEntries, size); } @Override public Iterator> sliding(int size, int step) { return Maps.sliding(this, this::createFromEntries, size, step); } @Override public Tuple2, HashMap> span(Predicate> predicate) { return Maps.span(this, this::createFromEntries, predicate); } @Override public HashMap tail() { if (trie.isEmpty()) { throw new UnsupportedOperationException("tail of empty HashMap"); } else { return remove(head()._1); } } @Override public Option> tailOption() { return Maps.tailOption(this); } @Override public HashMap take(int n) { return Maps.take(this, this::createFromEntries, n); } @Override public HashMap takeRight(int n) { return Maps.takeRight(this, this::createFromEntries, n); } @Override public HashMap takeUntil(Predicate> predicate) { return Maps.takeUntil(this, this::createFromEntries, predicate); } @Override public HashMap takeWhile(Predicate> predicate) { return Maps.takeWhile(this, this::createFromEntries, predicate); } @Override public java.util.HashMap toJavaMap() { return toJavaMap(java.util.HashMap::new, t -> t); } @Override public Stream values() { return trie.valuesIterator().toStream(); } @Override public Iterator valuesIterator() { return trie.valuesIterator(); } @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } private Object readResolve() { return isEmpty() ? EMPTY : this; } @Override public String stringPrefix() { return "HashMap"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } private static HashMap wrap(HashArrayMappedTrie trie) { return trie.isEmpty() ? empty() : new HashMap<>(trie); } // We need this method to narrow the argument of `ofEntries`. // If this method is static with type args , the jdk fails to infer types at the call site. private HashMap createFromEntries(Iterable> tuples) { return HashMap.ofEntries(tuples); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/HashMultimap.java000066400000000000000000000513151342074374400251540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple2; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; /** * A {@link HashMap}-based implementation of {@link Multimap} * * @param Key type * @param Value type * @author Ruslan Sennov */ public final class HashMultimap extends AbstractMultimap> implements Serializable { private static final long serialVersionUID = 1L; public static Builder withSeq() { return new Builder<>(ContainerType.SEQ, List::empty); } public static Builder withSet() { return new Builder<>(ContainerType.SET, HashSet::empty); } public static > Builder withSortedSet() { return new Builder<>(ContainerType.SORTED_SET, TreeSet::empty); } public static Builder withSortedSet(Comparator comparator) { return new Builder<>(ContainerType.SORTED_SET, () -> TreeSet.empty(comparator)); } public static class Builder { private final ContainerType containerType; private final SerializableSupplier> emptyContainer; private Builder(ContainerType containerType, SerializableSupplier> emptyContainer) { this.containerType = containerType; this.emptyContainer = emptyContainer; } /** * Returns the empty {@code HashMultimap}. * * @param The key type * @param The value type * @return A new empty HashMultimap. */ public HashMultimap empty() { return new HashMultimap<>(HashMap.empty(), containerType, emptyContainer); } /** * Creates a {@code HashMultimap} of the given entries. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new HashMultimap containing the given entries. */ public HashMultimap ofEntries(Iterable> entries) { Objects.requireNonNull(entries, "entries is null"); HashMultimap result = empty(); for (Tuple2 entry : entries) { result = result.put(entry._1, entry._2); } return result; } /** * Creates a {@code HashMultimap} of the given entries. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new HashMultimap containing the given entries. */ @SafeVarargs public final HashMultimap ofEntries(Tuple2... entries) { Objects.requireNonNull(entries, "entries is null"); HashMultimap result = empty(); for (Tuple2 entry : entries) { result = result.put(entry._1, entry._2); } return result; } /** * Creates a {@code HashMultimap} of the given entries. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new HashMultimap containing the given entries. */ @SafeVarargs public final HashMultimap ofEntries(java.util.Map.Entry... entries) { Objects.requireNonNull(entries, "entries is null"); HashMultimap result = empty(); for (java.util.Map.Entry entry : entries) { result = result.put(entry.getKey(), entry.getValue()); } return result; } /** * Returns a {@code HashMultimap}, from a source java.util.Map. * * @param map A map * @param The key type * @param The value type * @return A new Multimap containing the given map entries */ public HashMultimap ofAll(java.util.Map map) { return Multimaps.ofJavaMap(empty(), map); } /** * Returns a {@code HashMultimap}, from entries mapped from stream. * * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Multimap */ public HashMultimap ofAll(java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Multimaps.ofStream(empty(), stream, keyMapper, valueMapper); } /** * Returns a {@code HashMultimap}, from entries mapped from stream. * * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new HashMultimap */ public HashMultimap ofAll(java.util.stream.Stream stream, Function> entryMapper) { return Multimaps.ofStream(empty(), stream, entryMapper); } /** * Returns a HashMultimap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param The key type * @param The value type * @param n The number of elements in the HashMultimap * @param f The Function computing element values * @return A HashMultimap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ @SuppressWarnings("unchecked") public HashMultimap tabulate(int n, Function> f) { Objects.requireNonNull(f, "f is null"); return ofEntries(Collections.tabulate(n, (Function>) f)); } /** * Returns a HashMultimap containing {@code n} values supplied by a given Supplier {@code s}. * * @param The key type * @param The value type * @param n The number of elements in the HashMultimap * @param s The Supplier computing element values * @return A HashMultimap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ @SuppressWarnings("unchecked") public HashMultimap fill(int n, Supplier> s) { Objects.requireNonNull(s, "s is null"); return ofEntries(Collections.fill(n, (Supplier>) s)); } /** * Returns a HashMultimap containing {@code n} times the given {@code element} * * @param The key type * @param The value type * @param n The number of elements in the HashMultimap * @param element The element * @return A HashMultimap of size {@code 1}, where each element contains {@code n} values of {@code element._2}. */ @SuppressWarnings("unchecked") public HashMultimap fill(int n, Tuple2 element) { return ofEntries(Collections.fillObject(n, element)); } /** * Creates a HashMultimap of the given key-value pair. * * @param key a key for the map * @param value the value for key * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K key, V2 value) { final HashMultimap e = empty(); return e.put(key, value); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2) { return of(k1, v1).put(k2, v2); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3) { return of(k1, v1, k2, v2).put(k3, v3); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4) { return of(k1, v1, k2, v2, k3, v3).put(k4, v4); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5) { return of(k1, v1, k2, v2, k3, v3, k4, v4).put(k5, v5); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5).put(k6, v6); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6).put(k7, v7); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7).put(k8, v8); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8).put(k9, v9); } /** * Creates a HashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public HashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9, K k10, V2 v10) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9).put(k10, v10); } /** * Creates a HashMultimap of the given key-value pair. * Returns a singleton {@code HashMultimap}, i.e. a {@code HashMultimap} of one entry. * * @param The key type * @param The value type * @param entry A tuple containing the key-value pair. * @return A new HashMultimap containing the given entry. */ public HashMultimap of(Tuple2 entry) { final HashMultimap e = empty(); return e.put(entry._1, entry._2); } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a * {@link HashMultimap}. * * @param The key type * @param The value type * @return A {@link HashMultimap} Collector. */ public Collector, ArrayList>, Multimap> collector() { final Supplier>> supplier = ArrayList::new; final BiConsumer>, Tuple2> accumulator = ArrayList::add; final BinaryOperator>> combiner = (left, right) -> { left.addAll(right); return left; }; return Collector.of(supplier, accumulator, combiner, this::ofEntries); } } /** * Narrows a widened {@code HashMultimap} to {@code HashMultimap} * by performing a type safe-cast. This is eligible because immutable/read-only * collections are covariant. * * @param map A {@code Map}. * @param Key type * @param Value type * @return the given {@code multimap} instance as narrowed type {@code Multimap}. */ @SuppressWarnings("unchecked") public static HashMultimap narrow(HashMultimap map) { return (HashMultimap) map; } private HashMultimap(Map> back, ContainerType containerType, SerializableSupplier> emptyContainer) { super(back, containerType, emptyContainer); } @Override protected Map emptyMapSupplier() { return HashMap.empty(); } @SuppressWarnings("unchecked") @Override protected HashMultimap emptyInstance() { return new HashMultimap<>(HashMap.empty(), getContainerType(), emptyContainer); } @Override protected HashMultimap createFromMap(Map> back) { return new HashMultimap<>(back, getContainerType(), emptyContainer); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/HashSet.java000066400000000000000000001074371342074374400241260ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.io.*; import java.util.ArrayList; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.*; import java.util.stream.Collector; /** * An immutable {@code HashSet} implementation. * * @param Component type * @author Ruslan Sennov, Patryk Najda, Daniel Dietrich */ public final class HashSet implements Set, Serializable { private static final long serialVersionUID = 1L; private static final HashSet EMPTY = new HashSet<>(HashArrayMappedTrie.empty()); private final HashArrayMappedTrie tree; private HashSet(HashArrayMappedTrie tree) { this.tree = tree; } @SuppressWarnings("unchecked") public static HashSet empty() { return (HashSet) EMPTY; } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link HashSet}. * * @param Component type of the HashSet. * @return A io.vavr.collection.HashSet Collector. */ public static Collector, HashSet> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, HashSet> finisher = HashSet::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Narrows a widened {@code HashSet} to {@code HashSet} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param hashSet A {@code HashSet}. * @param Component type of the {@code HashSet}. * @return the given {@code hashSet} instance as narrowed type {@code HashSet}. */ @SuppressWarnings("unchecked") public static HashSet narrow(HashSet hashSet) { return (HashSet) hashSet; } /** * Returns a singleton {@code HashSet}, i.e. a {@code HashSet} of one element. * * @param element An element. * @param The component type * @return A new HashSet instance containing the given element */ public static HashSet of(T element) { return HashSet. empty().add(element); } /** * Creates a HashSet of the given elements. * *
HashSet.of(1, 2, 3, 4)
* * @param Component type of the HashSet. * @param elements Zero or more elements. * @return A set containing the given elements. * @throws NullPointerException if {@code elements} is null */ @SafeVarargs public static HashSet of(T... elements) { Objects.requireNonNull(elements, "elements is null"); HashArrayMappedTrie tree = HashArrayMappedTrie.empty(); for (T element : elements) { tree = tree.put(element, element); } return tree.isEmpty() ? empty() : new HashSet<>(tree); } /** * Returns an HashSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the HashSet * @param n The number of elements in the HashSet * @param f The Function computing element values * @return An HashSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static HashSet tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f, HashSet.empty(), HashSet::of); } /** * Returns a HashSet containing tuples returned by {@code n} calls to a given Supplier {@code s}. * * @param Component type of the HashSet * @param n The number of elements in the HashSet * @param s The Supplier computing element values * @return An HashSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static HashSet fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s, HashSet.empty(), HashSet::of); } /** * Creates a HashSet of the given elements. * * @param elements Set elements * @param The value type * @return A new HashSet containing the given entries */ @SuppressWarnings("unchecked") public static HashSet ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof HashSet) { return (HashSet) elements; } else { final HashArrayMappedTrie tree = addAll(HashArrayMappedTrie.empty(), elements); return tree.isEmpty() ? empty() : new HashSet<>(tree); } } /** * Creates a HashSet that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return A HashSet containing the given elements in the same order. */ public static HashSet ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return HashSet.ofAll(Iterator.ofAll(javaStream.iterator())); } /** * Creates a HashSet from boolean values. * * @param elements boolean values * @return A new HashSet of Boolean values * @throws NullPointerException if elements is null */ public static HashSet ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet from byte values. * * @param elements byte values * @return A new HashSet of Byte values * @throws NullPointerException if elements is null */ public static HashSet ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet from char values. * * @param elements char values * @return A new HashSet of Character values * @throws NullPointerException if elements is null */ public static HashSet ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet from double values. * * @param elements double values * @return A new HashSet of Double values * @throws NullPointerException if elements is null */ public static HashSet ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet from float values. * * @param elements float values * @return A new HashSet of Float values * @throws NullPointerException if elements is null */ public static HashSet ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet from int values. * * @param elements int values * @return A new HashSet of Integer values * @throws NullPointerException if elements is null */ public static HashSet ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet from long values. * * @param elements long values * @return A new HashSet of Long values * @throws NullPointerException if elements is null */ public static HashSet ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet from short values. * * @param elements short values * @return A new HashSet of Short values * @throws NullPointerException if elements is null */ public static HashSet ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return HashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a HashSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * HashSet.range(0, 0)  // = HashSet()
     * HashSet.range(2, 0)  // = HashSet()
     * HashSet.range(-2, 2) // = HashSet(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ public static HashSet range(int from, int toExclusive) { return HashSet.ofAll(Iterator.range(from, toExclusive)); } public static HashSet range(char from, char toExclusive) { return HashSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a HashSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * HashSet.rangeBy(1, 3, 1)  // = HashSet(1, 2)
     * HashSet.rangeBy(1, 4, 2)  // = HashSet(1, 3)
     * HashSet.rangeBy(4, 1, -2) // = HashSet(4, 2)
     * HashSet.rangeBy(4, 1, 2)  // = HashSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static HashSet rangeBy(int from, int toExclusive, int step) { return HashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static HashSet rangeBy(char from, char toExclusive, int step) { return HashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } @GwtIncompatible public static HashSet rangeBy(double from, double toExclusive, double step) { return HashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a HashSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * HashSet.range(0L, 0L)  // = HashSet()
     * HashSet.range(2L, 0L)  // = HashSet()
     * HashSet.range(-2L, 2L) // = HashSet(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ public static HashSet range(long from, long toExclusive) { return HashSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a HashSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * HashSet.rangeBy(1L, 3L, 1L)  // = HashSet(1L, 2L)
     * HashSet.rangeBy(1L, 4L, 2L)  // = HashSet(1L, 3L)
     * HashSet.rangeBy(4L, 1L, -2L) // = HashSet(4L, 2L)
     * HashSet.rangeBy(4L, 1L, 2L)  // = HashSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static HashSet rangeBy(long from, long toExclusive, long step) { return HashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a HashSet of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * HashSet.rangeClosed(0, 0)  // = HashSet(0)
     * HashSet.rangeClosed(2, 0)  // = HashSet()
     * HashSet.rangeClosed(-2, 2) // = HashSet(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ public static HashSet rangeClosed(int from, int toInclusive) { return HashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } public static HashSet rangeClosed(char from, char toInclusive) { return HashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a HashSet of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * HashSet.rangeClosedBy(1, 3, 1)  // = HashSet(1, 2, 3)
     * HashSet.rangeClosedBy(1, 4, 2)  // = HashSet(1, 3)
     * HashSet.rangeClosedBy(4, 1, -2) // = HashSet(4, 2)
     * HashSet.rangeClosedBy(4, 1, 2)  // = HashSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static HashSet rangeClosedBy(int from, int toInclusive, int step) { return HashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } public static HashSet rangeClosedBy(char from, char toInclusive, int step) { return HashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @GwtIncompatible public static HashSet rangeClosedBy(double from, double toInclusive, double step) { return HashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a HashSet of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * HashSet.rangeClosed(0L, 0L)  // = HashSet(0L)
     * HashSet.rangeClosed(2L, 0L)  // = HashSet()
     * HashSet.rangeClosed(-2L, 2L) // = HashSet(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ public static HashSet rangeClosed(long from, long toInclusive) { return HashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a HashSet of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * HashSet.rangeClosedBy(1L, 3L, 1L)  // = HashSet(1L, 2L, 3L)
     * HashSet.rangeClosedBy(1L, 4L, 2L)  // = HashSet(1L, 3L)
     * HashSet.rangeClosedBy(4L, 1L, -2L) // = HashSet(4L, 2L)
     * HashSet.rangeClosedBy(4L, 1L, 2L)  // = HashSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static HashSet rangeClosedBy(long from, long toInclusive, long step) { return HashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @Override public HashSet add(T element) { return contains(element) ? this : new HashSet<>(tree.put(element, element)); } @Override public HashSet addAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() && elements instanceof HashSet) { @SuppressWarnings("unchecked") final HashSet set = (HashSet) elements; return set; } final HashArrayMappedTrie that = addAll(tree, elements); if (that.size() == tree.size()) { return this; } else { return new HashSet<>(that); } } @Override public HashSet collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } @Override public boolean contains(T element) { return tree.get(element).isDefined(); } @Override public HashSet diff(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() || elements.isEmpty()) { return this; } else { return removeAll(elements); } } @Override public HashSet distinct() { return this; } @Override public HashSet distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return HashSet.ofAll(iterator().distinctBy(comparator)); } @Override public HashSet distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return HashSet.ofAll(iterator().distinctBy(keyExtractor)); } @Override public HashSet drop(int n) { if (n <= 0) { return this; } else { return HashSet.ofAll(iterator().drop(n)); } } @Override public HashSet dropRight(int n) { return drop(n); } @Override public HashSet dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override public HashSet dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final HashSet dropped = HashSet.ofAll(iterator().dropWhile(predicate)); return dropped.length() == length() ? this : dropped; } @Override public HashSet filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final HashSet filtered = HashSet.ofAll(iterator().filter(predicate)); if (filtered.isEmpty()) { return empty(); } else if (filtered.length() == length()) { return this; } else { return filtered; } } @Override public HashSet reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(predicate.negate()); } @Override public HashSet flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final HashArrayMappedTrie that = foldLeft(HashArrayMappedTrie.empty(), (tree, t) -> addAll(tree, mapper.apply(t))); return new HashSet<>(that); } } @Override public U foldRight(U zero, BiFunction f) { return foldLeft(zero, (u, t) -> f.apply(t, u)); } @Override public Map> groupBy(Function classifier) { return Collections.groupBy(this, classifier, HashSet::ofAll); } @Override public Iterator> grouped(int size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public T head() { if (tree.isEmpty()) { throw new NoSuchElementException("head of empty set"); } return iterator().next(); } @Override public Option headOption() { return iterator().headOption(); } @Override public HashSet init() { return tail(); } @Override public Option> initOption() { return tailOption(); } @Override public HashSet intersect(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() || elements.isEmpty()) { return empty(); } else { final int size = size(); if (size <= elements.size()) { return retainAll(elements); } else { final HashSet results = HashSet. ofAll(elements).retainAll(this); return (size == results.size()) ? this : results; } } } /** * A {@code HashSet} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return tree.isEmpty(); } /** * A {@code HashSet} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } @Override public Iterator iterator() { return tree.keysIterator(); } @Override public T last() { return Collections.last(this); } @Override public int length() { return tree.size(); } @Override public HashSet map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final HashArrayMappedTrie that = foldLeft(HashArrayMappedTrie.empty(), (tree, t) -> { final U u = mapper.apply(t); return tree.put(u, u); }); return new HashSet<>(that); } } @Override public String mkString(CharSequence prefix, CharSequence delimiter, CharSequence suffix) { return iterator().mkString(prefix, delimiter, suffix); } @Override public HashSet orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override public HashSet orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override public Tuple2, HashSet> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2, Iterator> p = iterator().partition(predicate); return Tuple.of(HashSet.ofAll(p._1), HashSet.ofAll(p._2)); } @Override public HashSet peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(iterator().head()); } return this; } @Override public HashSet remove(T element) { final HashArrayMappedTrie newTree = tree.remove(element); return (newTree == tree) ? this : new HashSet<>(newTree); } @Override public HashSet removeAll(Iterable elements) { return Collections.removeAll(this, elements); } @Override public HashSet replace(T currentElement, T newElement) { if (tree.containsKey(currentElement)) { return remove(currentElement).add(newElement); } else { return this; } } @Override public HashSet replaceAll(T currentElement, T newElement) { return replace(currentElement, newElement); } @Override public HashSet retainAll(Iterable elements) { return Collections.retainAll(this, elements); } @Override public HashSet scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override public HashSet scanLeft(U zero, BiFunction operation) { return Collections.scanLeft(this, zero, operation, HashSet::ofAll); } @Override public HashSet scanRight(U zero, BiFunction operation) { return Collections.scanRight(this, zero, operation, HashSet::ofAll); } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(HashSet::ofAll); } @Override public Iterator> sliding(int size) { return sliding(size, 1); } @Override public Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(HashSet::ofAll); } @Override public Tuple2, HashSet> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2, Iterator> t = iterator().span(predicate); return Tuple.of(HashSet.ofAll(t._1), HashSet.ofAll(t._2)); } @Override public HashSet tail() { if (tree.isEmpty()) { throw new UnsupportedOperationException("tail of empty set"); } return remove(head()); } @Override public Option> tailOption() { if (tree.isEmpty()) { return Option.none(); } else { return Option.some(tail()); } } @Override public HashSet take(int n) { if (n >= size() || isEmpty()) { return this; } else if (n <= 0) { return empty(); } else { return ofAll(() -> iterator().take(n)); } } @Override public HashSet takeRight(int n) { return take(n); } @Override public HashSet takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override public HashSet takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final HashSet taken = HashSet.ofAll(iterator().takeWhile(predicate)); return taken.length() == length() ? this : taken; } /** * Transforms this {@code HashSet}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public java.util.HashSet toJavaSet() { return toJavaSet(java.util.HashSet::new); } @SuppressWarnings("unchecked") @Override public HashSet union(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { if (elements instanceof HashSet) { return (HashSet) elements; } else { return HashSet.ofAll(elements); } } else if (elements.isEmpty()) { return this; } else { final HashArrayMappedTrie that = addAll(tree, elements); if (that.size() == tree.size()) { return this; } else { return new HashSet<>(that); } } } @Override public Tuple2, HashSet> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Tuple2, Iterator> t = iterator().unzip(unzipper); return Tuple.of(HashSet.ofAll(t._1), HashSet.ofAll(t._2)); } @Override public Tuple3, HashSet, HashSet> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Tuple3, Iterator, Iterator> t = iterator().unzip3(unzipper); return Tuple.of(HashSet.ofAll(t._1), HashSet.ofAll(t._2), HashSet.ofAll(t._3)); } @Override public HashSet> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public HashSet zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return HashSet.ofAll(iterator().zipWith(that, mapper)); } @Override public HashSet> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return HashSet.ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public HashSet> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public HashSet zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return HashSet.ofAll(iterator().zipWithIndex(mapper)); } // -- Object @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } @Override public String stringPrefix() { return "HashSet"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } private static HashArrayMappedTrie addAll(HashArrayMappedTrie initial, Iterable additional) { HashArrayMappedTrie that = initial; for (T t : additional) { that = that.put(t, t); } return that; } // -- Serialization /** * {@code writeReplace} method for the serialization proxy pattern. *

* The presence of this method causes the serialization system to emit a SerializationProxy instance instead of * an instance of the enclosing class. * * @return A SerializationProxy for this enclosing class. */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private Object writeReplace() { return new SerializationProxy<>(this.tree); } /** * {@code readObject} method for the serialization proxy pattern. *

* Guarantees that the serialization system will never generate a serialized instance of the enclosing class. * * @param stream An object serialization stream. * @throws java.io.InvalidObjectException This method will throw with the message "Proxy required". */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } /** * A serialization proxy which, in this context, is used to deserialize immutable, linked Lists with final * instance fields. * * @param The component type of the underlying list. */ // DEV NOTE: The serialization proxy pattern is not compatible with non-final, i.e. extendable, // classes. Also, it may not be compatible with circular object graphs. @GwtIncompatible("The Java serialization protocol is explicitly not supported") private static final class SerializationProxy implements Serializable { private static final long serialVersionUID = 1L; // the instance to be serialized/deserialized private transient HashArrayMappedTrie tree; /** * Constructor for the case of serialization, called by {@link HashSet#writeReplace()}. *

* The constructor of a SerializationProxy takes an argument that concisely represents the logical state of * an instance of the enclosing class. * * @param tree a Cons */ SerializationProxy(HashArrayMappedTrie tree) { this.tree = tree; } /** * Write an object to a serialization stream. * * @param s An object serialization stream. * @throws java.io.IOException If an error occurs writing to the stream. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(tree.size()); for (Tuple2 e : tree) { s.writeObject(e._1); } } /** * Read an object from a deserialization stream. * * @param s An object deserialization stream. * @throws ClassNotFoundException If the object's class read from the stream cannot be found. * @throws InvalidObjectException If the stream contains no list elements. * @throws IOException If an error occurs reading from the stream. */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); final int size = s.readInt(); if (size < 0) { throw new InvalidObjectException("No elements"); } HashArrayMappedTrie temp = HashArrayMappedTrie.empty(); for (int i = 0; i < size; i++) { @SuppressWarnings("unchecked") final T element = (T) s.readObject(); temp = temp.put(element, element); } tree = temp; } /** * {@code readResolve} method for the serialization proxy pattern. *

* Returns a logically equivalent instance of the enclosing class. The presence of this method causes the * serialization system to translate the serialization proxy back into an instance of the enclosing class * upon deserialization. * * @return A deserialized instance of the enclosing class. */ private Object readResolve() { return tree.isEmpty() ? HashSet.empty() : new HashSet<>(tree); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/IndexedSeq.java000066400000000000000000000424731342074374400246160ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple3; import io.vavr.Tuple2; import io.vavr.control.Option; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.*; /** * Interface for immutable, indexed sequences. *

* Efficient random access is characteristic for indexed sequences. * * @param component type * @author Daniel Dietrich */ public interface IndexedSeq extends Seq { long serialVersionUID = 1L; /** * Narrows a widened {@code IndexedSeq} to {@code IndexedSeq} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param indexedSeq An {@code IndexedSeq}. * @param Component type of the {@code IndexedSeq}. * @return the given {@code indexedSeq} instance as narrowed type {@code IndexedSeq}. */ @SuppressWarnings("unchecked") static IndexedSeq narrow(IndexedSeq indexedSeq) { return (IndexedSeq) indexedSeq; } // -- Adjusted return types of Seq methods @Override IndexedSeq append(T element); @Override IndexedSeq appendAll(Iterable elements); @GwtIncompatible @Override IndexedSeq asJava(Consumer> action); @GwtIncompatible @Override IndexedSeq asJavaMutable(Consumer> action); @Override default PartialFunction asPartialFunction() throws IndexOutOfBoundsException { return new PartialFunction() { private static final long serialVersionUID = 1L; @Override public T apply(Integer index) { return get(index); } @Override public boolean isDefinedAt(Integer index) { return 0 <= index && index < length(); } }; } @Override IndexedSeq collect(PartialFunction partialFunction); @Override IndexedSeq> combinations(); @Override IndexedSeq> combinations(int k); @Override Iterator> crossProduct(int power); @Override IndexedSeq distinct(); @Override IndexedSeq distinctBy(Comparator comparator); @Override IndexedSeq distinctBy(Function keyExtractor); @Override IndexedSeq drop(int n); @Override IndexedSeq dropUntil(Predicate predicate); @Override IndexedSeq dropWhile(Predicate predicate); @Override IndexedSeq dropRight(int n); @Override IndexedSeq dropRightUntil(Predicate predicate); @Override IndexedSeq dropRightWhile(Predicate predicate); @Override default boolean endsWith(Seq that) { Objects.requireNonNull(that, "that is null"); if (that instanceof IndexedSeq) { int i = length() - 1; int j = that.length() - 1; if (j > i) { return false; } else { while (j >= 0) { if (!Objects.equals(this.get(i), that.get(j))) { return false; } i--; j--; } return true; } } else { return Seq.super.endsWith(that); } } @Override IndexedSeq filter(Predicate predicate); @Override IndexedSeq reject(Predicate predicate); @Override IndexedSeq flatMap(Function> mapper); @Override Map> groupBy(Function classifier); @Override default int indexWhere(Predicate predicate, int from) { Objects.requireNonNull(predicate, "predicate is null"); int start = Math.max(from, 0); int n = start + segmentLength(predicate.negate(), start); return (n >= length()) ? -1 : n; } @Override Iterator> grouped(int size); @Override default int indexOfSlice(Iterable that, int from) { Objects.requireNonNull(that, "that is null"); return IndexedSeqModule.Slice.indexOfSlice(this, that, from); } @Override IndexedSeq init(); @Override Option> initOption(); @Override IndexedSeq insert(int index, T element); @Override IndexedSeq insertAll(int index, Iterable elements); @Override IndexedSeq intersperse(T element); @Deprecated @Override default boolean isDefinedAt(Integer index) { return 0 <= index && index < length(); } @Override default T last() { if (isEmpty()) { throw new NoSuchElementException("last of empty IndexedSeq"); } else { return get(length() - 1); } } @Override default int lastIndexOfSlice(Iterable that, int end) { Objects.requireNonNull(that, "that is null"); return IndexedSeqModule.Slice.lastIndexOfSlice(this, that, end); } @Override default int lastIndexWhere(Predicate predicate, int end) { Objects.requireNonNull(predicate, "predicate is null"); int i = Math.min(end, length() - 1); while (i >= 0 && !predicate.test(this.get(i))) { i--; } return i; } @Override IndexedSeq map(Function mapper); @Override IndexedSeq orElse(Iterable other); @Override IndexedSeq orElse(Supplier> supplier); @Override IndexedSeq padTo(int length, T element); @Override IndexedSeq patch(int from, Iterable that, int replaced); @Override Tuple2, ? extends IndexedSeq> partition(Predicate predicate); @Override IndexedSeq peek(Consumer action); @Override IndexedSeq> permutations(); @Override IndexedSeq prepend(T element); @Override IndexedSeq prependAll(Iterable elements); @Override IndexedSeq remove(T element); @Override IndexedSeq removeFirst(Predicate predicate); @Override IndexedSeq removeLast(Predicate predicate); @Override IndexedSeq removeAt(int index); @Override IndexedSeq removeAll(T element); @Override IndexedSeq removeAll(Iterable elements); @Override @Deprecated IndexedSeq removeAll(Predicate predicate); @Override IndexedSeq replace(T currentElement, T newElement); @Override IndexedSeq replaceAll(T currentElement, T newElement); @Override IndexedSeq retainAll(Iterable elements); @Override IndexedSeq reverse(); @Override default Iterator reverseIterator() { return new AbstractIterator() { private int i = IndexedSeq.this.length(); @Override public boolean hasNext() { return i > 0; } @Override public T getNext() { return IndexedSeq.this.get(--i); } }; } @Override IndexedSeq rotateLeft(int n); @Override IndexedSeq rotateRight(int n); @Override IndexedSeq scan(T zero, BiFunction operation); @Override IndexedSeq scanLeft(U zero, BiFunction operation); @Override IndexedSeq scanRight(U zero, BiFunction operation); @Override default int segmentLength(Predicate predicate, int from) { Objects.requireNonNull(predicate, "predicate is null"); int len = length(); int i = from; while (i < len && predicate.test(this.get(i))) { i++; } return i - from; } @Override IndexedSeq shuffle(); @Override IndexedSeq slice(int beginIndex, int endIndex); @Override Iterator> slideBy(Function classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override IndexedSeq sorted(); @Override IndexedSeq sorted(Comparator comparator); @Override > IndexedSeq sortBy(Function mapper); @Override IndexedSeq sortBy(Comparator comparator, Function mapper); @Override Tuple2, ? extends IndexedSeq> span(Predicate predicate); @Override default boolean startsWith(Iterable that, int offset) { Objects.requireNonNull(that, "that is null"); if (offset < 0) { return false; } if (that instanceof IndexedSeq) { IndexedSeq thatIndexedSeq = (IndexedSeq) that; int i = offset; int j = 0; int thisLen = length(); int thatLen = thatIndexedSeq.length(); while (i < thisLen && j < thatLen && Objects.equals(this.get(i), thatIndexedSeq.get(j))) { i++; j++; } return j == thatLen; } else { int i = offset; int thisLen = length(); java.util.Iterator thatElems = that.iterator(); while (i < thisLen && thatElems.hasNext()) { if (!Objects.equals(this.get(i), thatElems.next())) { return false; } i++; } return !thatElems.hasNext(); } } @Override IndexedSeq subSequence(int beginIndex); @Override IndexedSeq subSequence(int beginIndex, int endIndex); @Override IndexedSeq tail(); @Override Option> tailOption(); @Override IndexedSeq take(int n); @Override IndexedSeq takeUntil(Predicate predicate); @Override IndexedSeq takeWhile(Predicate predicate); @Override IndexedSeq takeRight(int n); @Override IndexedSeq takeRightUntil(Predicate predicate); @Override IndexedSeq takeRightWhile(Predicate predicate); @Override Tuple2, ? extends IndexedSeq> unzip(Function> unzipper); @Override Tuple3, ? extends IndexedSeq, ? extends IndexedSeq> unzip3(Function> unzipper); @Override IndexedSeq update(int index, T element); @Override IndexedSeq update(int index, Function updater); @Override IndexedSeq> zip(Iterable that); @Override IndexedSeq zipWith(Iterable that, BiFunction mapper); @Override IndexedSeq> zipAll(Iterable that, T thisElem, U thatElem); @Override IndexedSeq> zipWithIndex(); @Override IndexedSeq zipWithIndex(BiFunction mapper); /** * Searches this sequence for a specific element using a binary search. The sequence must already be sorted into * ascending natural order. If it is not sorted, the results are undefined. * * @param element the element to find * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. * @throws ClassCastException if T cannot be cast to {@code Comparable} */ @Override @SuppressWarnings("unchecked") default int search(T element) { IntUnaryOperator comparison = midIndex -> { Comparable midVal = (Comparable) get(midIndex); return midVal.compareTo(element); }; return IndexedSeqModule.Search.binarySearch(this, comparison); } /** * Searches this sequence for a specific element using a binary search. The sequence must already be sorted into * ascending order according to the specified comparator. If it is not sorted, the results are undefined. * * @param element the element to find * @param comparator the comparator by which this sequence is ordered * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. */ @Override default int search(T element, Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); IntUnaryOperator comparison = midIndex -> { T midVal = get(midIndex); return comparator.compare(midVal, element); }; return IndexedSeqModule.Search.binarySearch(this, comparison); } } interface IndexedSeqModule { class Slice { static int indexOfSlice(IndexedSeq source, Iterable slice, int from) { if (source.isEmpty()) { return from == 0 && Collections.isEmpty(slice) ? 0 : -1; } final IndexedSeq _slice = toIndexedSeq(slice); final int maxIndex = source.length() - _slice.length(); return findSlice(source, _slice, Math.max(from, 0), maxIndex); } static int lastIndexOfSlice(IndexedSeq source, Iterable slice, int end) { if (end < 0) { return -1; } else if (source.isEmpty()) { return Collections.isEmpty(slice) ? 0 : -1; } else if (Collections.isEmpty(slice)) { final int len = source.length(); return len < end ? len : end; } int index = 0; int result = -1; final IndexedSeq _slice = toIndexedSeq(slice); final int maxIndex = source.length() - _slice.length(); while (index <= maxIndex) { int indexOfSlice = findSlice(source, _slice, index, maxIndex); if (indexOfSlice < 0) { return result; } if (indexOfSlice <= end) { result = indexOfSlice; index = indexOfSlice + 1; } else { return result; } } return result; } private static int findSlice(IndexedSeq source, IndexedSeq slice, int index, int maxIndex) { while (index <= maxIndex) { if (source.startsWith(slice, index)) { return index; } index++; } return -1; } @SuppressWarnings("unchecked") private static IndexedSeq toIndexedSeq(Iterable iterable) { return (iterable instanceof IndexedSeq) ? (IndexedSeq) iterable : Vector.ofAll(iterable); } } interface Search { static int binarySearch(IndexedSeq seq, IntUnaryOperator comparison) { int low = 0; int high = seq.size() - 1; while (low <= high) { final int mid = (low + high) >>> 1; final int cmp = comparison.applyAsInt(mid); if (cmp < 0) { low = mid + 1; } else if (cmp > 0) { high = mid - 1; } else { return mid; } } return -(low + 1); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Iterator.java000066400000000000000000002214111342074374400243450ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.collection.IteratorModule.ConcatIterator; import io.vavr.collection.IteratorModule.DistinctIterator; import io.vavr.collection.IteratorModule.GroupedIterator; import io.vavr.control.Option; import java.math.BigDecimal; import java.util.*; import java.util.function.*; import static java.lang.Double.NEGATIVE_INFINITY; import static java.lang.Double.POSITIVE_INFINITY; import static java.math.RoundingMode.HALF_UP; import static io.vavr.collection.IteratorModule.BigDecimalHelper.areEqual; import static io.vavr.collection.IteratorModule.BigDecimalHelper.asDecimal; import static io.vavr.collection.IteratorModule.CachedIterator; import static io.vavr.collection.IteratorModule.EmptyIterator; /** * {@code io.vavr.collection.Iterator} is a compositional replacement for {@code java.util.Iterator} * whose purpose is to iterate once over a sequence of elements. *

* Note: Iterators encapsulate mutable state. * They are not meant to be used concurrently by different threads. Do not reuse Iterators, e.g. after passing to * {@linkplain io.vavr.collection.List#ofAll(Iterable)}. *

* There are two abstract methods: {@code hasNext} for checking if there is a next element available, * and {@code next} which removes the next element from the iterator and returns it. They can be called * an arbitrary amount of times. If {@code hasNext} returns false, a call of {@code next} will throw * a {@code NoSuchElementException}. *

* Caution: Other methods than {@code hasNext} and {@code next} can be called only once (exclusively). * More specifically, after calling a method it cannot be guaranteed that the next call will succeed. *

* An Iterator that can be only used once because it is a traversal pointer into a collection, and not a collection * itself. * * @param Component type * @author Daniel Dietrich */ // DEV-NOTE: we prefer returning empty() over this if !hasNext() == true in order to free memory. public interface Iterator extends java.util.Iterator, Traversable { /** * Creates an Iterator which traverses along the concatenation of the given iterables. * * @param iterables The iterables * @param Component type. * @return A new {@code io.vavr.collection.Iterator} */ @SuppressWarnings("varargs") @SafeVarargs static Iterator concat(Iterable... iterables) { Objects.requireNonNull(iterables, "iterables is null"); if (iterables.length == 0) { return empty(); } else { ConcatIterator res = new ConcatIterator<>(); for (Iterable iterable : iterables) { res.append(iterable.iterator()); } return res; } } /** * Creates an Iterator which traverses along the concatenation of the given iterables. * * @param iterables The iterable of iterables * @param Component type. * @return A new {@code io.vavr.collection.Iterator} */ static Iterator concat(Iterable> iterables) { Objects.requireNonNull(iterables, "iterables is null"); if (!iterables.iterator().hasNext()) { return empty(); } else { ConcatIterator res = new ConcatIterator<>(); for (Iterable iterable : iterables) { res.append(iterable.iterator()); } return res; } } /** * Returns the empty Iterator. * * @param Component type * @return The empty Iterator */ @SuppressWarnings("unchecked") static Iterator empty() { return (Iterator) EmptyIterator.INSTANCE; } /** * Narrows a widened {@code Iterator} to {@code Iterator} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param iterator An {@code Iterator}. * @param Component type of the {@code Iterator}. * @return the given {@code iterator} instance as narrowed type {@code Iterator}. */ @SuppressWarnings("unchecked") static Iterator narrow(Iterator iterator) { return (Iterator) iterator; } /** * Creates an Iterator which traverses one element. * * @param element An element * @param Component type. * @return A new Iterator */ static Iterator of(T element) { return new AbstractIterator() { boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public T getNext() { hasNext = false; return element; } }; } /** * Creates an Iterator which traverses the given elements. * * @param elements Zero or more elements * @param Component type * @return A new Iterator */ @SafeVarargs static Iterator of(T... elements) { Objects.requireNonNull(elements, "elements is null"); if (elements.length == 0) { return empty(); } else { return new AbstractIterator() { int index = 0; @Override public boolean hasNext() { return index < elements.length; } @Override public T getNext() { return elements[index++]; } }; } } /** * Creates an Iterator based on the given Iterable. This is a convenience method for * {@code Iterator.ofAll(iterable.iterator()}. * * @param iterable A {@link Iterable} * @param Component type. * @return A new {@code io.vavr.collection.Iterator} */ @SuppressWarnings("unchecked") static Iterator ofAll(Iterable iterable) { Objects.requireNonNull(iterable, "iterable is null"); if (iterable instanceof Iterator) { return (Iterator) iterable; } else { return ofAll(iterable.iterator()); } } /** * Creates an Iterator based on the given Iterator by * delegating calls of {@code hasNext()} and {@code next()} to it. * * @param iterator A {@link java.util.Iterator} * @param Component type. * @return A new {@code io.vavr.collection.Iterator} */ @SuppressWarnings("unchecked") static Iterator ofAll(java.util.Iterator iterator) { Objects.requireNonNull(iterator, "iterator is null"); if (iterator instanceof Iterator) { return (Iterator) iterator; } else { return new AbstractIterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T getNext() { return iterator.next(); } }; } } /** * Creates an Iterator from boolean values. * * @param elements boolean values * @return A new Iterator of Boolean values * @throws NullPointerException if elements is null */ static Iterator ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Boolean getNext() { return elements[i++]; } }; } /** * Creates an Iterator from byte values. * * @param elements byte values * @return A new Iterator of Byte values * @throws NullPointerException if elements is null */ static Iterator ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Byte getNext() { return elements[i++]; } }; } /** * Creates an Iterator from char values. * * @param elements char values * @return A new Iterator of Character values * @throws NullPointerException if elements is null */ static Iterator ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Character getNext() { return elements[i++]; } }; } /** * Creates ann Iterator from double values. * * @param elements double values * @return A new Iterator of Double values * @throws NullPointerException if elements is null */ static Iterator ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Double getNext() { return elements[i++]; } }; } /** * Creates an Iterator from float values. * * @param elements float values * @return A new Iterator of Float values * @throws NullPointerException if elements is null */ static Iterator ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Float getNext() { return elements[i++]; } }; } /** * Creates an Iterator from int values. * * @param elements int values * @return A new Iterator of Integer values * @throws NullPointerException if elements is null */ static Iterator ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Integer getNext() { return elements[i++]; } }; } /** * Creates an Iterator from long values. * * @param elements long values * @return A new Iterator of Long values * @throws NullPointerException if elements is null */ static Iterator ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Long getNext() { return elements[i++]; } }; } /** * Creates an Iterator from short values. * * @param elements short values * @return A new Iterator of Short values * @throws NullPointerException if elements is null */ static Iterator ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return new AbstractIterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public Short getNext() { return elements[i++]; } }; } /** * Returns an Iterator on a sequence of {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the Iterator * @param n The number of elements * @param f The Function computing element values * @return An Iterator on a sequence of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ static Iterator tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return io.vavr.collection.Collections.tabulate(n, f); } /** * Returns an Iterator on a sequence of {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the Iterator * @param n The number of elements * @param s The Supplier computing element values * @return An iterator on a sequence of {@code n} elements, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ static Iterator fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return io.vavr.collection.Collections.fill(n, s); } /** * Returns a Iterator containing {@code n} times the given {@code element} * * @param Component type of the Iterator * @param n The number of elements * @param element The element * @return An iterator of {@code n} sequence elements, where each element is the given {@code element}. */ static Iterator fill(int n, T element) { return io.vavr.collection.Collections.fillObject(n, element); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Iterator.range('a', 'c')  // = ('a', 'b')
     * Iterator.range('c', 'a')  // = ()
     * 
     * 
* * @param from the first character * @param toExclusive the successor of the last character * @return a range of characters as specified or the empty range if {@code from >= toExclusive} */ static Iterator range(char from, char toExclusive) { return rangeBy(from, toExclusive, 1); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Iterator.rangeBy('a', 'c', 1)  // = ('a', 'b')
     * Iterator.rangeBy('a', 'd', 2)  // = ('a', 'c')
     * Iterator.rangeBy('d', 'a', -2) // = ('d', 'b')
     * Iterator.rangeBy('d', 'a', 2)  // = ()
     * 
     * 
* * @param from the first character * @param toExclusive the successor of the last character if step > 0, the predecessor of the last character if step < 0 * @param step the step * @return a range of characters as specified or the empty range if {@code signum(step) == signum(from - toExclusive)}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeBy(char from, char toExclusive, int step) { return rangeBy((int) from, (int) toExclusive, step).map(i -> (char) i.shortValue()); } @GwtIncompatible("BigDecimalHelper is GwtIncompatible") static Iterator rangeBy(double from, double toExclusive, double step) { final BigDecimal fromDecimal = asDecimal(from), toDecimal = asDecimal(toExclusive), stepDecimal = asDecimal(step); return rangeBy(fromDecimal, toDecimal, stepDecimal).map(BigDecimal::doubleValue); } static Iterator rangeBy(BigDecimal from, BigDecimal toExclusive, BigDecimal step) { if (step.signum() == 0) { throw new IllegalArgumentException("step cannot be 0"); } else if (areEqual(from, toExclusive) || step.signum() == from.subtract(toExclusive).signum()) { return empty(); } else { if (step.signum() > 0) { return new AbstractIterator() { BigDecimal i = from; @Override public boolean hasNext() { return i.compareTo(toExclusive) < 0; } @Override public BigDecimal getNext() { final BigDecimal next = this.i; this.i = next.add(step); return next; } }; } else { return new AbstractIterator() { BigDecimal i = from; @Override public boolean hasNext() { return i.compareTo(toExclusive) > 0; } @Override public BigDecimal getNext() { final BigDecimal next = this.i; this.i = next.add(step); return next; } }; } } } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Iterator.range(0, 0)  // = ()
     * Iterator.range(2, 0)  // = ()
     * Iterator.range(-2, 2) // = (-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ static Iterator range(int from, int toExclusive) { return rangeBy(from, toExclusive, 1); } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Iterator.rangeBy(1, 3, 1)  // = (1, 2)
     * Iterator.rangeBy(1, 4, 2)  // = (1, 3)
     * Iterator.rangeBy(4, 1, -2) // = (4, 2)
     * Iterator.rangeBy(4, 1, 2)  // = ()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 if step > 0, the last number - 1 if step < 0 * @param step the step * @return a range of long values as specified or the empty range if {@code (from == toExclusive) || (step * (from - toExclusive) > 0)}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeBy(int from, int toExclusive, int step) { final int toInclusive = toExclusive - (step > 0 ? 1 : -1); return rangeClosedBy(from, toInclusive, step); } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Iterator.range(0L, 0L)  // = ()
     * Iterator.range(2L, 0L)  // = ()
     * Iterator.range(-2L, 2L) // = (-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ static Iterator range(long from, long toExclusive) { return rangeBy(from, toExclusive, 1); } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Iterator.rangeBy(1L, 3L, 1L)  // = (1L, 2L)
     * Iterator.rangeBy(1L, 4L, 2L)  // = (1L, 3L)
     * Iterator.rangeBy(4L, 1L, -2L) // = (4L, 2L)
     * Iterator.rangeBy(4L, 1L, 2L)  // = ()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 if step > 0, the last number - 1 if step < 0 * @param step the step * @return a range of long values as specified or the empty range if {@code (from == toExclusive) || (step * (from - toExclusive) > 0)}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeBy(long from, long toExclusive, long step) { final long toInclusive = toExclusive - (step > 0 ? 1 : -1); return rangeClosedBy(from, toInclusive, step); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Iterator.rangeClosed('a', 'c')  // = ('a', 'b', 'c')
     * Iterator.rangeClosed('c', 'a')  // = ()
     * 
     * 
* * @param from the first character * @param toInclusive the last character * @return a range of characters as specified or the empty range if {@code from > toInclusive} */ static Iterator rangeClosed(char from, char toInclusive) { return rangeClosedBy(from, toInclusive, 1); } /** * Creates an Iterator of characters starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Iterator.rangeClosedBy('a', 'c', 1)  // = ('a', 'b', 'c')
     * Iterator.rangeClosedBy('a', 'd', 2)  // = ('a', 'c')
     * Iterator.rangeClosedBy('d', 'a', -2) // = ('d', 'b')
     * Iterator.rangeClosedBy('d', 'a', 2)  // = ()
     * 
     * 
* * @param from the first character * @param toInclusive the last character * @param step the step * @return a range of characters as specified or the empty range if {@code signum(step) == signum(from - toInclusive)}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeClosedBy(char from, char toInclusive, int step) { return rangeClosedBy((int) from, (int) toInclusive, step).map(i -> (char) i.shortValue()); } @GwtIncompatible static Iterator rangeClosedBy(double from, double toInclusive, double step) { if (from == toInclusive) { return of(from); } final double toExclusive = (step > 0) ? Math.nextUp(toInclusive) : Math.nextDown(toInclusive); return rangeBy(from, toExclusive, step); } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Iterator.rangeClosed(0, 0)  // = (0)
     * Iterator.rangeClosed(2, 0)  // = ()
     * Iterator.rangeClosed(-2, 2) // = (-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ static Iterator rangeClosed(int from, int toInclusive) { return rangeClosedBy(from, toInclusive, 1); } /** * Creates an Iterator of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Iterator.rangeClosedBy(1, 3, 1)  // = (1, 2, 3)
     * Iterator.rangeClosedBy(1, 4, 2)  // = (1, 3)
     * Iterator.rangeClosedBy(4, 1, -2) // = (4, 2)
     * Iterator.rangeClosedBy(4, 1, 2)  // = ()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if {@code signum(step) == signum(from - toInclusive)}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeClosedBy(int from, int toInclusive, int step) { if (step == 0) { throw new IllegalArgumentException("step cannot be 0"); } else if (from == toInclusive) { return of(from); } else if (Integer.signum(step) == Integer.signum(from - toInclusive)) { return empty(); } else { final int end = toInclusive - step; if (step > 0) { return new AbstractIterator() { int i = from - step; @Override public boolean hasNext() { return i <= end; } @Override public Integer getNext() { return i += step; } }; } else { return new AbstractIterator() { int i = from - step; @Override public boolean hasNext() { return i >= end; } @Override public Integer getNext() { return i += step; } }; } } } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Iterator.rangeClosed(0L, 0L)  // = (0L)
     * Iterator.rangeClosed(2L, 0L)  // = ()
     * Iterator.rangeClosed(-2L, 2L) // = (-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ static Iterator rangeClosed(long from, long toInclusive) { return rangeClosedBy(from, toInclusive, 1L); } /** * Creates an Iterator of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Iterator.rangeClosedBy(1L, 3L, 1L)  // = (1L, 2L, 3L)
     * Iterator.rangeClosedBy(1L, 4L, 2L)  // = (1L, 3L)
     * Iterator.rangeClosedBy(4L, 1L, -2L) // = (4L, 2L)
     * Iterator.rangeClosedBy(4L, 1L, 2L)  // = ()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if {@code signum(step) == signum(from - toInclusive)}. * @throws IllegalArgumentException if {@code step} is zero */ static Iterator rangeClosedBy(long from, long toInclusive, long step) { if (step == 0) { throw new IllegalArgumentException("step cannot be 0"); } else if (from == toInclusive) { return of(from); } else if (Long.signum(step) == Long.signum(from - toInclusive)) { return empty(); } else { final long end = toInclusive - step; if (step > 0) { return new AbstractIterator() { long i = from - step; @Override public boolean hasNext() { return i <= end; } @Override public Long getNext() { return i += step; } }; } else { return new AbstractIterator() { long i = from - step; @Override public boolean hasNext() { return i >= end; } @Override public Long getNext() { return i += step; } }; } } } /** * Returns an infinite iterator of int values starting from {@code value}. *

* The {@code Iterator} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}. * * @param value a start int value * @return a new {@code Iterator} of int values starting from {@code from} */ static Iterator from(int value) { return new AbstractIterator() { private int next = value; @Override public boolean hasNext() { return true; } @Override public Integer getNext() { return next++; } }; } /** * Returns an infinite iterator of int values starting from {@code value} and spaced by {@code step}. *

* The {@code Iterator} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}. * * @param value a start int value * @param step the step by which to advance on each iteration * @return a new {@code Iterator} of int values starting from {@code from} */ static Iterator from(int value, int step) { return new AbstractIterator() { private int next = value; @Override public boolean hasNext() { return true; } @Override public Integer getNext() { final int result = next; next += step; return result; } }; } /** * Returns an infinite iterator of long values starting from {@code value}. *

* The {@code Iterator} extends to {@code Long.MIN_VALUE} when passing {@code Long.MAX_VALUE}. * * @param value a start long value * @return a new {@code Iterator} of long values starting from {@code from} */ static Iterator from(long value) { return new AbstractIterator() { private long next = value; @Override public boolean hasNext() { return true; } @Override public Long getNext() { return next++; } }; } /** * Returns an infinite iterator of long values starting from {@code value} and spaced by {@code step}. *

* The {@code Iterator} extends to {@code Long.MIN_VALUE} when passing {@code Long.MAX_VALUE}. * * @param value a start long value * @param step the step by which to advance on each iteration * @return a new {@code Iterator} of long values starting from {@code from} */ static Iterator from(long value, long step) { return new AbstractIterator() { private long next = value; @Override public boolean hasNext() { return true; } @Override public Long getNext() { final long result = next; next += step; return result; } }; } /** * Generates an infinite iterator using a value Supplier. * * @param supplier A Supplier of iterator values * @param value type * @return A new {@code Iterator} */ static Iterator continually(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return new AbstractIterator() { @Override public boolean hasNext() { return true; } @Override public T getNext() { return supplier.get(); } }; } /** * Creates an iterator that repeatedly invokes the supplier * while it's a {@code Some} and end on the first {@code None} * * @param supplier A Supplier of iterator values * @param value type * @return A new {@code Iterator} * @throws NullPointerException if supplier produces null value */ static Iterator iterate(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return new AbstractIterator() { Option nextOption; @Override public boolean hasNext() { if (nextOption == null) { nextOption = supplier.get(); } return nextOption.isDefined(); } @Override public T getNext() { final T next = nextOption.get(); nextOption = null; return next; } }; } /** * Generates an infinite iterator using a function to calculate the next value * based on the previous. * * @param seed The first value in the iterator * @param f A function to calculate the next value based on the previous * @param value type * @return A new {@code Iterator} */ static Iterator iterate(T seed, Function f) { Objects.requireNonNull(f, "f is null"); return new AbstractIterator() { Function nextFunc = s -> { nextFunc = f; return seed; }; T current = null; @Override public boolean hasNext() { return true; } @Override public T getNext() { current = nextFunc.apply(current); return current; } }; } /** * Creates an infinite iterator returning the given element. * * @param t An element * @param Element type * @return A new Iterator containing infinite {@code t}'s. */ static Iterator continually(T t) { return new AbstractIterator() { @Override public boolean hasNext() { return true; } @Override public T getNext() { return t; } }; } // -- Additional methods of Iterator @Override default Iterator collect(PartialFunction partialFunction) { Objects.requireNonNull(partialFunction, "partialFunction is null"); return filter(partialFunction::isDefinedAt).map(partialFunction::apply); } // DEV-NOTE: cannot use arg Iterable, it would be ambiguous default Iterator concat(java.util.Iterator that) { Objects.requireNonNull(that, "that is null"); if (!that.hasNext()) { return this; } else if (!hasNext()) { return ofAll(that); } else { return concat(this, ofAll(that)); } } /** * Inserts an element between all elements of this Iterator. * * @param element An element. * @return an interspersed version of this */ default Iterator intersperse(T element) { if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { boolean insertElement = false; @Override public boolean hasNext() { return that.hasNext(); } @Override public T getNext() { if (insertElement) { insertElement = false; return element; } else { insertElement = true; return that.next(); } } }; } } /** * Transforms this {@code Iterator}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override default Iterator> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override default Iterator zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final Iterator it1 = this; final java.util.Iterator it2 = that.iterator(); return new AbstractIterator() { @Override public boolean hasNext() { return it1.hasNext() && it2.hasNext(); } @Override public R getNext() { return mapper.apply(it1.next(), it2.next()); } }; } } @Override default Iterator> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); final java.util.Iterator thatIt = that.iterator(); if (isEmpty() && !thatIt.hasNext()) { return empty(); } else { final Iterator thisIt = this; return new AbstractIterator>() { @Override public boolean hasNext() { return thisIt.hasNext() || thatIt.hasNext(); } @Override public Tuple2 getNext() { final T v1 = thisIt.hasNext() ? thisIt.next() : thisElem; final U v2 = thatIt.hasNext() ? thatIt.next() : thatElem; return Tuple.of(v1, v2); } }; } } @Override default Iterator> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override default Iterator zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final Iterator it1 = this; return new AbstractIterator() { private int index = 0; @Override public boolean hasNext() { return it1.hasNext(); } @Override public U getNext() { return mapper.apply(it1.next(), index++); } }; } } @Override default Tuple2, Iterator> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (!hasNext()) { return Tuple.of(empty(), empty()); } else { final Stream> source = Stream.ofAll(this.map(unzipper)); return Tuple.of(source.map(t -> (T1) t._1).iterator(), source.map(t -> (T2) t._2).iterator()); } } @Override default Tuple3, Iterator, Iterator> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (!hasNext()) { return Tuple.of(empty(), empty(), empty()); } else { final Stream> source = Stream.ofAll(this.map(unzipper)); return Tuple.of(source.map(t -> (T1) t._1).iterator(), source.map(t -> (T2) t._2).iterator(), source.map(t -> (T3) t._3).iterator()); } } /** * Creates an iterator from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating elements, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting iterator and * the element for the next call. *

* Example: *

     * 
     * Iterator.unfold(10, x -> x == 0
     *                 ? Option.none()
     *                 : Option.of(new Tuple2<>(x-1, x)));
     * // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds and unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a list with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static Iterator unfold(T seed, Function>> f) { return unfoldLeft(seed, f); } /** * Creates an iterator from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating elements, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting iterator and * the element for the next call. *

* Example: *

     * 
     * Iterator.unfoldLeft(10, x -> x == 0
     *                    ? Option.none()
     *                    : Option.of(new Tuple2<>(x-1, x)));
     * // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a list with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static Iterator unfoldLeft(T seed, Function>> f) { Objects.requireNonNull(f, "f is null"); return Stream. ofAll( unfoldRight(seed, f.andThen(tupleOpt -> tupleOpt.map(t -> Tuple.of(t._2, t._1))))) .reverse().iterator(); } /** * Creates an iterator from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating elements, otherwise {@code Some} {@code Tuple} * of the element for the next call and the value to add to the * resulting iterator. *

* Example: *

     * 
     * Iterator.unfoldRight(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x, x-1)));
     * // List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a list with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static Iterator unfoldRight(T seed, Function>> f) { Objects.requireNonNull(f, "the unfold iterating function is null"); return new AbstractIterator() { private Option> nextVal = f.apply(seed); @Override public boolean hasNext() { return nextVal.isDefined(); } @Override public U getNext() { final U result = nextVal.get()._1; nextVal = f.apply(nextVal.get()._2); return result; } }; } // -- Overridden methods of Traversable @Override default Iterator distinct() { if (!hasNext()) { return empty(); } else { return new DistinctIterator<>(this, io.vavr.collection.HashSet.empty(), Function.identity()); } } @Override default Iterator distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); if (!hasNext()) { return empty(); } else { return new DistinctIterator<>(this, TreeSet.empty(comparator), Function.identity()); } } @Override default Iterator distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); if (!hasNext()) { return empty(); } else { return new DistinctIterator<>(this, io.vavr.collection.HashSet.empty(), keyExtractor); } } /** * Removes up to n elements from this iterator. * * @param n A number * @return The empty iterator, if {@code n <= 0} or this is empty, otherwise a new iterator without the first n elements. */ @Override default Iterator drop(int n) { if (n <= 0) { return this; } else if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { long count = n; @Override public boolean hasNext() { while (count > 0 && that.hasNext()) { that.next(); // discarded count--; } return that.hasNext(); } @Override public T getNext() { return that.next(); } }; } } @Override default Iterator dropRight(int n) { if (n <= 0) { return this; } else if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { private io.vavr.collection.Queue queue = io.vavr.collection.Queue.empty(); @Override public boolean hasNext() { while (queue.length() < n && that.hasNext()) { queue = queue.append(that.next()); } return queue.length() == n && that.hasNext(); } @Override public T getNext() { final Tuple2> t = queue.append(that.next()).dequeue(); queue = t._2; return t._1; } }; } } @Override default Iterator dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override default Iterator dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return empty(); } else { final CachedIterator that = new CachedIterator<>(this); while (that.hasNext() && predicate.test(that.touch())) { that.next(); } return that; } } /** * Returns an Iterator that contains elements that satisfy the given {@code predicate}. * * @param predicate A predicate * @return A new Iterator */ @Override default Iterator filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { Option next = Option.none(); @Override public boolean hasNext() { while (next.isEmpty() && that.hasNext()) { final T candidate = that.next(); if (predicate.test(candidate)) { next = Option.some(candidate); } } return next.isDefined(); } @Override public T getNext() { final T result = next.get(); next = Option.none(); return result; } }; } } @Override default Iterator reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(predicate.negate()); } @Override default Option findLast(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); T last = null; while (hasNext()) { final T elem = next(); if (predicate.test(elem)) { last = elem; } } return Option.of(last); } /** * FlatMaps the elements of this Iterator to Iterables, which are iterated in the order of occurrence. * * @param mapper A mapper * @param Component type * @return A new Iterable */ @Override default Iterator flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { final Iterator inputs = that; java.util.Iterator current = java.util.Collections.emptyIterator(); @Override public boolean hasNext() { boolean currentHasNext; while (!(currentHasNext = current.hasNext()) && inputs.hasNext()) { current = mapper.apply(inputs.next()).iterator(); } return currentHasNext; } @Override public U getNext() { return current.next(); } }; } } @Override default U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return Stream.ofAll(this).foldRight(zero, f); } @Override default T get() { return head(); } @Override default Map> groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(this, classifier, Iterator::ofAll); } @Override default Iterator> grouped(int size) { return new GroupedIterator<>(this, size, size); } @Override default boolean hasDefiniteSize() { return false; } @Override default T head() { if (!hasNext()) { throw new NoSuchElementException("head() on empty iterator"); } return next(); } @Override default Iterator init() { if (!hasNext()) { throw new UnsupportedOperationException(); } else { return dropRight(1); } } @Override default Option> initOption() { return hasNext() ? Option.some(init()) : Option.none(); } /** * An {@code Iterator} is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } @Override default boolean isEmpty() { return !hasNext(); } /** * An {@code Iterator} is computed lazily. * * @return true */ @Override default boolean isLazy() { return true; } @Override default boolean isTraversableAgain() { return false; } @Override default boolean isSequential() { return true; } @Override default Iterator iterator() { return this; } @Override default T last() { return Collections.last(this); } @Override default int length() { return foldLeft(0, (n, ignored) -> n + 1); } /** * Maps the elements of this Iterator lazily using the given {@code mapper}. * * @param mapper A mapper. * @param Component type * @return A new Iterator */ @Override default Iterator map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { @Override public boolean hasNext() { return that.hasNext(); } @Override public U getNext() { return mapper.apply(that.next()); } }; } } @Override default Iterator orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override default Iterator orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override default Tuple2, Iterator> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return Tuple.of(empty(), empty()); } else { final Stream that = Stream.ofAll(this); final Iterator first = that.iterator().filter(predicate); final Iterator second = that.iterator().filter(predicate.negate()); return Tuple.of(first, second); } } @Override default Iterator peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { @Override public boolean hasNext() { return that.hasNext(); } @Override public T getNext() { final T next = that.next(); action.accept(next); return next; } }; } } @Override default T reduceLeft(BiFunction op) { Objects.requireNonNull(op, "op is null"); if (isEmpty()) { throw new NoSuchElementException("reduceLeft on Nil"); } else { T xs = next(); while (hasNext()) { xs = op.apply(xs, next()); } return xs; } } @Override default T reduceRight(BiFunction op) { Objects.requireNonNull(op, "op is null"); if (isEmpty()) { throw new NoSuchElementException("reduceRight on Nil"); } else { final Stream reversed = Stream.ofAll(this).reverse(); return reversed.reduceLeft((xs, x) -> op.apply(x, xs)); } } @Override default Iterator replace(T currentElement, T newElement) { if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { boolean isFirst = true; @Override public boolean hasNext() { return that.hasNext(); } @Override public T getNext() { final T elem = that.next(); if (isFirst && Objects.equals(currentElement, elem)) { isFirst = false; return newElement; } else { return elem; } } }; } } @Override default Iterator replaceAll(T currentElement, T newElement) { if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { @Override public boolean hasNext() { return that.hasNext(); } @Override public T getNext() { final T elem = that.next(); if (Objects.equals(currentElement, elem)) { return newElement; } else { return elem; } } }; } } @Override default Iterator retainAll(Iterable elements) { return io.vavr.collection.Collections.retainAll(this, elements); } @Override default Traversable scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override default Iterator scanLeft(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); if (isEmpty()) { return of(zero); } else { final Iterator that = this; return new AbstractIterator() { boolean isFirst = true; U acc = zero; @Override public boolean hasNext() { return isFirst || that.hasNext(); } @Override public U getNext() { if (isFirst) { isFirst = false; return acc; } else { acc = operation.apply(acc, that.next()); return acc; } } }; } } // not lazy! @Override default Iterator scanRight(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); if (isEmpty()) { return of(zero); } else { return io.vavr.collection.Collections.scanRight(this, zero, operation, Function.identity()); } } @Override default Iterator> slideBy(Function classifier) { Objects.requireNonNull(classifier, "classifier is null"); if (!hasNext()) { return empty(); } else { final CachedIterator source = new CachedIterator<>(this); return new AbstractIterator>() { private Stream next = null; @Override public boolean hasNext() { if (next == null && source.hasNext()) { final Object key = classifier.apply(source.touch()); final java.util.List acc = new ArrayList<>(); while (source.hasNext() && key.equals(classifier.apply(source.touch()))) { acc.add(source.getNext()); } next = Stream.ofAll(acc); } return next != null; } @Override public Stream getNext() { final Stream result = next; next = null; return result; } }; } } @Override default Iterator> sliding(int size) { return sliding(size, 1); } @Override default Iterator> sliding(int size, int step) { return new GroupedIterator<>(this, size, step); } @Override default Tuple2, Iterator> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return Tuple.of(empty(), empty()); } else { final Stream that = Stream.ofAll(this); return Tuple.of(that.iterator().takeWhile(predicate), that.iterator().dropWhile(predicate)); } } @Override default String stringPrefix() { return "Iterator"; } @Override default Iterator tail() { if (!hasNext()) { throw new UnsupportedOperationException(); } else { next(); // remove first element return this; } } @Override default Option> tailOption() { if (hasNext()) { next(); return Option.some(this); } else { return Option.none(); } } /** * Take the first n elements from this iterator. * * @param n A number * @return The empty iterator, if {@code n <= 0} or this is empty, otherwise a new iterator without the first n elements. */ @Override default Iterator take(int n) { if (n <= 0 || !hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { long count = n; @Override public boolean hasNext() { return count > 0 && that.hasNext(); } @Override public T getNext() { count--; return that.next(); } }; } } @Override default Iterator takeRight(int n) { if (n <= 0) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { private io.vavr.collection.Queue queue = io.vavr.collection.Queue.empty(); @Override public boolean hasNext() { while (that.hasNext()) { queue = queue.enqueue(that.next()); if (queue.length() > n) { queue = queue.dequeue()._2; } } return queue.length() > 0; } @Override public T getNext() { final Tuple2> t = queue.dequeue(); queue = t._2; return t._1; } }; } } @Override default Iterator takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override default Iterator takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (!hasNext()) { return empty(); } else { final Iterator that = this; return new AbstractIterator() { private T next; private boolean cached = false; private boolean finished = false; @Override public boolean hasNext() { if (cached) { return true; } else if (finished) { return false; } else if (that.hasNext()) { next = that.next(); if (predicate.test(next)) { cached = true; return true; } } finished = true; return false; } @Override public T getNext() { cached = false; return next; } }; } } } interface IteratorModule { // inspired by Scala's ConcatIterator final class ConcatIterator extends AbstractIterator { private static class Cell { Iterator it; Cell next; static Cell of(Iterator it) { Cell cell = new Cell<>(); cell.it = it; return cell; } Cell append(Iterator it) { Cell cell = of(it); next = cell; return cell; } } private Iterator curr; private Cell tail; private Cell last; private boolean hasNextCalculated; void append(java.util.Iterator that) { final Iterator it = Iterator.ofAll(that); if (tail == null) { tail = last = Cell.of(it); } else { last = last.append(it); } } @Override public Iterator concat(java.util.Iterator that) { append(that); return this; } @Override public boolean hasNext() { if (hasNextCalculated) { return curr != null; } hasNextCalculated = true; while(true) { if (curr != null) { if (curr.hasNext()) { return true; } else { curr = null; } } if (tail == null) { return false; } curr = tail.it; tail = tail.next; while (curr instanceof ConcatIterator) { ConcatIterator it = (ConcatIterator) curr; curr = it.curr; it.last.next = tail; tail = it.tail; } } } @Override public T getNext() { hasNextCalculated = false; return curr.next(); } } final class DistinctIterator extends AbstractIterator { private final Iterator that; private io.vavr.collection.Set known; private final Function keyExtractor; private T next = null; DistinctIterator(Iterator that, Set set, Function keyExtractor) { this.that = that; this.known = set; this.keyExtractor = keyExtractor; } @Override public boolean hasNext() { while (next == null && that.hasNext()) { final T elem = that.next(); final U key = keyExtractor.apply(elem); if (!known.contains(key)) { known = known.add(key); next = elem; } } return next != null; } @Override public T getNext() { final T result = next; next = null; return result; } } final class EmptyIterator implements Iterator { static final EmptyIterator INSTANCE = new EmptyIterator(); @Override public boolean hasNext() { return false; } @Override public Object next() { throw new NoSuchElementException(stringPrefix() + ".next()"); } @Override public String stringPrefix() { return "EmptyIterator"; } @Override public String toString() { return stringPrefix() + "()"; } } final class GroupedIterator implements Iterator> { private final Iterator that; private final int size; private final int step; private final int gap; private final int preserve; private Object[] buffer; GroupedIterator(Iterator that, int size, int step) { if (size < 1 || step < 1) { throw new IllegalArgumentException("size (" + size + ") and step (" + step + ") must both be positive"); } this.that = that; this.size = size; this.step = step; this.gap = Math.max(step - size, 0); this.preserve = Math.max(size - step, 0); this.buffer = take(that, new Object[size], 0, size); } @Override public boolean hasNext() { return buffer.length > 0; } @Override public Seq next() { if (buffer.length == 0) { throw new NoSuchElementException(); } final Object[] result = buffer; if (that.hasNext()) { buffer = new Object[size]; if (preserve > 0) { System.arraycopy(result, step, buffer, 0, preserve); } if (gap > 0) { drop(that, gap); buffer = take(that, buffer, preserve, size); } else { buffer = take(that, buffer, preserve, step); } } else { buffer = new Object[0]; } return Array.wrap(result); } private static void drop(Iterator source, int count) { for (int i = 0; i < count && source.hasNext(); i++) { source.next(); } } private static Object[] take(Iterator source, Object[] target, int offset, int count) { int i = offset; while (i < count + offset && source.hasNext()) { target[i] = source.next(); i++; } if (i < target.length) { final Object[] result = new Object[i]; System.arraycopy(target, 0, result, 0, i); return result; } else { return target; } } } final class CachedIterator extends AbstractIterator { private final Iterator that; private T next; private boolean cached = false; CachedIterator(Iterator that) { this.that = that; } @Override public boolean hasNext() { return cached || that.hasNext(); } @Override public T getNext() { if (cached) { T result = next; next = null; cached = false; return result; } else { return that.next(); } } T touch() { next = next(); cached = true; return next; } } final class BigDecimalHelper { @GwtIncompatible("Math::nextDown is not implemented") private static final Lazy INFINITY_DISTANCE = Lazy.of(() -> { final BigDecimal two = BigDecimal.valueOf(2); final BigDecimal supremum = BigDecimal.valueOf(Math.nextDown(Double.POSITIVE_INFINITY)); BigDecimal lowerBound = supremum; BigDecimal upperBound = two.pow(Double.MAX_EXPONENT + 1); while (true) { final BigDecimal magicValue = lowerBound.add(upperBound).divide(two, HALF_UP); if (Double.isInfinite(magicValue.doubleValue())) { if (areEqual(magicValue, upperBound)) { return magicValue.subtract(supremum); } upperBound = magicValue; } else { lowerBound = magicValue; } } }); /* scale-independent equality */ static boolean areEqual(BigDecimal from, BigDecimal toExclusive) { return from.compareTo(toExclusive) == 0; } /* parse infinite values also */ @GwtIncompatible("Math::nextUp is not implemented") static BigDecimal asDecimal(double number) { if (number == NEGATIVE_INFINITY) { final BigDecimal result = BigDecimal.valueOf(Math.nextUp(NEGATIVE_INFINITY)); return result.subtract(INFINITY_DISTANCE.get()); } else if (number == POSITIVE_INFINITY) { final BigDecimal result = BigDecimal.valueOf(Math.nextDown(POSITIVE_INFINITY)); return result.add(INFINITY_DISTANCE.get()); } else { return BigDecimal.valueOf(number); } } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/JavaConverters.java000066400000000000000000000361631342074374400255200ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import java.io.Serializable; import java.util.*; import java.util.function.Consumer; import java.util.function.Supplier; /** * THIS CLASS IS INTENDED TO BE USED INTERNALLY ONLY! *

* This helper class provides methods that return views on Java collections. * The view creation and back conversion take O(1). * * @author Daniel Dietrich */ class JavaConverters { private JavaConverters() { } @GwtIncompatible static > ListView asJava(C seq, ChangePolicy changePolicy) { return new ListView<>(seq, changePolicy.isMutable()); } enum ChangePolicy { IMMUTABLE, MUTABLE; boolean isMutable() { return this == MUTABLE; } } // -- private view implementations /** * Encapsulates the access to delegate and performs mutability checks. * * @param The Vavr collection type */ private static abstract class HasDelegate> implements Serializable { private static final long serialVersionUID = 1L; private C delegate; private final boolean mutable; HasDelegate(C delegate, boolean mutable) { this.delegate = delegate; this.mutable = mutable; } protected boolean isMutable() { return mutable; } C getDelegate() { return delegate; } protected boolean setDelegateAndCheckChanged(Supplier delegate) { ensureMutable(); final C previousDelegate = this.delegate; final C newDelegate = delegate.get(); final boolean changed = newDelegate.size() != previousDelegate.size(); if (changed) { this.delegate = newDelegate; } return changed; } protected void setDelegate(Supplier newDelegate) { ensureMutable(); this.delegate = newDelegate.get(); } protected void ensureMutable() { if (!mutable) { throw new UnsupportedOperationException(); } } } @GwtIncompatible("reflection is not supported") static class ListView> extends HasDelegate implements java.util.List { private static final long serialVersionUID = 1L; ListView(C delegate, boolean mutable) { super(delegate, mutable); } @SuppressWarnings("unchecked") @Override public boolean add(T element) { setDelegate(() -> (C) getDelegate().append(element)); return true; } @SuppressWarnings("unchecked") @Override public void add(int index, T element) { setDelegate(() -> (C) getDelegate().insert(index, element)); } @SuppressWarnings("unchecked") @Override public boolean addAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); return setDelegateAndCheckChanged(() -> (C) getDelegate().appendAll(collection)); } @SuppressWarnings("unchecked") @Override public boolean addAll(int index, Collection collection) { Objects.requireNonNull(collection, "collection is null"); return setDelegateAndCheckChanged(() -> (C) getDelegate().insertAll(index, collection)); } @SuppressWarnings("unchecked") @Override public void clear() { // DEV-NOTE: acts like Java: works for empty immutable collections if (isEmpty()) { return; } setDelegate(() -> (C) getDelegate().take(0)); } @Override public boolean contains(Object obj) { @SuppressWarnings("unchecked") final T that = (T) obj; return getDelegate().contains(that); } @Override public boolean containsAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); @SuppressWarnings("unchecked") final Collection that = (Collection) collection; return getDelegate().containsAll(that); } @Override public T get(int index) { return getDelegate().get(index); } @Override public int indexOf(Object obj) { @SuppressWarnings("unchecked") final T that = (T) obj; return getDelegate().indexOf(that); } @Override public boolean isEmpty() { return getDelegate().isEmpty(); } @Override public java.util.Iterator iterator() { return new Iterator<>(this); } @Override public int lastIndexOf(Object obj) { @SuppressWarnings("unchecked") final T that = (T) obj; return getDelegate().lastIndexOf(that); } @Override public java.util.ListIterator listIterator() { return new ListIterator<>(this, 0); } @Override public java.util.ListIterator listIterator(int index) { return new ListIterator<>(this, index); } @SuppressWarnings("unchecked") @Override public T remove(int index) { return setDelegateAndGetPreviousElement(index, () -> (C) getDelegate().removeAt(index)); } @SuppressWarnings("unchecked") @Override public boolean remove(Object obj) { final T that = (T) obj; return setDelegateAndCheckChanged(() -> (C) getDelegate().remove(that)); } @SuppressWarnings("unchecked") @Override public boolean removeAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); @SuppressWarnings("unchecked") final Collection that = (Collection) collection; return setDelegateAndCheckChanged(() -> (C) getDelegate().removeAll(that)); } @SuppressWarnings("unchecked") @Override public boolean retainAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); @SuppressWarnings("unchecked") final Collection that = (Collection) collection; return setDelegateAndCheckChanged(() -> (C) getDelegate().retainAll(that)); } @SuppressWarnings("unchecked") @Override public T set(int index, T element) { return setDelegateAndGetPreviousElement(index, () -> (C) getDelegate().update(index, element)); } @Override public int size() { return getDelegate().size(); } @SuppressWarnings("unchecked") @Override public void sort(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); if (isEmpty()) { return; } setDelegate(() -> (C) getDelegate().sorted(comparator)); } @Override public java.util.List subList(int fromIndex, int toIndex) { return new ListView<>(getDelegate().subSequence(fromIndex, toIndex), isMutable()); } @Override public Object[] toArray() { return getDelegate().toJavaArray(); } @SuppressWarnings("unchecked") @Override public U[] toArray(U[] array) { Objects.requireNonNull(array, "array is null"); final U[] target; final C delegate = getDelegate(); final int length = delegate.length(); if (array.length < length) { final Class newType = array.getClass(); target = (newType == Object[].class) ? (U[]) new Object[length] : (U[]) java.lang.reflect.Array.newInstance(newType.getComponentType(), length); } else { if (array.length > length) { array[length] = null; } target = array; } final java.util.Iterator iter = delegate.iterator(); for (int i = 0; i < length; i++) { target[i] = (U) iter.next(); } return target; } // -- Object.* @Override public boolean equals(Object o) { return o == this || o instanceof java.util.List && Collections.areEqual(getDelegate(), (java.util.List) o); } @Override public int hashCode() { // DEV-NOTE: Ensures that hashCode calculation is stable, regardless of delegate.hashCode() return Collections.hashOrdered(getDelegate()); } @Override public String toString() { return getDelegate().mkString("[", ", ", "]"); } // -- private helpers private T setDelegateAndGetPreviousElement(int index, Supplier delegate) { ensureMutable(); final T previousElement = getDelegate().get(index); setDelegate(delegate); return previousElement; } // DEV-NOTE: Iterator is intentionally not Serializable private static class Iterator> implements java.util.Iterator { ListView list; int expectedSize; int nextIndex = 0; int lastIndex = -1; Iterator(ListView list) { this.list = list; expectedSize = list.size(); } @Override public boolean hasNext() { return nextIndex != list.size(); } @Override public T next() { checkForComodification(); if (nextIndex >= list.size()) { throw new NoSuchElementException(); } try { return list.get(lastIndex = nextIndex++); } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void remove() { list.ensureMutable(); if (lastIndex < 0) { throw new IllegalStateException(); } checkForComodification(); try { list.remove(nextIndex = lastIndex); lastIndex = -1; expectedSize = list.size(); } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void forEachRemaining(Consumer consumer) { Objects.requireNonNull(consumer, "consumer is null"); checkForComodification(); if (nextIndex >= list.size()) { return; } int index = nextIndex; // DEV-NOTE: intentionally not using hasNext() and next() in order not to modify internal state while (expectedSize == list.size() && index < expectedSize) { consumer.accept(list.get(index++)); } nextIndex = index; lastIndex = index - 1; checkForComodification(); } final void checkForComodification() { if (expectedSize != list.size()) { throw new ConcurrentModificationException(); } } } // DEV-NOTE: ListIterator is intentionally not Serializable private static class ListIterator> extends ListView.Iterator implements java.util.ListIterator { ListIterator(ListView list, int index) { super(list); if (index < 0 || index > list.size()) { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + list.size()); } this.nextIndex = index; } @Override public boolean hasPrevious() { return nextIndex != 0; } @Override public int nextIndex() { return nextIndex; } @Override public int previousIndex() { return nextIndex - 1; } @Override public T previous() { checkForComodification(); final int index = nextIndex - 1; if (index < 0) { throw new NoSuchElementException(); } if (index >= list.size()) { throw new ConcurrentModificationException(); } try { final T element = list.get(index); // DEV-NOTE: intentionally updating indices _after_ reading the element. This makes a difference in case of a concurrent modification. lastIndex = nextIndex = index; return element; } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void set(T element) { list.ensureMutable(); if (lastIndex < 0) { throw new IllegalStateException(); } checkForComodification(); try { list.set(lastIndex, element); } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void add(T element) { list.ensureMutable(); checkForComodification(); try { final int index = nextIndex; list.add(index, element); // DEV-NOTE: intentionally increasing nextIndex _after_ adding the element. This makes a difference in case of a concurrent modification. nextIndex = index + 1; lastIndex = -1; expectedSize = list.size(); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/LinearSeq.java000066400000000000000000000372701342074374400244470ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.control.Option; import io.vavr.Tuple2; import java.util.Comparator; import java.util.Objects; import java.util.function.*; /** * Interface for immutable, linear sequences. *

* Efficient {@code head()}, {@code tail()}, and {@code isEmpty()} methods are characteristic for linear sequences. * * @param component type * @author Daniel Dietrich */ public interface LinearSeq extends Seq { long serialVersionUID = 1L; /** * Narrows a widened {@code LinearSeq} to {@code LinearSeq} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param linearSeq A {@code LinearSeq}. * @param Component type of the {@code LinearSeq}. * @return the given {@code linearSeq} instance as narrowed type {@code LinearSeq}. */ @SuppressWarnings("unchecked") static LinearSeq narrow(LinearSeq linearSeq) { return (LinearSeq) linearSeq; } // -- Adjusted return types of Seq methods @Override LinearSeq append(T element); @Override LinearSeq appendAll(Iterable elements); @GwtIncompatible @Override LinearSeq asJava(Consumer> action); @GwtIncompatible @Override LinearSeq asJavaMutable(Consumer> action); @Override default PartialFunction asPartialFunction() throws IndexOutOfBoundsException { return new PartialFunction() { private static final long serialVersionUID = 1L; @Override public T apply(Integer index) { return get(index); } @Override public boolean isDefinedAt(Integer index) { // we can't use length() because of infinite long sequences return 0 <= index && drop(index).nonEmpty(); } }; } @Override LinearSeq collect(PartialFunction partialFunction); @Override LinearSeq> combinations(); @Override LinearSeq> combinations(int k); @Override Iterator> crossProduct(int power); @Override LinearSeq distinct(); @Override LinearSeq distinctBy(Comparator comparator); @Override LinearSeq distinctBy(Function keyExtractor); @Override LinearSeq drop(int n); @Override LinearSeq dropUntil(Predicate predicate); @Override LinearSeq dropWhile(Predicate predicate); @Override LinearSeq dropRight(int n); @Override LinearSeq dropRightUntil(Predicate predicate); @Override LinearSeq dropRightWhile(Predicate predicate); @Override LinearSeq filter(Predicate predicate); @Override LinearSeq reject(Predicate predicate); @Override LinearSeq flatMap(Function> mapper); @Override Map> groupBy(Function classifier); @Override Iterator> grouped(int size); @Override default int indexOfSlice(Iterable that, int from) { Objects.requireNonNull(that, "that is null"); return LinearSeqModule.Slice.indexOfSlice(this, that, from); } @Override default int indexWhere(Predicate predicate, int from) { Objects.requireNonNull(predicate, "predicate is null"); int i = from; LinearSeq these = drop(from); while (!these.isEmpty()) { if (predicate.test(these.head())) { return i; } i++; these = these.tail(); } return -1; } @Override LinearSeq init(); @Override Option> initOption(); @Override LinearSeq insert(int index, T element); @Override LinearSeq insertAll(int index, Iterable elements); @Override LinearSeq intersperse(T element); @Deprecated @Override default boolean isDefinedAt(Integer index) { // we can't use length() because of infinite long sequences return 0 <= index && drop(index).nonEmpty(); } @Override default int lastIndexOfSlice(Iterable that, int end) { Objects.requireNonNull(that, "that is null"); return LinearSeqModule.Slice.lastIndexOfSlice(this, that, end); } @Override default int lastIndexWhere(Predicate predicate, int end) { Objects.requireNonNull(predicate, "predicate is null"); int i = 0; LinearSeq these = this; int last = -1; while (!these.isEmpty() && i <= end) { if (predicate.test(these.head())) { last = i; } these = these.tail(); i++; } return last; } @Override LinearSeq map(Function mapper); @Override LinearSeq orElse(Iterable other); @Override LinearSeq orElse(Supplier> supplier); @Override LinearSeq padTo(int length, T element); @Override LinearSeq patch(int from, Iterable that, int replaced); @Override Tuple2, ? extends LinearSeq> partition(Predicate predicate); @Override LinearSeq peek(Consumer action); @Override LinearSeq> permutations(); @Override LinearSeq prepend(T element); @Override LinearSeq prependAll(Iterable elements); @Override LinearSeq remove(T element); @Override LinearSeq removeFirst(Predicate predicate); @Override LinearSeq removeLast(Predicate predicate); @Override LinearSeq removeAt(int index); @Override LinearSeq removeAll(T element); @Override LinearSeq removeAll(Iterable elements); @Override @Deprecated LinearSeq removeAll(Predicate predicate); @Override LinearSeq replace(T currentElement, T newElement); @Override LinearSeq replaceAll(T currentElement, T newElement); @Override LinearSeq retainAll(Iterable elements); @Override LinearSeq reverse(); @Override default Iterator reverseIterator() { return reverse().iterator(); } @Override LinearSeq rotateLeft(int n); @Override LinearSeq rotateRight(int n); @Override LinearSeq shuffle(); @Override LinearSeq scan(T zero, BiFunction operation); @Override LinearSeq scanLeft(U zero, BiFunction operation); @Override LinearSeq scanRight(U zero, BiFunction operation); @Override default int segmentLength(Predicate predicate, int from) { Objects.requireNonNull(predicate, "predicate is null"); int i = 0; LinearSeq these = this.drop(from); while (!these.isEmpty() && predicate.test(these.head())) { i++; these = these.tail(); } return i; } @Override LinearSeq slice(int beginIndex, int endIndex); @Override Iterator> slideBy(Function classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override LinearSeq sorted(); @Override LinearSeq sorted(Comparator comparator); @Override > LinearSeq sortBy(Function mapper); @Override LinearSeq sortBy(Comparator comparator, Function mapper); @Override Tuple2, ? extends LinearSeq> span(Predicate predicate); @Override LinearSeq subSequence(int beginIndex); @Override LinearSeq subSequence(int beginIndex, int endIndex); @Override LinearSeq tail(); @Override Option> tailOption(); @Override LinearSeq take(int n); @Override LinearSeq takeUntil(Predicate predicate); @Override LinearSeq takeWhile(Predicate predicate); @Override LinearSeq takeRight(int n); @Override LinearSeq takeRightUntil(Predicate predicate); @Override LinearSeq takeRightWhile(Predicate predicate); @Override Tuple2, ? extends LinearSeq> unzip(Function> unzipper); @Override LinearSeq update(int index, T element); @Override LinearSeq update(int index, Function updater); @Override LinearSeq> zip(Iterable that); @Override LinearSeq zipWith(Iterable that, BiFunction mapper); @Override LinearSeq> zipAll(Iterable that, T thisElem, U thatElem); @Override LinearSeq> zipWithIndex(); @Override LinearSeq zipWithIndex(BiFunction mapper); /** * Searches this sequence for a specific element using a linear search. The sequence must already be sorted into * ascending natural order. If it is not sorted, the results are undefined. * * @param element the element to find * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. * @throws ClassCastException if T cannot be cast to {@code Comparable} */ @Override @SuppressWarnings("unchecked") default int search(T element) { final ToIntFunction comparison = ((Comparable) element)::compareTo; return LinearSeqModule.Search.linearSearch(this, comparison); } /** * Searches this sequence for a specific element using a linear search. The sequence must already be sorted into * ascending order according to the specified comparator. If it is not sorted, the results are undefined. * * @param element the element to find * @param comparator the comparator by which this sequence is ordered * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. */ @Override default int search(T element, Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final ToIntFunction comparison = current -> comparator.compare(element, current); return LinearSeqModule.Search.linearSearch(this, comparison); } } interface LinearSeqModule { class Slice { static int indexOfSlice(LinearSeq source, Iterable slice, int from) { if (source.isEmpty()) { return from == 0 && Collections.isEmpty(slice) ? 0 : -1; } final LinearSeq _slice = toLinearSeq(slice); return findFirstSlice(source, _slice, Math.max(from, 0)); } static int lastIndexOfSlice(LinearSeq source, Iterable slice, int end) { if (end < 0) { return -1; } else if (source.isEmpty()) { return Collections.isEmpty(slice) ? 0 : -1; } else if (Collections.isEmpty(slice)) { final int len = source.length(); return len < end ? len : end; } int index = 0; int result = -1; final LinearSeq _slice = toLinearSeq(slice); while (source.length() >= _slice.length()) { final Tuple2, Integer> r = findNextSlice(source, _slice); if (r == null) { return result; } if (index + r._2 <= end) { result = index + r._2; index += r._2 + 1; source = r._1.tail(); } else { return result; } } return result; } private static int findFirstSlice(LinearSeq source, LinearSeq slice, int from) { int index = 0; final int sliceLength = slice.length(); // DEV-NOTE: we can't compute the length of an infinite Stream but it may contain a slice final Predicate> hasMore = source.isLazy() ? LinearSeq::nonEmpty : seq -> seq.length() >= sliceLength; while (hasMore.test(source)) { if (index >= from && source.startsWith(slice)) { return index; } index++; source = source.tail(); } return -1; } private static Tuple2, Integer> findNextSlice(LinearSeq source, LinearSeq slice) { int index = 0; while (source.length() >= slice.length()) { if (source.startsWith(slice)) { return Tuple.of(source, index); } index++; source = source.tail(); } return null; } @SuppressWarnings("unchecked") private static LinearSeq toLinearSeq(Iterable iterable) { return (iterable instanceof LinearSeq) ? (LinearSeq) iterable : List.ofAll(iterable); } } interface Search { static int linearSearch(LinearSeq seq, ToIntFunction comparison) { int idx = 0; for (T current : seq) { final int cmp = comparison.applyAsInt(current); if (cmp == 0) { return idx; } else if (cmp < 0) { return -(idx + 1); } idx += 1; } return -(idx + 1); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/LinkedHashMap.java000066400000000000000000001145711342074374400252340ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.Objects; import java.util.function.*; import java.util.stream.Collector; /** * An immutable {@code LinkedHashMap} implementation that has predictable (insertion-order) iteration. * * @author Ruslan Sennov */ public final class LinkedHashMap implements Map, Serializable { private static final long serialVersionUID = 1L; private static final LinkedHashMap EMPTY = new LinkedHashMap<>(Queue.empty(), HashMap.empty()); private final Queue> list; private final HashMap map; private LinkedHashMap(Queue> list, HashMap map) { this.list = list; this.map = map; } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link LinkedHashMap}. * * @param The key type * @param The value type * @return A {@link LinkedHashMap} Collector. */ public static Collector, ArrayList>, LinkedHashMap> collector() { final Supplier>> supplier = ArrayList::new; final BiConsumer>, Tuple2> accumulator = ArrayList::add; final BinaryOperator>> combiner = (left, right) -> { left.addAll(right); return left; }; final Function>, LinkedHashMap> finisher = LinkedHashMap::ofEntries; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link LinkedHashMap}. * * @param keyMapper The key mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @return A {@link LinkedHashMap} Collector. */ public static Collector, LinkedHashMap> collector(Function keyMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); return LinkedHashMap.collector(keyMapper, v -> v); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link LinkedHashMap}. * * @param keyMapper The key mapper * @param valueMapper The value mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @return A {@link LinkedHashMap} Collector. */ public static Collector, LinkedHashMap> collector( Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, LinkedHashMap> finisher = arr -> LinkedHashMap.ofEntries(Iterator.ofAll(arr) .map(t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t)))); return Collector.of(supplier, accumulator, combiner, finisher); } @SuppressWarnings("unchecked") public static LinkedHashMap empty() { return (LinkedHashMap) EMPTY; } /** * Narrows a widened {@code LinkedHashMap} to {@code LinkedHashMap} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param linkedHashMap A {@code LinkedHashMap}. * @param Key type * @param Value type * @return the given {@code linkedHashMap} instance as narrowed type {@code LinkedHashMap}. */ @SuppressWarnings("unchecked") public static LinkedHashMap narrow(LinkedHashMap linkedHashMap) { return (LinkedHashMap) linkedHashMap; } /** * Returns a singleton {@code LinkedHashMap}, i.e. a {@code LinkedHashMap} of one element. * * @param entry A map entry. * @param The key type * @param The value type * @return A new Map containing the given entry */ @SuppressWarnings("unchecked") public static LinkedHashMap of(Tuple2 entry) { final HashMap map = HashMap.of(entry); final Queue> list = Queue.of((Tuple2) entry); return wrap(list, map); } /** * Returns a {@code LinkedHashMap}, from a source java.util.Map. * * @param map A map * @param The key type * @param The value type * @return A new Map containing the given map */ public static LinkedHashMap ofAll(java.util.Map map) { Objects.requireNonNull(map, "map is null"); LinkedHashMap result = LinkedHashMap.empty(); for (java.util.Map.Entry entry : map.entrySet()) { result = result.put(entry.getKey(), entry.getValue()); } return result; } /** * Returns a {@code LinkedHashMap}, from entries mapped from stream. * * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static LinkedHashMap ofAll(java.util.stream.Stream stream, Function> entryMapper) { return Maps.ofStream(empty(), stream, entryMapper); } /** * Returns a {@code LinkedHashMap}, from entries mapped from stream. * * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static LinkedHashMap ofAll(java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Maps.ofStream(empty(), stream, keyMapper, valueMapper); } /** * Returns a singleton {@code LinkedHashMap}, i.e. a {@code LinkedHashMap} of one element. * * @param key A singleton map key. * @param value A singleton map value. * @param The key type * @param The value type * @return A new Map containing the given entry */ public static LinkedHashMap of(K key, V value) { final HashMap map = HashMap.of(key, value); final Queue> list = Queue.of(Tuple.of(key, value)); return wrap(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2) { final HashMap map = HashMap.of(k1, v1, k2, v2); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7), Tuple.of(k8, v8)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7), Tuple.of(k8, v8), Tuple.of(k9, v9)); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7), Tuple.of(k8, v8), Tuple.of(k9, v9), Tuple.of(k10, v10)); return wrapNonUnique(list, map); } /** * Returns a LinkedHashMap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param The key type * @param The value type * @param n The number of elements in the LinkedHashMap * @param f The Function computing element values * @return A LinkedHashMap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ @SuppressWarnings("unchecked") public static LinkedHashMap tabulate(int n, Function> f) { Objects.requireNonNull(f, "f is null"); return ofEntries(Collections.tabulate(n, (Function>) f)); } /** * Returns a LinkedHashMap containing tuples returned by {@code n} calls to a given Supplier {@code s}. * * @param The key type * @param The value type * @param n The number of elements in the LinkedHashMap * @param s The Supplier computing element values * @return A LinkedHashMap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ @SuppressWarnings("unchecked") public static LinkedHashMap fill(int n, Supplier> s) { Objects.requireNonNull(s, "s is null"); return ofEntries(Collections.fill(n, (Supplier>) s)); } /** * Creates a LinkedHashMap of the given entries. * * @param entries Map entries * @param The key type * @param The value type * @return A new Map containing the given entries */ @SuppressWarnings("unchecked") public static LinkedHashMap ofEntries(java.util.Map.Entry... entries) { HashMap map = HashMap.empty(); Queue> list = Queue.empty(); for (java.util.Map.Entry entry : entries) { final Tuple2 tuple = Tuple.of(entry.getKey(), entry.getValue()); map = map.put(tuple); list = list.append(tuple); } return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given entries. * * @param entries Map entries * @param The key type * @param The value type * @return A new Map containing the given entries */ @SuppressWarnings("unchecked") public static LinkedHashMap ofEntries(Tuple2... entries) { final HashMap map = HashMap.ofEntries(entries); final Queue> list = Queue.of((Tuple2[]) entries); return wrapNonUnique(list, map); } /** * Creates a LinkedHashMap of the given entries. * * @param entries Map entries * @param The key type * @param The value type * @return A new Map containing the given entries */ @SuppressWarnings("unchecked") public static LinkedHashMap ofEntries(Iterable> entries) { Objects.requireNonNull(entries, "entries is null"); if (entries instanceof LinkedHashMap) { return (LinkedHashMap) entries; } else { HashMap map = HashMap.empty(); Queue> list = Queue.empty(); for (Tuple2 entry : entries) { map = map.put(entry); list = list.append((Tuple2) entry); } return wrapNonUnique(list, map); } } @Override public LinkedHashMap bimap(Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); final Iterator> entries = iterator().map(entry -> Tuple.of(keyMapper.apply(entry._1), valueMapper.apply(entry._2))); return LinkedHashMap.ofEntries(entries); } @Override public Tuple2> computeIfAbsent(K key, Function mappingFunction) { return Maps.computeIfAbsent(this, key, mappingFunction); } @Override public Tuple2, LinkedHashMap> computeIfPresent(K key, BiFunction remappingFunction) { return Maps.computeIfPresent(this, key, remappingFunction); } @Override public boolean containsKey(K key) { return map.containsKey(key); } @Override public LinkedHashMap distinct() { return Maps.distinct(this); } @Override public LinkedHashMap distinctBy(Comparator> comparator) { return Maps.distinctBy(this, this::createFromEntries, comparator); } @Override public LinkedHashMap distinctBy(Function, ? extends U> keyExtractor) { return Maps.distinctBy(this, this::createFromEntries, keyExtractor); } @Override public LinkedHashMap drop(int n) { return Maps.drop(this, this::createFromEntries, LinkedHashMap::empty, n); } @Override public LinkedHashMap dropRight(int n) { return Maps.dropRight(this, this::createFromEntries, LinkedHashMap::empty, n); } @Override public LinkedHashMap dropUntil(Predicate> predicate) { return Maps.dropUntil(this, this::createFromEntries, predicate); } @Override public LinkedHashMap dropWhile(Predicate> predicate) { return Maps.dropWhile(this, this::createFromEntries, predicate); } @Override public LinkedHashMap filter(BiPredicate predicate) { return Maps.filter(this, this::createFromEntries, predicate); } @Override public LinkedHashMap reject(BiPredicate predicate) { return Maps.reject(this, this::createFromEntries, predicate); } @Override public LinkedHashMap filter(Predicate> predicate) { return Maps.filter(this, this::createFromEntries, predicate); } @Override public LinkedHashMap reject(Predicate> predicate) { return Maps.reject(this, this::createFromEntries, predicate); } @Override public LinkedHashMap filterKeys(Predicate predicate) { return Maps.filterKeys(this, this::createFromEntries, predicate); } @Override public LinkedHashMap rejectKeys(Predicate predicate) { return Maps.rejectKeys(this, this::createFromEntries, predicate); } @Override public LinkedHashMap filterValues(Predicate predicate) { return Maps.filterValues(this, this::createFromEntries, predicate); } @Override public LinkedHashMap rejectValues(Predicate predicate) { return Maps.rejectValues(this, this::createFromEntries, predicate); } @Override public LinkedHashMap flatMap(BiFunction>> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return foldLeft(LinkedHashMap. empty(), (acc, entry) -> { for (Tuple2 mappedEntry : mapper.apply(entry._1, entry._2)) { acc = acc.put(mappedEntry); } return acc; }); } @Override public Option get(K key) { return map.get(key); } @Override public V getOrElse(K key, V defaultValue) { return map.getOrElse(key, defaultValue); } @Override public Map> groupBy(Function, ? extends C> classifier) { return Maps.groupBy(this, this::createFromEntries, classifier); } @Override public Iterator> grouped(int size) { return Maps.grouped(this, this::createFromEntries, size); } @Override public Tuple2 head() { return list.head(); } @Override public LinkedHashMap init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty LinkedHashMap"); } else { return LinkedHashMap.ofEntries(list.init()); } } @Override public Option> initOption() { return Maps.initOption(this); } /** * An {@code LinkedHashMap}'s value is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return map.isEmpty(); } /** * An {@code LinkedHashMap}'s value is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isSequential() { return true; } @Override public Iterator> iterator() { return list.iterator(); } @SuppressWarnings("unchecked") @Override public Set keySet() { return LinkedHashSet.wrap((LinkedHashMap) this); } @Override public Tuple2 last() { return list.last(); } @Override public LinkedHashMap map(BiFunction> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return foldLeft(LinkedHashMap.empty(), (acc, entry) -> acc.put(entry.map(mapper))); } @Override public LinkedHashMap mapKeys(Function keyMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); return map((k, v) -> Tuple.of(keyMapper.apply(k), v)); } @Override public LinkedHashMap mapKeys(Function keyMapper, BiFunction valueMerge) { return Collections.mapKeys(this, LinkedHashMap.empty(), keyMapper, valueMerge); } @Override public LinkedHashMap mapValues(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return map((k, v) -> Tuple.of(k, mapper.apply(v))); } @Override public LinkedHashMap merge(Map that) { return Maps.merge(this, this::createFromEntries, that); } @Override public LinkedHashMap merge(Map that, BiFunction collisionResolution) { return Maps.merge(this, this::createFromEntries, that, collisionResolution); } @Override public LinkedHashMap orElse(Iterable> other) { return isEmpty() ? ofEntries(other) : this; } @Override public LinkedHashMap orElse(Supplier>> supplier) { return isEmpty() ? ofEntries(supplier.get()) : this; } @Override public Tuple2, LinkedHashMap> partition(Predicate> predicate) { return Maps.partition(this, this::createFromEntries, predicate); } @Override public LinkedHashMap peek(Consumer> action) { return Maps.peek(this, action); } @Override public LinkedHashMap put(K key, U value, BiFunction merge) { return Maps.put(this, key, value, merge); } /** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old value is * replaced by the specified value. *

* Note that this method has a worst-case linear complexity. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return A new Map containing these elements and that entry. */ @Override public LinkedHashMap put(K key, V value) { final Queue> newList; final Option currentEntry = get(key); if (currentEntry.isDefined()) { newList = list.replace(Tuple.of(key, currentEntry.get()), Tuple.of(key, value)); } else { newList = list.append(Tuple.of(key, value)); } final HashMap newMap = map.put(key, value); return wrap(newList, newMap); } @Override public LinkedHashMap put(Tuple2 entry) { return Maps.put(this, entry); } @Override public LinkedHashMap put(Tuple2 entry, BiFunction merge) { return Maps.put(this, entry, merge); } @Override public LinkedHashMap remove(K key) { if (containsKey(key)) { final Queue> newList = list.removeFirst(t -> Objects.equals(t._1, key)); final HashMap newMap = map.remove(key); return wrap(newList, newMap); } else { return this; } } @Override @Deprecated public LinkedHashMap removeAll(BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override public LinkedHashMap removeAll(Iterable keys) { Objects.requireNonNull(keys, "keys is null"); final HashSet toRemove = HashSet.ofAll(keys); final Queue> newList = list.filter(t -> !toRemove.contains(t._1)); final HashMap newMap = map.filter(t -> !toRemove.contains(t._1)); return newList.size() == size() ? this : wrap(newList, newMap); } @Override @Deprecated public LinkedHashMap removeKeys(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectKeys(predicate); } @Override @Deprecated public LinkedHashMap removeValues(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectValues(predicate); } @Override public LinkedHashMap replace(Tuple2 currentElement, Tuple2 newElement) { Objects.requireNonNull(currentElement, "currentElement is null"); Objects.requireNonNull(newElement, "newElement is null"); // We replace the whole element, i.e. key and value have to be present. if (!Objects.equals(currentElement, newElement) && contains(currentElement)) { Queue> newList = list; HashMap newMap = map; final K currentKey = currentElement._1; final K newKey = newElement._1; // If current key and new key are equal, the element will be automatically replaced, // otherwise we need to remove the pair (newKey, ?) from the list manually. if (!Objects.equals(currentKey, newKey)) { final Option value = newMap.get(newKey); if (value.isDefined()) { newList = newList.remove(Tuple.of(newKey, value.get())); } } newList = newList.replace(currentElement, newElement); newMap = newMap.remove(currentKey).put(newElement); return wrap(newList, newMap); } else { return this; } } @Override public LinkedHashMap replaceAll(Tuple2 currentElement, Tuple2 newElement) { return Maps.replaceAll(this, currentElement, newElement); } @Override public LinkedHashMap replaceValue(K key, V value) { return Maps.replaceValue(this, key, value); } @Override public LinkedHashMap replace(K key, V oldValue, V newValue) { return Maps.replace(this, key, oldValue, newValue); } @Override public LinkedHashMap replaceAll(BiFunction function) { return Maps.replaceAll(this, function); } @Override public LinkedHashMap retainAll(Iterable> elements) { Objects.requireNonNull(elements, "elements is null"); LinkedHashMap result = empty(); for (Tuple2 entry : elements) { if (contains(entry)) { result = result.put(entry._1, entry._2); } } return result; } @Override public LinkedHashMap scan( Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation) { return Maps.scan(this, zero, operation, this::createFromEntries); } @Override public int size() { return map.size(); } @Override public Iterator> slideBy(Function, ?> classifier) { return Maps.slideBy(this, this::createFromEntries, classifier); } @Override public Iterator> sliding(int size) { return Maps.sliding(this, this::createFromEntries, size); } @Override public Iterator> sliding(int size, int step) { return Maps.sliding(this, this::createFromEntries, size, step); } @Override public Tuple2, LinkedHashMap> span(Predicate> predicate) { return Maps.span(this, this::createFromEntries, predicate); } @Override public LinkedHashMap tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty LinkedHashMap"); } else { return LinkedHashMap.ofEntries(list.tail()); } } @Override public Option> tailOption() { return Maps.tailOption(this); } @Override public LinkedHashMap take(int n) { return Maps.take(this, this::createFromEntries, n); } @Override public LinkedHashMap takeRight(int n) { return Maps.takeRight(this, this::createFromEntries, n); } @Override public LinkedHashMap takeUntil(Predicate> predicate) { return Maps.takeUntil(this, this::createFromEntries, predicate); } @Override public LinkedHashMap takeWhile(Predicate> predicate) { return Maps.takeWhile(this, this::createFromEntries, predicate); } @Override public java.util.LinkedHashMap toJavaMap() { return toJavaMap(java.util.LinkedHashMap::new, t -> t); } @Override public Seq values() { return map(t -> t._2); } @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } private Object readResolve() { return isEmpty() ? EMPTY : this; } @Override public String stringPrefix() { return "LinkedHashMap"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } /** * Construct Map with given values and key order. * * @param list The list of key-value tuples with unique keys. * @param map The map of key-value tuples. * @param The key type * @param The value type * @return A new Map containing the given map with given key order */ private static LinkedHashMap wrap(Queue> list, HashMap map) { return list.isEmpty() ? empty() : new LinkedHashMap<>(list, map); } /** * Construct Map with given values and key order. * * @param list The list of key-value tuples with non-unique keys. * @param map The map of key-value tuples. * @param The key type * @param The value type * @return A new Map containing the given map with given key order */ private static LinkedHashMap wrapNonUnique(Queue> list, HashMap map) { return list.isEmpty() ? empty() : new LinkedHashMap<>(list.reverse().distinctBy(Tuple2::_1).reverse().toQueue(), map); } // We need this method to narrow the argument of `ofEntries`. // If this method is static with type args , the jdk fails to infer types at the call site. private LinkedHashMap createFromEntries(Iterable> tuples) { return LinkedHashMap.ofEntries(tuples); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/LinkedHashMultimap.java000066400000000000000000000524111342074374400263010ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple2; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; /** * A {@link LinkedHashMap}-based implementation of {@link Multimap} * * @param Key type * @param Value type * @author Ruslan Sennov */ public final class LinkedHashMultimap extends AbstractMultimap> implements Serializable { private static final long serialVersionUID = 1L; public static Builder withSeq() { return new Builder<>(ContainerType.SEQ, List::empty); } public static Builder withSet() { return new Builder<>(ContainerType.SET, HashSet::empty); } public static > Builder withSortedSet() { return new Builder<>(ContainerType.SORTED_SET, TreeSet::empty); } public static Builder withSortedSet(Comparator comparator) { return new Builder<>(ContainerType.SORTED_SET, () -> TreeSet.empty(comparator)); } public static class Builder { private final ContainerType containerType; private final SerializableSupplier> emptyContainer; private Builder(ContainerType containerType, SerializableSupplier> emptyContainer) { this.containerType = containerType; this.emptyContainer = emptyContainer; } /** * Returns the empty {@code LinkedHashMultimap}. * * @param The key type * @param The value type * @return A new empty LinkedHashMultimap. */ public LinkedHashMultimap empty() { return new LinkedHashMultimap<>(LinkedHashMap.empty(), containerType, emptyContainer); } /** * Creates a {@code LinkedHashMultimap} of the given entries. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new LinkedHashMultimap containing the given entries. */ public LinkedHashMultimap ofEntries(Iterable> entries) { Objects.requireNonNull(entries, "entries is null"); LinkedHashMultimap result = empty(); for (Tuple2 entry : entries) { result = result.put(entry._1, entry._2); } return result; } /** * Creates a {@code LinkedHashMultimap} of the given entries. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new LinkedHashMultimap containing the given entries. */ @SafeVarargs public final LinkedHashMultimap ofEntries(Tuple2... entries) { Objects.requireNonNull(entries, "entries is null"); LinkedHashMultimap result = empty(); for (Tuple2 entry : entries) { result = result.put(entry._1, entry._2); } return result; } /** * Creates a {@code LinkedHashMultimap} of the given entries. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new LinkedHashMultimap containing the given entries. */ @SafeVarargs public final LinkedHashMultimap ofEntries(java.util.Map.Entry... entries) { Objects.requireNonNull(entries, "entries is null"); LinkedHashMultimap result = empty(); for (java.util.Map.Entry entry : entries) { result = result.put(entry.getKey(), entry.getValue()); } return result; } /** * Returns a {@code LinkedHashMultimap}, from a source java.util.Map. * * @param map A map * @param The key type * @param The value type * @return A new Multimap containing the given map entries */ public LinkedHashMultimap ofAll(java.util.Map map) { return Multimaps.ofJavaMap(empty(), map); } /** * Returns a {@code LinkedHashMultimap}, from entries mapped from stream. * * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Multimap */ public LinkedHashMultimap ofAll(java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Multimaps.ofStream(empty(), stream, keyMapper, valueMapper); } /** * Returns a {@code LinkedHashMultimap}, from entries mapped from stream. * * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new Multimap */ public LinkedHashMultimap ofAll(java.util.stream.Stream stream, Function> entryMapper) { return Multimaps.ofStream(empty(), stream, entryMapper); } /** * Returns a LinkedHashMultimap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param The key type * @param The value type * @param n The number of elements in the LinkedHashMultimap * @param f The Function computing element values * @return A LinkedHashMultimap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ @SuppressWarnings("unchecked") public LinkedHashMultimap tabulate(int n, Function> f) { Objects.requireNonNull(f, "f is null"); return ofEntries(Collections.tabulate(n, (Function>) f)); } /** * Returns a LinkedHashMultimap containing {@code n} values supplied by a given Supplier {@code s}. * * @param The key type * @param The value type * @param n The number of elements in the LinkedHashMultimap * @param s The Supplier computing element values * @return A LinkedHashMultimap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ @SuppressWarnings("unchecked") public LinkedHashMultimap fill(int n, Supplier> s) { Objects.requireNonNull(s, "s is null"); return ofEntries(Collections.fill(n, (Supplier>) s)); } /** * Returns a LinkedHashMultimap containing {@code n} times the given {@code element} * * @param The key type * @param The value type * @param n The number of elements in the LinkedHashMultimap * @param element The element * @return A LinkedHashMultimap of size {@code 1}, where each element contains {@code n} values of {@code element._2}. */ @SuppressWarnings("unchecked") public LinkedHashMultimap fill(int n, Tuple2 element) { return ofEntries(Collections.fillObject(n, element)); } /** * Creates a LinkedHashMultimap of the given key-value pair. * * @param key A singleton map key. * @param value A singleton map value. * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K key, V2 value) { final LinkedHashMultimap e = empty(); return e.put(key, value); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2) { return of(k1, v1).put(k2, v2); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3) { return of(k1, v1, k2, v2).put(k3, v3); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4) { return of(k1, v1, k2, v2, k3, v3).put(k4, v4); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5) { return of(k1, v1, k2, v2, k3, v3, k4, v4).put(k5, v5); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5).put(k6, v6); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6).put(k7, v7); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7).put(k8, v8); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8).put(k9, v9); } /** * Creates a LinkedHashMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public LinkedHashMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9, K k10, V2 v10) { return of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9).put(k10, v10); } /** * Creates a LinkedHashMultimap of the given key-value pair. * Returns a singleton {@code LinkedHashMultimap}, i.e. a {@code LinkedHashMultimap} of one entry. * * @param The key type * @param The value type * @param entry A tuple containing the key-value pair. * @return A new LinkedHashMultimap containing the given entry. */ public LinkedHashMultimap of(Tuple2 entry) { final LinkedHashMultimap e = empty(); return e.put(entry._1, entry._2); } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a * {@link LinkedHashMultimap}. * * @param The key type * @param The value type * @return A {@link LinkedHashMultimap} Collector. */ public Collector, ArrayList>, Multimap> collector() { final Supplier>> supplier = ArrayList::new; final BiConsumer>, Tuple2> accumulator = ArrayList::add; final BinaryOperator>> combiner = (left, right) -> { left.addAll(right); return left; }; return Collector.of(supplier, accumulator, combiner, this::ofEntries); } } /** * Narrows a widened {@code HashMultimap} to {@code HashMultimap} * by performing a type safe-cast. This is eligible because immutable/read-only * collections are covariant. * * @param map A {@code Map}. * @param Key type * @param Value type * @return the given {@code multimap} instance as narrowed type {@code Multimap}. */ @SuppressWarnings("unchecked") public static LinkedHashMultimap narrow(LinkedHashMultimap map) { return (LinkedHashMultimap) map; } private LinkedHashMultimap(Map> back, ContainerType containerType, SerializableSupplier> emptyContainer) { super(back, containerType, emptyContainer); } @Override protected Map emptyMapSupplier() { return LinkedHashMap.empty(); } @SuppressWarnings("unchecked") @Override protected LinkedHashMultimap emptyInstance() { return new LinkedHashMultimap<>(LinkedHashMap.empty(), getContainerType(), emptyContainer); } @Override protected LinkedHashMultimap createFromMap(Map> back) { return new LinkedHashMultimap<>(back, getContainerType(), emptyContainer); } @Override public boolean isSequential() { return true; } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/LinkedHashSet.java000066400000000000000000001155721342074374400252540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.io.*; import java.util.ArrayList; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.*; import java.util.stream.Collector; /** * An immutable {@code HashSet} implementation that has predictable (insertion-order) iteration. * * @param Component type * @author Ruslan Sennov, Patryk Najda, Daniel Dietrich */ public final class LinkedHashSet implements Set, Serializable { private static final long serialVersionUID = 1L; private static final LinkedHashSet EMPTY = new LinkedHashSet<>(LinkedHashMap.empty()); private final LinkedHashMap map; private LinkedHashSet(LinkedHashMap map) { this.map = map; } @SuppressWarnings("unchecked") public static LinkedHashSet empty() { return (LinkedHashSet) EMPTY; } static LinkedHashSet wrap(LinkedHashMap map) { return new LinkedHashSet<>(map); } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a {@link LinkedHashSet}. * * @param Component type of the LinkedHashSet. * @return A io.vavr.collection.LinkedHashSet Collector. */ public static Collector, LinkedHashSet> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, LinkedHashSet> finisher = LinkedHashSet::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Narrows a widened {@code LinkedHashSet} to {@code LinkedHashSet} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param linkedHashSet A {@code LinkedHashSet}. * @param Component type of the {@code linkedHashSet}. * @return the given {@code linkedHashSet} instance as narrowed type {@code LinkedHashSet}. */ @SuppressWarnings("unchecked") public static LinkedHashSet narrow(LinkedHashSet linkedHashSet) { return (LinkedHashSet) linkedHashSet; } /** * Returns a singleton {@code LinkedHashSet}, i.e. a {@code LinkedHashSet} of one element. * * @param element An element. * @param The component type * @return A new LinkedHashSet instance containing the given element */ public static LinkedHashSet of(T element) { return LinkedHashSet. empty().add(element); } /** * Creates a LinkedHashSet of the given elements. * *

LinkedHashSet.of(1, 2, 3, 4)
* * @param Component type of the LinkedHashSet. * @param elements Zero or more elements. * @return A set containing the given elements. * @throws NullPointerException if {@code elements} is null */ @SafeVarargs public static LinkedHashSet of(T... elements) { Objects.requireNonNull(elements, "elements is null"); LinkedHashMap map = LinkedHashMap.empty(); for (T element : elements) { map = map.put(element, element); } return map.isEmpty() ? LinkedHashSet.empty() : new LinkedHashSet<>(map); } /** * Returns a LinkedHashSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the LinkedHashSet * @param n The number of elements in the LinkedHashSet * @param f The Function computing element values * @return A LinkedHashSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static LinkedHashSet tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f, LinkedHashSet.empty(), LinkedHashSet::of); } /** * Returns a LinkedHashSet containing tuples returned by {@code n} calls to a given Supplier {@code s}. * * @param Component type of the LinkedHashSet * @param n The number of elements in the LinkedHashSet * @param s The Supplier computing element values * @return A LinkedHashSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static LinkedHashSet fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s, LinkedHashSet.empty(), LinkedHashSet::of); } /** * Creates a LinkedHashSet of the given elements. * * @param elements Set elements * @param The value type * @return A new LinkedHashSet containing the given entries */ @SuppressWarnings("unchecked") public static LinkedHashSet ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof LinkedHashSet) { return (LinkedHashSet) elements; } else { final LinkedHashMap mao = addAll(LinkedHashMap.empty(), elements); return mao.isEmpty() ? empty() : new LinkedHashSet<>(mao); } } /** * Creates a LinkedHashSet that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return A LinkedHashSet containing the given elements in the same order. */ public static LinkedHashSet ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return ofAll(Iterator.ofAll(javaStream.iterator())); } /** * Creates a LinkedHashSet from boolean values. * * @param elements boolean values * @return A new LinkedHashSet of Boolean values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet from byte values. * * @param elements byte values * @return A new LinkedHashSet of Byte values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet from char values. * * @param elements char values * @return A new LinkedHashSet of Character values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet from double values. * * @param elements double values * @return A new LinkedHashSet of Double values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet from float values. * * @param elements a float values * @return A new LinkedHashSet of Float values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet from int values. * * @param elements int values * @return A new LinkedHashSet of Integer values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet from long values. * * @param elements long values * @return A new LinkedHashSet of Long values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet from short values. * * @param elements short values * @return A new LinkedHashSet of Short values * @throws NullPointerException if elements is null */ public static LinkedHashSet ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return LinkedHashSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * LinkedHashSet.range(0, 0)  // = LinkedHashSet()
     * LinkedHashSet.range(2, 0)  // = LinkedHashSet()
     * LinkedHashSet.range(-2, 2) // = LinkedHashSet(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ public static LinkedHashSet range(int from, int toExclusive) { return LinkedHashSet.ofAll(Iterator.range(from, toExclusive)); } public static LinkedHashSet range(char from, char toExclusive) { return LinkedHashSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeBy(1, 3, 1)  // = LinkedHashSet(1, 2)
     * LinkedHashSet.rangeBy(1, 4, 2)  // = LinkedHashSet(1, 3)
     * LinkedHashSet.rangeBy(4, 1, -2) // = LinkedHashSet(4, 2)
     * LinkedHashSet.rangeBy(4, 1, 2)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeBy(int from, int toExclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static LinkedHashSet rangeBy(char from, char toExclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } @GwtIncompatible public static LinkedHashSet rangeBy(double from, double toExclusive, double step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * LinkedHashSet.range(0L, 0L)  // = LinkedHashSet()
     * LinkedHashSet.range(2L, 0L)  // = LinkedHashSet()
     * LinkedHashSet.range(-2L, 2L) // = LinkedHashSet(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ public static LinkedHashSet range(long from, long toExclusive) { return LinkedHashSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeBy(1L, 3L, 1L)  // = LinkedHashSet(1L, 2L)
     * LinkedHashSet.rangeBy(1L, 4L, 2L)  // = LinkedHashSet(1L, 3L)
     * LinkedHashSet.rangeBy(4L, 1L, -2L) // = LinkedHashSet(4L, 2L)
     * LinkedHashSet.rangeBy(4L, 1L, 2L)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeBy(long from, long toExclusive, long step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosed(0, 0)  // = LinkedHashSet(0)
     * LinkedHashSet.rangeClosed(2, 0)  // = LinkedHashSet()
     * LinkedHashSet.rangeClosed(-2, 2) // = LinkedHashSet(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ public static LinkedHashSet rangeClosed(int from, int toInclusive) { return LinkedHashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } public static LinkedHashSet rangeClosed(char from, char toInclusive) { return LinkedHashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosedBy(1, 3, 1)  // = LinkedHashSet(1, 2, 3)
     * LinkedHashSet.rangeClosedBy(1, 4, 2)  // = LinkedHashSet(1, 3)
     * LinkedHashSet.rangeClosedBy(4, 1, -2) // = LinkedHashSet(4, 2)
     * LinkedHashSet.rangeClosedBy(4, 1, 2)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeClosedBy(int from, int toInclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } public static LinkedHashSet rangeClosedBy(char from, char toInclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @GwtIncompatible public static LinkedHashSet rangeClosedBy(double from, double toInclusive, double step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosed(0L, 0L)  // = LinkedHashSet(0L)
     * LinkedHashSet.rangeClosed(2L, 0L)  // = LinkedHashSet()
     * LinkedHashSet.rangeClosed(-2L, 2L) // = LinkedHashSet(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ public static LinkedHashSet rangeClosed(long from, long toInclusive) { return LinkedHashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosedBy(1L, 3L, 1L)  // = LinkedHashSet(1L, 2L, 3L)
     * LinkedHashSet.rangeClosedBy(1L, 4L, 2L)  // = LinkedHashSet(1L, 3L)
     * LinkedHashSet.rangeClosedBy(4L, 1L, -2L) // = LinkedHashSet(4L, 2L)
     * LinkedHashSet.rangeClosedBy(4L, 1L, 2L)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeClosedBy(long from, long toInclusive, long step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Add the given element to this set, replacing existing one if it is already contained. *

* Note that this method has a worst-case linear complexity. * * @param element The element to be added. * @return A new set containing all elements of this set and also {@code element}. */ @Override public LinkedHashSet add(T element) { return contains(element) ? this : new LinkedHashSet<>(map.put(element, element)); } /** * Adds all of the given elements to this set, replacing existing one if they are not already contained. *

* Note that this method has a worst-case quadratic complexity. * * @param elements The elements to be added. * @return A new set containing all elements of this set and the given {@code elements}, if not already contained. */ @Override public LinkedHashSet addAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() && elements instanceof LinkedHashSet) { @SuppressWarnings("unchecked") final LinkedHashSet set = (LinkedHashSet) elements; return set; } final LinkedHashMap that = addAll(map, elements); if (that.size() == map.size()) { return this; } else { return new LinkedHashSet<>(that); } } @Override public LinkedHashSet collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } @Override public boolean contains(T element) { return map.get(element).isDefined(); } @Override public LinkedHashSet diff(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() || elements.isEmpty()) { return this; } else { return removeAll(elements); } } @Override public LinkedHashSet distinct() { return this; } @Override public LinkedHashSet distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return LinkedHashSet.ofAll(iterator().distinctBy(comparator)); } @Override public LinkedHashSet distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return LinkedHashSet.ofAll(iterator().distinctBy(keyExtractor)); } @Override public LinkedHashSet drop(int n) { if (n <= 0) { return this; } else { return LinkedHashSet.ofAll(iterator().drop(n)); } } @Override public LinkedHashSet dropRight(int n) { if (n <= 0) { return this; } else { return LinkedHashSet.ofAll(iterator().dropRight(n)); } } @Override public LinkedHashSet dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override public LinkedHashSet dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final LinkedHashSet dropped = LinkedHashSet.ofAll(iterator().dropWhile(predicate)); return dropped.length() == length() ? this : dropped; } @Override public LinkedHashSet filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final LinkedHashSet filtered = LinkedHashSet.ofAll(iterator().filter(predicate)); return filtered.length() == length() ? this : filtered; } @Override public LinkedHashSet reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(predicate.negate()); } @Override public LinkedHashSet flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final LinkedHashMap that = foldLeft(LinkedHashMap.empty(), (tree, t) -> addAll(tree, mapper.apply(t))); return new LinkedHashSet<>(that); } } @Override public U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return iterator().foldRight(zero, f); } @Override public Map> groupBy(Function classifier) { return Collections.groupBy(this, classifier, LinkedHashSet::ofAll); } @Override public Iterator> grouped(int size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public T head() { if (map.isEmpty()) { throw new NoSuchElementException("head of empty set"); } return iterator().next(); } @Override public Option headOption() { return iterator().headOption(); } @Override public LinkedHashSet init() { if (map.isEmpty()) { throw new UnsupportedOperationException("tail of empty set"); } else { return new LinkedHashSet<>(map.init()); } } @Override public Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override public LinkedHashSet intersect(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() || elements.isEmpty()) { return empty(); } else { return retainAll(elements); } } /** * An {@code LinkedHashSet}'s value is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return map.isEmpty(); } /** * An {@code LinkedHashSet}'s value is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } @Override public boolean isSequential() { return true; } @Override public Iterator iterator() { return map.iterator().map(t -> t._1); } @Override public T last() { return map.last()._1; } @Override public int length() { return map.size(); } @Override public LinkedHashSet map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final LinkedHashMap that = foldLeft(LinkedHashMap.empty(), (tree, t) -> { final U u = mapper.apply(t); return tree.put(u, u); }); return new LinkedHashSet<>(that); } } @Override public String mkString(CharSequence prefix, CharSequence delimiter, CharSequence suffix) { return iterator().mkString(prefix, delimiter, suffix); } @Override public LinkedHashSet orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override public LinkedHashSet orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override public Tuple2, LinkedHashSet> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2, Iterator> p = iterator().partition(predicate); return Tuple.of(LinkedHashSet.ofAll(p._1), LinkedHashSet.ofAll(p._2)); } @Override public LinkedHashSet peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(iterator().head()); } return this; } @Override public LinkedHashSet remove(T element) { final LinkedHashMap newMap = map.remove(element); return (newMap == map) ? this : new LinkedHashSet<>(newMap); } @Override public LinkedHashSet removeAll(Iterable elements) { return Collections.removeAll(this, elements); } @Override public LinkedHashSet replace(T currentElement, T newElement) { if (!Objects.equals(currentElement, newElement) && contains(currentElement)) { final Tuple2 currentPair = Tuple.of(currentElement, currentElement); final Tuple2 newPair = Tuple.of(newElement, newElement); final LinkedHashMap newMap = map.replace(currentPair, newPair); return new LinkedHashSet<>(newMap); } else { return this; } } @Override public LinkedHashSet replaceAll(T currentElement, T newElement) { return replace(currentElement, newElement); } @Override public LinkedHashSet retainAll(Iterable elements) { return Collections.retainAll(this, elements); } @Override public LinkedHashSet scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override public LinkedHashSet scanLeft(U zero, BiFunction operation) { return Collections.scanLeft(this, zero, operation, LinkedHashSet::ofAll); } @Override public LinkedHashSet scanRight(U zero, BiFunction operation) { return Collections.scanRight(this, zero, operation, LinkedHashSet::ofAll); } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(LinkedHashSet::ofAll); } @Override public Iterator> sliding(int size) { return sliding(size, 1); } @Override public Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(LinkedHashSet::ofAll); } @Override public Tuple2, LinkedHashSet> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2, Iterator> t = iterator().span(predicate); return Tuple.of(LinkedHashSet.ofAll(t._1), LinkedHashSet.ofAll(t._2)); } @Override public LinkedHashSet tail() { if (map.isEmpty()) { throw new UnsupportedOperationException("tail of empty set"); } return remove(head()); } @Override public Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override public LinkedHashSet take(int n) { if (map.size() <= n) { return this; } return LinkedHashSet.ofAll(() -> iterator().take(n)); } @Override public LinkedHashSet takeRight(int n) { if (map.size() <= n) { return this; } return LinkedHashSet.ofAll(() -> iterator().takeRight(n)); } @Override public LinkedHashSet takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override public LinkedHashSet takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final LinkedHashSet taken = LinkedHashSet.ofAll(iterator().takeWhile(predicate)); return taken.length() == length() ? this : taken; } /** * Transforms this {@code LinkedHashSet}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public java.util.LinkedHashSet toJavaSet() { return toJavaSet(java.util.LinkedHashSet::new); } /** * Adds all of the elements of {@code elements} to this set, replacing existing ones if they already present. *

* Note that this method has a worst-case quadratic complexity. *

* See also {@link #addAll(Iterable)}. * * @param elements The set to form the union with. * @return A new set that contains all distinct elements of this and {@code elements} set. */ @SuppressWarnings("unchecked") @Override public LinkedHashSet union(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { if (elements instanceof LinkedHashSet) { return (LinkedHashSet) elements; } else { return LinkedHashSet.ofAll(elements); } } else if (elements.isEmpty()) { return this; } else { final LinkedHashMap that = addAll(map, elements); if (that.size() == map.size()) { return this; } else { return new LinkedHashSet<>(that); } } } @Override public Tuple2, LinkedHashSet> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Tuple2, Iterator> t = iterator().unzip(unzipper); return Tuple.of(LinkedHashSet.ofAll(t._1), LinkedHashSet.ofAll(t._2)); } @Override public Tuple3, LinkedHashSet, LinkedHashSet> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Tuple3, Iterator, Iterator> t = iterator().unzip3(unzipper); return Tuple.of(LinkedHashSet.ofAll(t._1), LinkedHashSet.ofAll(t._2), LinkedHashSet.ofAll(t._3)); } @Override public LinkedHashSet> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public LinkedHashSet zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return LinkedHashSet.ofAll(iterator().zipWith(that, mapper)); } @Override public LinkedHashSet> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return LinkedHashSet.ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public LinkedHashSet> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public LinkedHashSet zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return LinkedHashSet.ofAll(iterator().zipWithIndex(mapper)); } // -- Object @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } @Override public String stringPrefix() { return "LinkedHashSet"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } private static LinkedHashMap addAll(LinkedHashMap initial, Iterable additional) { LinkedHashMap that = initial; for (T t : additional) { that = that.put(t, t); } return that; } // -- Serialization /** * {@code writeReplace} method for the serialization proxy pattern. *

* The presence of this method causes the serialization system to emit a SerializationProxy instance instead of * an instance of the enclosing class. * * @return A SerializationProxy for this enclosing class. */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private Object writeReplace() { return new SerializationProxy<>(this.map); } /** * {@code readObject} method for the serialization proxy pattern. *

* Guarantees that the serialization system will never generate a serialized instance of the enclosing class. * * @param stream An object serialization stream. * @throws InvalidObjectException This method will throw with the message "Proxy required". */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } /** * A serialization proxy which, in this context, is used to deserialize immutable, linked Lists with final * instance fields. * * @param The component type of the underlying list. */ // DEV NOTE: The serialization proxy pattern is not compatible with non-final, i.e. extendable, // classes. Also, it may not be compatible with circular object graphs. @GwtIncompatible("The Java serialization protocol is explicitly not supported") private static final class SerializationProxy implements Serializable { private static final long serialVersionUID = 1L; // the instance to be serialized/deserialized private transient LinkedHashMap map; /** * Constructor for the case of serialization, called by {@link LinkedHashSet#writeReplace()}. *

* The constructor of a SerializationProxy takes an argument that concisely represents the logical state of * an instance of the enclosing class. * * @param map a Cons */ SerializationProxy(LinkedHashMap map) { this.map = map; } /** * Write an object to a serialization stream. * * @param s An object serialization stream. * @throws IOException If an error occurs writing to the stream. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(map.size()); for (Tuple2 e : map) { s.writeObject(e._1); } } /** * Read an object from a deserialization stream. * * @param s An object deserialization stream. * @throws ClassNotFoundException If the object's class read from the stream cannot be found. * @throws InvalidObjectException If the stream contains no list elements. * @throws IOException If an error occurs reading from the stream. */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); final int size = s.readInt(); if (size < 0) { throw new InvalidObjectException("No elements"); } LinkedHashMap temp = LinkedHashMap.empty(); for (int i = 0; i < size; i++) { @SuppressWarnings("unchecked") final T element = (T) s.readObject(); temp = temp.put(element, element); } map = temp; } /** * {@code readResolve} method for the serialization proxy pattern. *

* Returns a logically equivalent instance of the enclosing class. The presence of this method causes the * serialization system to translate the serialization proxy back into an instance of the enclosing class * upon deserialization. * * @return A deserialized instance of the enclosing class. */ private Object readResolve() { return map.isEmpty() ? LinkedHashSet.empty() : new LinkedHashSet<>(map); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/List.java000066400000000000000000002003671342074374400234760ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.collection.List.Nil; import io.vavr.collection.ListModule.Combinations; import io.vavr.collection.ListModule.SplitAt; import io.vavr.control.Option; import java.io.*; import java.util.*; import java.util.function.*; import java.util.stream.Collector; import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE; import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE; /** * An immutable {@code List} is an eager sequence of elements. Its immutability makes it suitable for concurrent programming. *

* A {@code List} is composed of a {@code head} element and a {@code tail} {@code List}. *

* There are two implementations of the {@code List} interface: * *

    *
  • {@link Nil}, which represents the empty {@code List}.
  • *
  • {@link Cons}, which represents a {@code List} containing one or more elements.
  • *
* * A {@code List} is a {@code Stack} in the sense that it stores elements allowing a last-in-first-out (LIFO) retrieval. *

* Stack API: * *

    *
  • {@link #peek()}
  • *
  • {@link #peekOption()}
  • *
  • {@link #pop()}
  • *
  • {@link #popOption()}
  • *
  • {@link #pop2()}
  • *
  • {@link #pop2Option()}
  • *
  • {@link #push(Object)}
  • *
  • {@link #push(Object[])}
  • *
  • {@link #pushAll(Iterable)}
  • *
* * Methods to obtain a {@code List}: * *
 * 
 * // factory methods
 * List.empty()                        // = List.of() = Nil.instance()
 * List.of(x)                          // = new Cons<>(x, Nil.instance())
 * List.of(Object...)                  // e.g. List.of(1, 2, 3)
 * List.ofAll(Iterable)                // e.g. List.ofAll(Stream.of(1, 2, 3)) = 1, 2, 3
 * List.ofAll(<primitive array>) // e.g. List.of(new int[] {1, 2, 3}) = 1, 2, 3
 *
 * // int sequences
 * List.range(0, 3)              // = 0, 1, 2
 * List.rangeClosed(0, 3)        // = 0, 1, 2, 3
 * 
 * 
* * Note: A {@code List} is primarily a {@code Seq} and extends {@code Stack} for technical reasons (so {@code Stack} does not need to wrap {@code List}). *

* If operating on a {@code List}, please prefer * *

    *
  • {@link #prepend(Object)} over {@link #push(Object)}
  • *
  • {@link #prependAll(Iterable)} over {@link #pushAll(Iterable)}
  • *
  • {@link #tail()} over {@link #pop()}
  • *
  • {@link #tailOption()} over {@link #popOption()}
  • *
* * Factory method applications: * *
 * 
 * List<Integer>       s1 = List.of(1);
 * List<Integer>       s2 = List.of(1, 2, 3);
 *                           // = List.of(new Integer[] {1, 2, 3});
 *
 * List<int[]>         s3 = List.ofAll(1, 2, 3);
 * List<List<Integer>> s4 = List.ofAll(List.of(1, 2, 3));
 *
 * List<Integer>       s5 = List.ofAll(1, 2, 3);
 * List<Integer>       s6 = List.ofAll(List.of(1, 2, 3));
 *
 * // cuckoo's egg
 * List<Integer[]>     s7 = List.<Integer[]> of(new Integer[] {1, 2, 3});
 * 
 * 
* * Example: Converting a String to digits * *
 * 
 * // = List(1, 2, 3)
 * List.of("123".toCharArray()).map(c -> Character.digit(c, 10))
 * 
 * 
* * See Okasaki, Chris: Purely Functional Data Structures (p. 7 ff.). Cambridge, 2003. * * @param Component type of the List * @author Daniel Dietrich */ public interface List extends LinearSeq { long serialVersionUID = 1L; /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link List}. * * @param Component type of the List. * @return A io.vavr.collection.List Collector. */ static Collector, List> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, List> finisher = List::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Returns the single instance of Nil. Convenience method for {@code Nil.instance()} . *

* Note: this method intentionally returns type {@code List} and not {@code Nil}. This comes handy when folding. * If you explicitly need type {@code Nil} use {@linkplain Nil#instance()}. * * @param Component type of Nil, determined by type inference in the particular context. * @return The empty list. */ static List empty() { return Nil.instance(); } /** * A {@code List} is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } @Override boolean isEmpty(); /** * A {@code List} is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } /** * Narrows a widened {@code List} to {@code List} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param list A {@code List}. * @param Component type of the {@code List}. * @return the given {@code list} instance as narrowed type {@code List}. */ @SuppressWarnings("unchecked") static List narrow(List list) { return (List) list; } /** * Returns a singleton {@code List}, i.e. a {@code List} of one element. * * @param element An element. * @param The component type * @return A new List instance containing the given element */ static List of(T element) { return new Cons<>(element, Nil.instance()); } /** * Creates a List of the given elements. *

     * 
     *   List.of(1, 2, 3, 4)
     * = Nil.instance().prepend(4).prepend(3).prepend(2).prepend(1)
     * = new Cons(1, new Cons(2, new Cons(3, new Cons(4, Nil.instance()))))
     * 
     * 
* * @param Component type of the List. * @param elements Zero or more elements. * @return A list containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SafeVarargs static List of(T... elements) { Objects.requireNonNull(elements, "elements is null"); List result = Nil.instance(); for (int i = elements.length - 1; i >= 0; i--) { result = result.prepend(elements[i]); } return result; } /** * Creates a List of the given elements. *

* The resulting list has the same iteration order as the given iterable of elements * if the iteration order of the elements is stable. * * @param Component type of the List. * @param elements An Iterable of elements. * @return A list containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("unchecked") static List ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof List) { return (List) elements; } else if (elements instanceof java.util.List) { List result = Nil.instance(); final java.util.List list = (java.util.List) elements; final ListIterator iterator = list.listIterator(list.size()); while (iterator.hasPrevious()) { result = result.prepend(iterator.previous()); } return result; } else if (elements instanceof NavigableSet) { List result = Nil.instance(); final java.util.Iterator iterator = ((NavigableSet) elements).descendingIterator(); while (iterator.hasNext()) { result = result.prepend(iterator.next()); } return result; } else { List result = Nil.instance(); for (T element : elements) { result = result.prepend(element); } return result.reverse(); } } /** * Creates a List that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return A List containing the given elements in the same order. */ static List ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); final java.util.Iterator iterator = javaStream.iterator(); List list = List.empty(); while (iterator.hasNext()) { list = list.prepend(iterator.next()); } return list.reverse(); } /** * Creates a List from boolean values. * * @param elements boolean values * @return A new List of Boolean values * @throws NullPointerException if elements is null */ static List ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates a List from byte values. * * @param elements byte values * @return A new List of Byte values * @throws NullPointerException if elements is null */ static List ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates a List from char values. * * @param elements char values * @return A new List of Character values * @throws NullPointerException if elements is null */ static List ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates a List from double values. * * @param elements double values * @return A new List of Double values * @throws NullPointerException if elements is null */ static List ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates a List from float values. * * @param elements a float values * @return A new List of Float values * @throws NullPointerException if elements is null */ static List ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates a List from int values. * * @param elements int values * @return A new List of Integer values * @throws NullPointerException if elements is null */ static List ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates a List from long values. * * @param elements long values * @return A new List of Long values * @throws NullPointerException if elements is null */ static List ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Creates a List from short values. * * @param elements short values * @return A new List of Short values * @throws NullPointerException if elements is null */ static List ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(Iterator.ofAll(elements)); } /** * Returns a List containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the List * @param n The number of elements in the List * @param f The Function computing element values * @return A List consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ static List tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f, empty(), List::of); } /** * Returns a List containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the List * @param n The number of elements in the List * @param s The Supplier computing element values * @return A List of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ static List fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s, empty(), List::of); } /** * Returns a List containing {@code n} times the given {@code element} * * @param Component type of the List * @param n The number of elements in the List * @param element The element * @return A List of size {@code n}, where each element is the given {@code element}. */ static List fill(int n, T element) { return Collections.fillObject(n, element, empty(), List::of); } static List range(char from, char toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } static List rangeBy(char from, char toExclusive, int step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } @GwtIncompatible static List rangeBy(double from, double toExclusive, double step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a List of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * List.range(0, 0)  // = List()
     * List.range(2, 0)  // = List()
     * List.range(-2, 2) // = List(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ static List range(int from, int toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } /** * Creates a List of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * List.rangeBy(1, 3, 1)  // = List(1, 2)
     * List.rangeBy(1, 4, 2)  // = List(1, 3)
     * List.rangeBy(4, 1, -2) // = List(4, 2)
     * List.rangeBy(4, 1, 2)  // = List()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static List rangeBy(int from, int toExclusive, int step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a List of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * List.range(0L, 0L)  // = List()
     * List.range(2L, 0L)  // = List()
     * List.range(-2L, 2L) // = List(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ static List range(long from, long toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } /** * Creates a List of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * List.rangeBy(1L, 3L, 1L)  // = List(1L, 2L)
     * List.rangeBy(1L, 4L, 2L)  // = List(1L, 3L)
     * List.rangeBy(4L, 1L, -2L) // = List(4L, 2L)
     * List.rangeBy(4L, 1L, 2L)  // = List()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static List rangeBy(long from, long toExclusive, long step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } static List rangeClosed(char from, char toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } static List rangeClosedBy(char from, char toInclusive, int step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @GwtIncompatible static List rangeClosedBy(double from, double toInclusive, double step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a List of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * List.rangeClosed(0, 0)  // = List(0)
     * List.rangeClosed(2, 0)  // = List()
     * List.rangeClosed(-2, 2) // = List(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ static List rangeClosed(int from, int toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a List of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * List.rangeClosedBy(1, 3, 1)  // = List(1, 2, 3)
     * List.rangeClosedBy(1, 4, 2)  // = List(1, 3)
     * List.rangeClosedBy(4, 1, -2) // = List(4, 2)
     * List.rangeClosedBy(4, 1, 2)  // = List()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static List rangeClosedBy(int from, int toInclusive, int step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a List of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * List.rangeClosed(0L, 0L)  // = List(0L)
     * List.rangeClosed(2L, 0L)  // = List()
     * List.rangeClosed(-2L, 2L) // = List(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ static List rangeClosed(long from, long toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a List of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * List.rangeClosedBy(1L, 3L, 1L)  // = List(1L, 2L, 3L)
     * List.rangeClosedBy(1L, 4L, 2L)  // = List(1L, 3L)
     * List.rangeClosedBy(4L, 1L, -2L) // = List(4L, 2L)
     * List.rangeClosedBy(4L, 1L, 2L)  // = List()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static List rangeClosedBy(long from, long toInclusive, long step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Transposes the rows and columns of a {@link List} matrix. * * @param matrix element type * @param matrix to be transposed. * @return a transposed {@link List} matrix. * @throws IllegalArgumentException if the row lengths of {@code matrix} differ. *

* ex: {@code * List.transpose(List(List(1,2,3), List(4,5,6))) → List(List(1,4), List(2,5), List(3,6)) * } */ static List> transpose(List> matrix) { return Collections.transpose(matrix, List::ofAll, List::of); } /** * Creates a list from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the list, otherwise {@code Some} {@code Tuple} * of the element for the next call and the value to add to the * resulting list. *

* Example: *

     * 
     * List.unfoldRight(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x, x-1)));
     * // List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a list with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static List unfoldRight(T seed, Function>> f) { return Iterator.unfoldRight(seed, f).toList(); } /** * Creates a list from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the list, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting list and * the element for the next call. *

* Example: *

     * 
     * List.unfoldLeft(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a list with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static List unfoldLeft(T seed, Function>> f) { return Iterator.unfoldLeft(seed, f).toList(); } /** * Creates a list from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the list, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting list and * the element for the next call. *

* Example: *

     * 
     * List.unfold(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds and unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a list with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static List unfold(T seed, Function>> f) { return Iterator.unfold(seed, f).toList(); } @Override default List append(T element) { return foldRight(of(element), (x, xs) -> xs.prepend(x)); } @Override default List appendAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); return List. ofAll(elements).prependAll(this); } @GwtIncompatible @Override default java.util.List asJava() { return JavaConverters.asJava(this, IMMUTABLE); } @GwtIncompatible @Override default List asJava(Consumer> action) { return Collections.asJava(this, action, IMMUTABLE); } @GwtIncompatible @Override default java.util.List asJavaMutable() { return JavaConverters.asJava(this, MUTABLE); } @GwtIncompatible @Override default List asJavaMutable(Consumer> action) { return Collections.asJava(this, action, MUTABLE); } @Override default List collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } @Override default List> combinations() { return rangeClosed(0, length()).map(this::combinations).flatMap(Function.identity()); } @Override default List> combinations(int k) { return Combinations.apply(this, Math.max(k, 0)); } @Override default Iterator> crossProduct(int power) { return Collections.crossProduct(empty(), this, power); } @Override default List distinct() { return distinctBy(Function.identity()); } @Override default List distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final java.util.Set seen = new java.util.TreeSet<>(comparator); return filter(seen::add); } @Override default List distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); final java.util.Set seen = new java.util.HashSet<>(); return filter(t -> seen.add(keyExtractor.apply(t))); } @Override default List drop(int n) { if (n <= 0) { return this; } if (n >= size()) { return empty(); } List list = this; for (long i = n; i > 0 && !list.isEmpty(); i--) { list = list.tail(); } return list; } @Override default List dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override default List dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); List list = this; while (!list.isEmpty() && predicate.test(list.head())) { list = list.tail(); } return list; } @Override default List dropRight(int n) { if (n <= 0) { return this; } if (n >= length()) { return empty(); } return ofAll(iterator().dropRight(n)); } @Override default List dropRightUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reverse().dropUntil(predicate).reverse(); } @Override default List dropRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropRightUntil(predicate.negate()); } @Override default List filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return this; } else { final List filtered = foldLeft(empty(), (xs, x) -> predicate.test(x) ? xs.prepend(x) : xs); if (filtered.isEmpty()) { return empty(); } else if (filtered.length() == length()) { return this; } else { return filtered.reverse(); } } } @Override default List reject(Predicate predicate){ Objects.requireNonNull(predicate, "predicate is null"); return Collections.reject(this, predicate); } @Override default List flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); List list = empty(); for (T t : this) { for (U u : mapper.apply(t)) { list = list.prepend(u); } } return list.reverse(); } @Override default T get(int index) { if (isEmpty()) { throw new IndexOutOfBoundsException("get(" + index + ") on Nil"); } if (index < 0) { throw new IndexOutOfBoundsException("get(" + index + ")"); } List list = this; for (int i = index - 1; i >= 0; i--) { list = list.tail(); if (list.isEmpty()) { throw new IndexOutOfBoundsException("get(" + index + ") on List of length " + (index - i)); } } return list.head(); } @Override default Map> groupBy(Function classifier) { return Collections.groupBy(this, classifier, List::ofAll); } @Override default Iterator> grouped(int size) { return sliding(size, size); } @Override default boolean hasDefiniteSize() { return true; } @Override default int indexOf(T element, int from) { int index = 0; for (List list = this; !list.isEmpty(); list = list.tail(), index++) { if (index >= from && Objects.equals(list.head(), element)) { return index; } } return -1; } @Override default List init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty list"); } else { return dropRight(1); } } @Override default Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override int length(); @Override default List insert(int index, T element) { if (index < 0) { throw new IndexOutOfBoundsException("insert(" + index + ", e)"); } List preceding = Nil.instance(); List tail = this; for (int i = index; i > 0; i--, tail = tail.tail()) { if (tail.isEmpty()) { throw new IndexOutOfBoundsException("insert(" + index + ", e) on List of length " + length()); } preceding = preceding.prepend(tail.head()); } List result = tail.prepend(element); for (T next : preceding) { result = result.prepend(next); } return result; } @Override default List insertAll(int index, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (index < 0) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements)"); } List preceding = Nil.instance(); List tail = this; for (int i = index; i > 0; i--, tail = tail.tail()) { if (tail.isEmpty()) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements) on List of length " + length()); } preceding = preceding.prepend(tail.head()); } List result = tail.prependAll(elements); for (T next : preceding) { result = result.prepend(next); } return result; } @Override default List intersperse(T element) { return ofAll(iterator().intersperse(element)); } @Override default boolean isTraversableAgain() { return true; } @Override default T last() { return Collections.last(this); } @Override default int lastIndexOf(T element, int end) { int result = -1, index = 0; for (List list = this; index <= end && !list.isEmpty(); list = list.tail(), index++) { if (Objects.equals(list.head(), element)) { result = index; } } return result; } @Override default List map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); List list = empty(); for (T t : this) { list = list.prepend(mapper.apply(t)); } return list.reverse(); } @Override default List orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override default List orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override default List padTo(int length, T element) { final int actualLength = length(); if (length <= actualLength) { return this; } else { return appendAll(Iterator.continually(element).take(length - actualLength)); } } @Override default List leftPadTo(int length, T element) { final int actualLength = length(); if (length <= actualLength) { return this; } else { return prependAll(Iterator.continually(element).take(length - actualLength)); } } @Override default List patch(int from, Iterable that, int replaced) { from = from < 0 ? 0 : from; replaced = replaced < 0 ? 0 : replaced; List result = take(from).appendAll(that); from += replaced; result = result.appendAll(drop(from)); return result; } @Override default Tuple2, List> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); List left = empty(), right = empty(); for (T t : this) { if (predicate.test(t)) { left = left.prepend(t); } else { right = right.prepend(t); } } return Tuple.of(left.reverse(), right.reverse()); } /** * Returns the head element without modifying the List. * * @return the first element * @throws java.util.NoSuchElementException if this List is empty */ default T peek() { if (isEmpty()) { throw new NoSuchElementException("peek of empty list"); } return head(); } /** * Returns the head element without modifying the List. * * @return {@code None} if this List is empty, otherwise a {@code Some} containing the head element */ default Option peekOption() { return isEmpty() ? Option.none() : Option.some(head()); } /** * Performs an action on the head element of this {@code List}. * * @param action A {@code Consumer} * @return this {@code List} */ @Override default List peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return this; } @Override default List> permutations() { if (isEmpty()) { return Nil.instance(); } else { final List tail = tail(); if (tail.isEmpty()) { return of(this); } else { final List> zero = Nil.instance(); return distinct().foldLeft(zero, (xs, x) -> { final Function, List> prepend = l -> l.prepend(x); return xs.appendAll(remove(x).permutations().map(prepend)); }); } } } /** * Removes the head element from this List. * * @return the elements of this List without the head element * @throws java.util.NoSuchElementException if this List is empty */ default List pop() { if (isEmpty()) { throw new NoSuchElementException("pop of empty list"); } return tail(); } /** * Removes the head element from this List. * * @return {@code None} if this List is empty, otherwise a {@code Some} containing the elements of this List without the head element */ default Option> popOption() { return isEmpty() ? Option.none() : Option.some(pop()); } /** * Removes the head element from this List. * * @return a tuple containing the head element and the remaining elements of this List * @throws java.util.NoSuchElementException if this List is empty */ default Tuple2> pop2() { if (isEmpty()) { throw new NoSuchElementException("pop2 of empty list"); } return Tuple.of(head(), tail()); } /** * Removes the head element from this List. * * @return {@code None} if this List is empty, otherwise {@code Some} {@code Tuple} containing the head element and the remaining elements of this List */ default Option>> pop2Option() { return isEmpty() ? Option.none() : Option.some(Tuple.of(head(), pop())); } @Override default List prepend(T element) { return new Cons<>(element, this); } @Override default List prependAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); return isEmpty() ? ofAll(elements) : ofAll(elements).reverse().foldLeft(this, List::prepend); } /** * Pushes a new element on top of this List. * * @param element The new element * @return a new {@code List} instance, containing the new element on top of this List */ default List push(T element) { return new Cons<>(element, this); } /** * Pushes the given elements on top of this List. A List has LIFO order, i.e. the last of the given elements is * the first which will be retrieved. * * @param elements Elements, may be empty * @return a new {@code List} instance, containing the new elements on top of this List * @throws NullPointerException if elements is null */ @SuppressWarnings("unchecked") default List push(T... elements) { Objects.requireNonNull(elements, "elements is null"); List result = this; for (T element : elements) { result = result.prepend(element); } return result; } /** * Pushes the given elements on top of this List. A List has LIFO order, i.e. the last of the given elements is * the first which will be retrieved. * * @param elements An Iterable of elements, may be empty * @return a new {@code List} instance, containing the new elements on top of this List * @throws NullPointerException if elements is null */ default List pushAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); List result = this; for (T element : elements) { result = result.prepend(element); } return result; } @Override default List remove(T element) { final Deque preceding = new ArrayDeque<>(size()); List result = this; boolean found = false; while (!found && !result.isEmpty()) { final T head = result.head(); if (Objects.equals(head, element)) { found = true; } else { preceding.addFirst(head); } result = result.tail(); } if (!found) { return this; } for (T next : preceding) { result = result.prepend(next); } return result; } @Override default List removeFirst(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); List init = empty(); List tail = this; while (!tail.isEmpty() && !predicate.test(tail.head())) { init = init.prepend(tail.head()); tail = tail.tail(); } if (tail.isEmpty()) { return this; } else { return init.foldLeft(tail.tail(), List::prepend); } } @Override default List removeLast(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final List removedAndReversed = reverse().removeFirst(predicate); return removedAndReversed.length() == length() ? this : removedAndReversed.reverse(); } @Override default List removeAt(int index) { if (index < 0) { throw new IndexOutOfBoundsException("removeAt(" + index + ")"); } if (isEmpty()) { throw new IndexOutOfBoundsException("removeAt(" + index + ") on Nil"); } List init = Nil.instance(); List tail = this; while (index > 0 && !tail.isEmpty()) { init = init.prepend(tail.head()); tail = tail.tail(); index--; } if (index > 0) { throw new IndexOutOfBoundsException("removeAt() on Nil"); } return init.reverse().appendAll(tail.tail()); } @Override default List removeAll(T element) { return Collections.removeAll(this, element); } @Override default List removeAll(Iterable elements) { return Collections.removeAll(this, elements); } @Override @Deprecated default List removeAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override default List replace(T currentElement, T newElement) { List preceding = Nil.instance(); List tail = this; while (!tail.isEmpty() && !Objects.equals(tail.head(), currentElement)) { preceding = preceding.prepend(tail.head()); tail = tail.tail(); } if (tail.isEmpty()) { return this; } // skip the current head element because it is replaced List result = tail.tail().prepend(newElement); for (T next : preceding) { result = result.prepend(next); } return result; } @Override default List replaceAll(T currentElement, T newElement) { List result = Nil.instance(); boolean changed = false; for (List list = this; !list.isEmpty(); list = list.tail()) { final T head = list.head(); if (Objects.equals(head, currentElement)) { result = result.prepend(newElement); changed = true; } else { result = result.prepend(head); } } return changed ? result.reverse() : this; } @Override default List retainAll(Iterable elements) { return Collections.retainAll(this, elements); } @Override default List reverse() { return (length() <= 1) ? this : foldLeft(empty(), List::prepend); } @Override default List rotateLeft(int n) { return Collections.rotateLeft(this, n); } @Override default List rotateRight(int n) { return Collections.rotateRight(this, n); } @Override default List scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override default List scanLeft(U zero, BiFunction operation) { return Collections.scanLeft(this, zero, operation, Iterator::toList); } @Override default List scanRight(U zero, BiFunction operation) { return Collections.scanRight(this, zero, operation, Iterator::toList); } @Override default List shuffle() { return Collections.shuffle(this, List::ofAll); } @Override default List slice(int beginIndex, int endIndex) { if (beginIndex >= endIndex || beginIndex >= length() || isEmpty()) { return empty(); } else { List result = Nil.instance(); List list = this; final long lowerBound = Math.max(beginIndex, 0); final long upperBound = Math.min(endIndex, length()); for (int i = 0; i < upperBound; i++) { if (i >= lowerBound) { result = result.prepend(list.head()); } list = list.tail(); } return result.reverse(); } } @Override default Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(List::ofAll); } @Override default Iterator> sliding(int size) { return sliding(size, 1); } @Override default Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(List::ofAll); } @Override default List sorted() { return isEmpty() ? this : toJavaStream().sorted().collect(collector()); } @Override default List sorted(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return isEmpty() ? this : toJavaStream().sorted(comparator).collect(collector()); } @Override default > List sortBy(Function mapper) { return sortBy(U::compareTo, mapper); } @Override default List sortBy(Comparator comparator, Function mapper) { return Collections.sortBy(this, comparator, mapper, collector()); } @Override default Tuple2, List> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2, Iterator> itt = iterator().span(predicate); return Tuple.of(ofAll(itt._1), ofAll(itt._2)); } @Override default Tuple2, List> splitAt(int n) { if (isEmpty()) { return Tuple.of(empty(), empty()); } else { List init = Nil.instance(); List tail = this; while (n > 0 && !tail.isEmpty()) { init = init.prepend(tail.head()); tail = tail.tail(); n--; } return Tuple.of(init.reverse(), tail); } } @Override default Tuple2, List> splitAt(Predicate predicate) { if (isEmpty()) { return Tuple.of(empty(), empty()); } else { final Tuple2, List> t = SplitAt.splitByPredicateReversed(this, predicate); if (t._2.isEmpty()) { return Tuple.of(this, empty()); } else { return Tuple.of(t._1.reverse(), t._2); } } } @Override default Tuple2, List> splitAtInclusive(Predicate predicate) { if (isEmpty()) { return Tuple.of(empty(), empty()); } else { final Tuple2, List> t = SplitAt.splitByPredicateReversed(this, predicate); if (t._2.isEmpty() || t._2.tail().isEmpty()) { return Tuple.of(this, empty()); } else { return Tuple.of(t._1.prepend(t._2.head()).reverse(), t._2.tail()); } } } @Override default String stringPrefix() { return "List"; } @Override default List subSequence(int beginIndex) { if (beginIndex < 0 || beginIndex > length()) { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ")"); } else { return drop(beginIndex); } } @Override default List subSequence(int beginIndex, int endIndex) { Collections.subSequenceRangeCheck(beginIndex, endIndex, length()); if (beginIndex == endIndex) { return empty(); } else if (beginIndex == 0 && endIndex == length()) { return this; } else { List result = Nil.instance(); List list = this; for (int i = 0; i < endIndex; i++, list = list.tail()) { if (i >= beginIndex) { result = result.prepend(list.head()); } } return result.reverse(); } } @Override List tail(); @Override default Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override default List take(int n) { if (n <= 0) { return empty(); } if (n >= length()) { return this; } List result = Nil.instance(); List list = this; for (int i = 0; i < n; i++, list = list.tail()) { result = result.prepend(list.head()); } return result.reverse(); } @Override default List takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override default List takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); List result = Nil.instance(); for (List list = this; !list.isEmpty() && predicate.test(list.head()); list = list.tail()) { result = result.prepend(list.head()); } return result.length() == length() ? this : result.reverse(); } @Override default List takeRight(int n) { if (n <= 0) { return empty(); } if (n >= length()) { return this; } return reverse().take(n).reverse(); } @Override default List takeRightUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeRightWhile(predicate.negate()); } @Override default List takeRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reverse().takeWhile(predicate).reverse(); } /** * Transforms this {@code List}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override default Tuple2, List> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); List xs = Nil.instance(); List ys = Nil.instance(); for (T element : this) { final Tuple2 t = unzipper.apply(element); xs = xs.prepend(t._1); ys = ys.prepend(t._2); } return Tuple.of(xs.reverse(), ys.reverse()); } @Override default Tuple3, List, List> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); List xs = Nil.instance(); List ys = Nil.instance(); List zs = Nil.instance(); for (T element : this) { final Tuple3 t = unzipper.apply(element); xs = xs.prepend(t._1); ys = ys.prepend(t._2); zs = zs.prepend(t._3); } return Tuple.of(xs.reverse(), ys.reverse(), zs.reverse()); } @Override default List update(int index, T element) { if (isEmpty()) { throw new IndexOutOfBoundsException("update(" + index + ", e) on Nil"); } if (index < 0) { throw new IndexOutOfBoundsException("update(" + index + ", e)"); } List preceding = Nil.instance(); List tail = this; for (int i = index; i > 0; i--, tail = tail.tail()) { if (tail.isEmpty()) { throw new IndexOutOfBoundsException("update(" + index + ", e) on List of length " + length()); } preceding = preceding.prepend(tail.head()); } if (tail.isEmpty()) { throw new IndexOutOfBoundsException("update(" + index + ", e) on List of length " + length()); } // skip the current head element because it is replaced List result = tail.tail().prepend(element); for (T next : preceding) { result = result.prepend(next); } return result; } @Override default List update(int index, Function updater) { Objects.requireNonNull(updater, "updater is null"); return update(index, updater.apply(get(index))); } @Override default List> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override default List zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return ofAll(iterator().zipWith(that, mapper)); } @Override default List> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override default List> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override default List zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return ofAll(iterator().zipWithIndex(mapper)); } /** * Representation of the singleton empty {@code List}. * * @param Component type of the List. */ final class Nil implements List, Serializable { private static final long serialVersionUID = 1L; private static final Nil INSTANCE = new Nil<>(); // hidden private Nil() { } /** * Returns the singleton instance of the linked list. * * @param Component type of the List * @return the singleton instance of the linked list. */ @SuppressWarnings("unchecked") public static Nil instance() { return (Nil) INSTANCE; } @Override public T head() { throw new NoSuchElementException("head of empty list"); } @Override public int length() { return 0; } @Override public List tail() { throw new UnsupportedOperationException("tail of empty list"); } @Override public boolean isEmpty() { return true; } @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashOrdered(this); } @Override public String toString() { return stringPrefix() + "()"; } /** * Instance control for object serialization. * * @return The singleton instance of Nil. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } } /** * Non-empty {@code List}, consisting of a {@code head} and a {@code tail}. * * @param Component type of the List. */ // DEV NOTE: class declared final because of serialization proxy pattern (see Effective Java, 2nd ed., p. 315) final class Cons implements List, Serializable { private static final long serialVersionUID = 1L; private final T head; private final List tail; private final int length; /** * Creates a List consisting of a head value and a trailing List. * * @param head The head * @param tail The tail */ private Cons(T head, List tail) { this.head = head; this.tail = tail; this.length = 1 + tail.length(); } @Override public T head() { return head; } @Override public int length() { return length; } @Override public List tail() { return tail; } @Override public boolean isEmpty() { return false; } @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashOrdered(this); } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } /** * {@code writeReplace} method for the serialization proxy pattern. *

* The presence of this method causes the serialization system to emit a SerializationProxy instance instead of * an instance of the enclosing class. * * @return A SerializationProxy for this enclosing class. */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private Object writeReplace() { return new SerializationProxy<>(this); } /** * {@code readObject} method for the serialization proxy pattern. *

* Guarantees that the serialization system will never generate a serialized instance of the enclosing class. * * @param stream An object serialization stream. * @throws java.io.InvalidObjectException This method will throw with the message "Proxy required". */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } /** * A serialization proxy which, in this context, is used to deserialize immutable, linked Lists with final * instance fields. * * @param The component type of the underlying list. */ // DEV NOTE: The serialization proxy pattern is not compatible with non-final, i.e. extendable, // classes. Also, it may not be compatible with circular object graphs. @GwtIncompatible("The Java serialization protocol is explicitly not supported") private static final class SerializationProxy implements Serializable { private static final long serialVersionUID = 1L; // the instance to be serialized/deserialized private transient Cons list; /** * Constructor for the case of serialization, called by {@link Cons#writeReplace()}. *

* The constructor of a SerializationProxy takes an argument that concisely represents the logical state of * an instance of the enclosing class. * * @param list a Cons */ SerializationProxy(Cons list) { this.list = list; } /** * Write an object to a serialization stream. * * @param s An object serialization stream. * @throws java.io.IOException If an error occurs writing to the stream. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(list.length()); for (List l = list; !l.isEmpty(); l = l.tail()) { s.writeObject(l.head()); } } /** * Read an object from a deserialization stream. * * @param s An object deserialization stream. * @throws ClassNotFoundException If the object's class read from the stream cannot be found. * @throws InvalidObjectException If the stream contains no list elements. * @throws IOException If an error occurs reading from the stream. */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); final int size = s.readInt(); if (size <= 0) { throw new InvalidObjectException("No elements"); } List temp = Nil.instance(); for (int i = 0; i < size; i++) { @SuppressWarnings("unchecked") final T element = (T) s.readObject(); temp = temp.prepend(element); } list = (Cons) temp.reverse(); } /** * {@code readResolve} method for the serialization proxy pattern. *

* Returns a logically equivalent instance of the enclosing class. The presence of this method causes the * serialization system to translate the serialization proxy back into an instance of the enclosing class * upon deserialization. * * @return A deserialized instance of the enclosing class. */ private Object readResolve() { return list; } } } } interface ListModule { interface Combinations { static List> apply(List elements, int k) { if (k == 0) { return List.of(List.empty()); } else { return elements.zipWithIndex().flatMap( t -> apply(elements.drop(t._2 + 1), (k - 1)).map(c -> c.prepend(t._1)) ); } } } interface SplitAt { static Tuple2, List> splitByPredicateReversed(List source, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); List init = Nil.instance(); List tail = source; while (!tail.isEmpty() && !predicate.test(tail.head())) { init = init.prepend(tail.head()); tail = tail.tail(); } return Tuple.of(init, tail); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Map.java000066400000000000000000000756271342074374400233110ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.io.Serializable; import java.util.*; import java.util.function.*; /** * An immutable {@code Map} interface. * *

* Basic operations: * *

    *
  • {@link #containsKey(Object)}
  • *
  • {@link #containsValue(Object)}
  • *
  • {@link #get(Object)}
  • *
  • {@link #keySet()}
  • *
  • {@link #merge(Map)}
  • *
  • {@link #merge(Map, BiFunction)}
  • *
  • {@link #put(Object, Object)}
  • *
  • {@link #put(Tuple2)}
  • *
  • {@link #put(Object, Object, BiFunction)}
  • *
  • {@link #put(Tuple2, BiFunction)}
  • *
  • {@link #values()}
  • *
* * Conversion: * *
    *
  • {@link #toJavaMap()}
  • *
* * Filtering: * *
    *
  • {@link #filter(BiPredicate)}
  • *
  • {@link #filterKeys(Predicate)}
  • *
  • {@link #filterValues(Predicate)}
  • *
  • {@link #reject(BiPredicate)}
  • *
  • {@link #rejectKeys(Predicate)}
  • *
  • {@link #rejectValues(Predicate)}
  • *
  • {@link #remove(Object)}
  • *
  • {@link #removeAll(Iterable)}
  • *
* * Iteration: * *
    *
  • {@link #forEach(BiConsumer)}
  • *
  • {@link #iterator(BiFunction)}
  • *
  • {@link #keysIterator()}
  • *
  • {@link #valuesIterator()}
  • *
* * Transformation: * *
    *
  • {@link #bimap(Function, Function)}
  • *
  • {@link #flatMap(BiFunction)}
  • *
  • {@link #lift()}
  • *
  • {@link #map(BiFunction)}
  • *
  • {@link #mapKeys(Function)}
  • *
  • {@link #mapKeys(Function, BiFunction)}
  • *
  • {@link #mapValues(Function)}
  • *
  • {@link #transform(Function)}
  • *
  • {@link #unzip(BiFunction)}
  • *
  • {@link #unzip3(BiFunction)}
  • *
  • {@link #withDefault(Function)}
  • *
  • {@link #withDefaultValue(Object)}
  • *
* * @param Key type * @param Value type * @author Daniel Dietrich, Ruslan Sennov */ public interface Map extends Traversable>, PartialFunction, Serializable { long serialVersionUID = 1L; /** * Narrows a widened {@code Map} to {@code Map} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param map A {@code Map}. * @param Key type * @param Value type * @return the given {@code map} instance as narrowed type {@code Map}. */ @SuppressWarnings("unchecked") static Map narrow(Map map) { return (Map) map; } /** * Convenience factory method to create a key/value pair. *

* If imported statically, this method allows to create a {@link Map} with arbitrary entries in a readable and * type-safe way, e.g.: *

     * {@code
     *
     * HashMap.ofEntries(
     *     entry(k1, v1),
     *     entry(k2, v2),
     *     entry(k3, v3)
     * );
     *
     * }
     * 
* * @param key the entry's key * @param value the entry's value * @param Key type * @param Value type * @return a key/value pair */ static Tuple2 entry(K key, V value) { return Tuple.of(key, value); } @Deprecated @Override default V apply(K key) { return get(key).getOrElseThrow(() -> new NoSuchElementException(String.valueOf(key))); } /** * Turns this {@code Map} into a {@link PartialFunction} which is defined at a specific index, if this {@code Map} * contains the given key. When applied to a defined key, the partial function will return * the value of this {@code Map} that is associated with the key. * * @return a new {@link PartialFunction} * @throws NoSuchElementException when a non-existing key is applied to the partial function */ default PartialFunction asPartialFunction() throws IndexOutOfBoundsException { return new PartialFunction() { private static final long serialVersionUID = 1L; @Override public V apply(K key) { return get(key).getOrElseThrow(() -> new NoSuchElementException(String.valueOf(key))); } @Override public boolean isDefinedAt(K key) { return containsKey(key); } }; } @Override default Seq collect(PartialFunction, ? extends R> partialFunction) { return io.vavr.collection.Vector.ofAll(iterator(). collect(partialFunction)); } /** * Maps this {@code Map} to a new {@code Map} with different component type by applying a function to its elements. * * @param key's component type of the map result * @param value's component type of the map result * @param keyMapper a {@code Function} that maps the keys of type {@code K} to keys of type {@code K2} * @param valueMapper a {@code Function} that the values of type {@code V} to values of type {@code V2} * @return a new {@code Map} * @throws NullPointerException if {@code keyMapper} or {@code valueMapper} is null */ Map bimap(Function keyMapper, Function valueMapper); @Override default boolean contains(Tuple2 element) { return get(element._1).map(v -> Objects.equals(v, element._2)).getOrElse(false); } /** * If the specified key is not already associated with a value, * attempts to compute its value using the given mapping * function and enters it into this map. * * @param key key whose presence in this map is to be tested * @param mappingFunction mapping function * @return the {@link Tuple2} of current or modified map and existing or computed value associated with the specified key */ Tuple2> computeIfAbsent(K key, Function mappingFunction); /** * If the value for the specified key is present, attempts to * compute a new mapping given the key and its current mapped value. * * @param key key whose presence in this map is to be tested * @param remappingFunction remapping function * @return the {@link Tuple2} of current or modified map and the {@code Some} of the value associated * with the specified key, or {@code None} if none */ Tuple2, ? extends Map> computeIfPresent(K key, BiFunction remappingFunction); /** * Returns true if this map contains a mapping for the specified key. * * @param key key whose presence in this map is to be tested * @return true if this map contains a mapping for the specified key */ boolean containsKey(K key); /** * Returns true if this map maps one or more keys to the * specified value. This operation will require time linear in the map size. * * @param value value whose presence in this map is to be tested * @return true if this map maps one or more keys to the * specified value */ default boolean containsValue(V value) { return iterator().map(Tuple2::_2).contains(value); } /** * Returns a new Map consisting of all elements which satisfy the given predicate. * * @param predicate the predicate used to test elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ Map filter(BiPredicate predicate); /** * Returns a new Map consisting of all elements which do not satisfy the given predicate. * * @param predicate the predicate used to test elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ Map reject(BiPredicate predicate); /** * Returns a new Map consisting of all elements with keys which satisfy the given predicate. * * @param predicate the predicate used to test keys of elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ Map filterKeys(Predicate predicate); /** * Returns a new Map consisting of all elements with keys which do not satisfy the given predicate. * * @param predicate the predicate used to test keys of elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ Map rejectKeys(Predicate predicate); /** * Returns a new Map consisting of all elements with values which satisfy the given predicate. * * @param predicate the predicate used to test values of elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ Map filterValues(Predicate predicate); /** * Returns a new Map consisting of all elements with values which do not satisfy the given predicate. * * @param predicate the predicate used to test values of elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ Map rejectValues(Predicate predicate); /** * FlatMaps this {@code Map} to a new {@code Map} with different component type. * * @param mapper A mapper * @param key's component type of the mapped {@code Map} * @param value's component type of the mapped {@code Map} * @return A new {@code Map}. * @throws NullPointerException if {@code mapper} is null */ Map flatMap(BiFunction>> mapper); /** * Flat-maps this entries to a sequence of values. *

* Please use {@link #flatMap(BiFunction)} if the result should be a {@code Map} * * @param mapper A mapper * @param Component type * @return A sequence of flat-mapped values. */ @SuppressWarnings("unchecked") @Override default Seq flatMap(Function, ? extends Iterable> mapper) { Objects.requireNonNull(mapper, "mapper is null"); // don't remove cast, doesn't compile in Eclipse without it return (Seq) iterator().flatMap(mapper).toStream(); } @Override default U foldRight(U zero, BiFunction, ? super U, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return iterator().foldRight(zero, f); } /** * Performs an action on key, value pair. * * @param action A {@code BiConsumer} * @throws NullPointerException if {@code action} is null */ default void forEach(BiConsumer action) { Objects.requireNonNull(action, "action is null"); for (Tuple2 t : this) { action.accept(t._1, t._2); } } /** * Returns the {@code Some} of value to which the specified key * is mapped, or {@code None} if this map contains no mapping for the key. * * @param key the key whose associated value is to be returned * @return the {@code Some} of value to which the specified key * is mapped, or {@code None} if this map contains no mapping * for the key */ Option get(K key); /** * Returns the value associated with a key, or a default value if the key is not contained in the map. * * @param key the key * @param defaultValue a default value * @return the value associated with key if it exists, otherwise the default value. */ V getOrElse(K key, V defaultValue); @Override default boolean hasDefiniteSize() { return true; } @Override default boolean isTraversableAgain() { return true; } @Override Iterator> iterator(); /** * Iterates this Map sequentially, mapping the (key, value) pairs to elements. * * @param mapper A function that maps (key, value) pairs to elements of type U * @param The type of the resulting elements * @return An iterator through the mapped elements. */ default Iterator iterator(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return iterator().map(t -> mapper.apply(t._1, t._2)); } /** * Returns the keys contained in this map. * * @return {@code Set} of the keys contained in this map. */ io.vavr.collection.Set keySet(); /** * Returns the keys contained in this map as an iterator. * * @return {@code Iterator} of the keys contained in this map. */ default Iterator keysIterator() { return iterator().map(Tuple2::_1); } @Override default int length() { return size(); } /** * Turns this map into a plain function returning an Option result. * * @return a function that takes a key k and returns its value in a Some if found, otherwise a None. */ default Function1> lift() { return this::get; } /** * Maps the {@code Map} entries to a sequence of values. *

* Please use {@link #map(BiFunction)} if the result has to be of type {@code Map}. * * @param mapper A mapper * @param Component type * @return A sequence of mapped values. */ @SuppressWarnings("unchecked") @Override default Seq map(Function, ? extends U> mapper) { Objects.requireNonNull(mapper, "mapper is null"); // don't remove cast, doesn't compile in Eclipse without it return (Seq) iterator().map(mapper).toStream(); } /** * Maps the entries of this {@code Map} to form a new {@code Map}. * * @param key's component type of the map result * @param value's component type of the map result * @param mapper a {@code Function} that maps entries of type {@code (K, V)} to entries of type {@code (K2, V2)} * @return a new {@code Map} * @throws NullPointerException if {@code mapper} is null */ Map map(BiFunction> mapper); /** * Maps the keys of this {@code Map} while preserving the corresponding values. *

* The size of the result map may be smaller if {@code keyMapper} maps two or more distinct keys to the same new key. * In this case the value at the {@code latest} of the original keys is retained. * Order of keys is predictable in {@code TreeMap} (by comparator) and {@code LinkedHashMap} (insertion-order) and not predictable in {@code HashMap}. * * @param the new key type * @param keyMapper a {@code Function} that maps keys of type {@code V} to keys of type {@code V2} * @return a new {@code Map} * @throws NullPointerException if {@code keyMapper} is null */ Map mapKeys(Function keyMapper); /** * Maps the keys of this {@code Map} while preserving the corresponding values and applying a value merge function on collisions. *

* The size of the result map may be smaller if {@code keyMapper} maps two or more distinct keys to the same new key. * In this case the associated values will be combined using {@code valueMerge}. * * @param the new key type * @param keyMapper a {@code Function} that maps keys of type {@code V} to keys of type {@code V2} * @param valueMerge a {@code BiFunction} that merges values * @return a new {@code Map} * @throws NullPointerException if {@code keyMapper} is null */ Map mapKeys(Function keyMapper, BiFunction valueMerge); /** * Maps the values of this {@code Map} while preserving the corresponding keys. * * @param the new value type * @param valueMapper a {@code Function} that maps values of type {@code V} to values of type {@code V2} * @return a new {@code Map} * @throws NullPointerException if {@code valueMapper} is null */ Map mapValues(Function valueMapper); /** * Creates a new map which by merging the entries of {@code this} map and {@code that} map. *

* If collisions occur, the value of {@code this} map is taken. * * @param that the other map * @return A merged map * @throws NullPointerException if that map is null */ Map merge(Map that); /** * Creates a new map which by merging the entries of {@code this} map and {@code that} map. *

* Uses the specified collision resolution function if two keys are the same. * The collision resolution function will always take the first argument from this map * and the second from that map. * * @param value type of that Map * @param that the other map * @param collisionResolution the collision resolution function * @return A merged map * @throws NullPointerException if that map or the given collision resolution function is null */ Map merge(Map that, BiFunction collisionResolution); /** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old value is * replaced by the specified value. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return A new Map containing these elements and that entry. */ Map put(K key, V value); /** * Convenience method for {@code put(entry._1, entry._2)}. * * @param entry A Tuple2 containing the key and value * @return A new Map containing these elements and that entry. */ Map put(Tuple2 entry); /** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the merge * function is used to combine the previous value to the value to * be inserted, and the result of that call is inserted in the map. * * @param the value type * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @param merge function taking the old and new values and merging them. * @return A new Map containing these elements and that entry. */ Map put(K key, U value, BiFunction merge); /** * Convenience method for {@code put(entry._1, entry._2, merge)}. * * @param the value type * @param entry A Tuple2 containing the key and value * @param merge function taking the old and new values and merging them. * @return A new Map containing these elements and that entry. */ Map put(Tuple2 entry, BiFunction merge); /** * Removes the mapping for a key from this map if it is present. * * @param key key whose mapping is to be removed from the map * @return A new Map containing these elements without the entry * specified by that key. */ Map remove(K key); /** * Returns a new Map consisting of all elements which do not satisfy the given predicate. * * @deprecated Please use {@link #reject(BiPredicate)} * @param predicate the predicate used to test elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ @Deprecated Map removeAll(BiPredicate predicate); /** * Removes the mapping for a key from this map if it is present. * * @param keys keys are to be removed from the map * @return A new Map containing these elements without the entries * specified by that keys. */ Map removeAll(Iterable keys); /** * Returns a new Map consisting of all elements with keys which do not satisfy the given predicate. * * @deprecated Please use {@link #rejectKeys(Predicate)} * @param predicate the predicate used to test keys of elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ @Deprecated Map removeKeys(Predicate predicate); /** * Returns a new Map consisting of all elements with values which do not satisfy the given predicate. * * @deprecated Please use {@link #rejectValues(Predicate)} * @param predicate the predicate used to test values of elements * @return a new Map * @throws NullPointerException if {@code predicate} is null */ @Deprecated Map removeValues(Predicate predicate); @Override default Seq scanLeft(U zero, BiFunction, ? extends U> operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, io.vavr.collection.Iterator::toVector); } @Override default Seq scanRight(U zero, BiFunction, ? super U, ? extends U> operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, io.vavr.collection.Iterator::toVector); } @Override int size(); /** * Converts this Vavr {@code Map} to a {@code java.util.Map} while preserving characteristics * like insertion order ({@code LinkedHashMap}) and sort order ({@code SortedMap}). * * @return a new {@code java.util.Map} instance */ java.util.Map toJavaMap(); /** * Transforms this {@code Map}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } default Tuple2, Seq> unzip() { return unzip(Function.identity()); } default Tuple2, Seq> unzip(BiFunction> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return unzip(entry -> unzipper.apply(entry._1, entry._2)); } @Override default Tuple2, Seq> unzip(Function, Tuple2> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip(unzipper).map(Stream::ofAll, Stream::ofAll); } default Tuple3, Seq, Seq> unzip3(BiFunction> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return unzip3(entry -> unzipper.apply(entry._1, entry._2)); } @Override default Tuple3, Seq, Seq> unzip3( Function, Tuple3> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map(Stream::ofAll, Stream::ofAll, Stream::ofAll); } /** * Returns a new {@link Seq} that contains the values of this {@code Map}. * *

{@code
     * // = Seq("a", "b", "c")
     * HashMap.of(1, "a", 2, "b", 3, "c").values()
     * }
* * @return a new {@link Seq} */ Seq values(); /** * Returns the values in this map. * *
{@code
     * // = Iterator.of("a", "b", "c")
     * HashMap.of(1, "a", 2, "b", 3, "c").values()
     * }
* * @return a new {@link Iterator} */ default Iterator valuesIterator() { return iterator().map(Tuple2::_2); } /** * Turns this map from a partial function into a total function that * returns a value computed by defaultFunction for all keys * absent from the map. * * @param defaultFunction function to evaluate for all keys not present in the map * @return a total function from K to T * @deprecated Will be removed */ @Deprecated default Function1 withDefault(Function defaultFunction) { return k -> get(k).getOrElse(() -> defaultFunction.apply(k)); } /** * Turns this map from a partial function into a total function that * returns defaultValue for all keys absent from the map. * * @param defaultValue default value to return for all keys not present in the map * @return a total function from K to T * @deprecated Will be removed */ @Deprecated default Function1 withDefaultValue(V defaultValue) { return k -> get(k).getOrElse(defaultValue); } @Override default Seq, U>> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override default Seq zipWith(Iterable that, BiFunction, ? super U, ? extends R> mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWith(that, mapper)); } @Override default Seq, U>> zipAll(Iterable that, Tuple2 thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return Stream.ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override default Seq, Integer>> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override default Seq zipWithIndex(BiFunction, ? super Integer, ? extends U> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWithIndex(mapper)); } // -- Adjusted return types of Traversable methods @Override Map distinct(); @Override Map distinctBy(Comparator> comparator); @Override Map distinctBy(Function, ? extends U> keyExtractor); @Override Map drop(int n); @Override Map dropRight(int n); @Override Map dropUntil(Predicate> predicate); @Override Map dropWhile(Predicate> predicate); @Override Map filter(Predicate> predicate); @Override Map reject(Predicate> predicate); @Override Map> groupBy(Function, ? extends C> classifier); @Override io.vavr.collection.Iterator> grouped(int size); @Deprecated @Override default boolean isDefinedAt(K key) { return containsKey(key); } @Override default boolean isDistinct() { return true; } @Override Map init(); @Override Option> initOption(); @Override Map orElse(Iterable> other); @Override Map orElse(Supplier>> supplier); @Override Tuple2, ? extends Map> partition(Predicate> predicate); @Override Map peek(Consumer> action); @Override Map replace(Tuple2 currentElement, Tuple2 newElement); /** * Replaces the entry for the specified key only if it is currently mapped to some value. * * @param key the key of the element to be substituted. * @param value the new value to be associated with the key * @return a new map containing key mapped to value if key was contained before. The old map otherwise. */ Map replaceValue(K key, V value); /** * Replaces the entry for the specified key only if currently mapped to the specified value. * * @param key the key of the element to be substituted. * @param oldValue the expected current value that the key is currently mapped to * @param newValue the new value to be associated with the key * @return a new map containing key mapped to newValue if key was contained before and oldValue matched. The old map otherwise. */ Map replace(K key, V oldValue, V newValue); /** * Replaces each entry's value with the result of invoking the given function on that entry until all entries have been processed or the function throws an exception. * * @param function function transforming key and current value to a new value * @return a new map with the same keySet but transformed values. */ Map replaceAll(BiFunction function); @Override Map replaceAll(Tuple2 currentElement, Tuple2 newElement); @Override Map retainAll(Iterable> elements); @Override Map scan(Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation); @Override io.vavr.collection.Iterator> slideBy(Function, ?> classifier); @Override io.vavr.collection.Iterator> sliding(int size); @Override io.vavr.collection.Iterator> sliding(int size, int step); @Override Tuple2, ? extends Map> span(Predicate> predicate); @Override Map tail(); @Override Option> tailOption(); @Override Map take(int n); @Override Map takeRight(int n); @Override Map takeUntil(Predicate> predicate); @Override Map takeWhile(Predicate> predicate); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Maps.java000066400000000000000000000356751342074374400234730ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import java.util.Comparator; import java.util.Objects; import java.util.function.*; import static io.vavr.API.Tuple; /** * INTERNAL: Common {@code Map} functions (not intended to be public). * * @author Ruslan Sennov, Daniel Dietrich */ final class Maps { private Maps() { } @SuppressWarnings("unchecked") static > Tuple2 computeIfAbsent(M map, K key, Function mappingFunction) { Objects.requireNonNull(mappingFunction, "mappingFunction is null"); final Option value = map.get(key); if (value.isDefined()) { return Tuple.of(value.get(), map); } else { final V newValue = mappingFunction.apply(key); final M newMap = (M) map.put(key, newValue); return Tuple.of(newValue, newMap); } } @SuppressWarnings("unchecked") static > Tuple2, M> computeIfPresent(M map, K key, BiFunction remappingFunction) { final Option value = map.get(key); if (value.isDefined()) { final V newValue = remappingFunction.apply(key, value.get()); final M newMap = (M) map.put(key, newValue); return Tuple.of(Option.of(newValue), newMap); } else { return Tuple.of(Option.none(), map); } } static > M distinct(M map) { return map; } static > M distinctBy(M map, OfEntries ofEntries, Comparator> comparator) { Objects.requireNonNull(comparator, "comparator is null"); return ofEntries.apply(map.iterator().distinctBy(comparator)); } static > M distinctBy( M map, OfEntries ofEntries, Function, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return ofEntries.apply(map.iterator().distinctBy(keyExtractor)); } static > M drop(M map, OfEntries ofEntries, Supplier emptySupplier, int n) { if (n <= 0) { return map; } else if (n >= map.size()) { return emptySupplier.get(); } else { return ofEntries.apply(map.iterator().drop(n)); } } static > M dropRight(M map, OfEntries ofEntries, Supplier emptySupplier, int n) { if (n <= 0) { return map; } else if (n >= map.size()) { return emptySupplier.get(); } else { return ofEntries.apply(map.iterator().dropRight(n)); } } static > M dropUntil(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(map, ofEntries, predicate.negate()); } static > M dropWhile(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return ofEntries.apply(map.iterator().dropWhile(predicate)); } static > M filter(M map, OfEntries ofEntries, BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(map, ofEntries, t -> predicate.test(t._1, t._2)); } static > M filter(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return ofEntries.apply(map.iterator().filter(predicate)); } static > M filterKeys(M map, OfEntries ofEntries, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(map, ofEntries, t -> predicate.test(t._1)); } static > M filterValues(M map, OfEntries ofEntries, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(map, ofEntries, t -> predicate.test(t._2)); } static > Map groupBy(M map, OfEntries ofEntries, Function, ? extends C> classifier) { return Collections.groupBy(map, classifier, ofEntries); } static > Iterator grouped(M map, OfEntries ofEntries, int size) { return sliding(map, ofEntries, size, size); } @SuppressWarnings("unchecked") static > Option initOption(M map) { return map.isEmpty() ? Option.none() : Option.some((M) map.init()); } static > M merge(M map, OfEntries ofEntries, Map that) { Objects.requireNonNull(that, "that is null"); if (map.isEmpty()) { return ofEntries.apply(Map.narrow(that)); } else if (that.isEmpty()) { return map; } else { return that.foldLeft(map, (result, entry) -> !result.containsKey(entry._1) ? put(result, entry) : result); } } @SuppressWarnings("unchecked") static > M merge( M map, OfEntries ofEntries, Map that, BiFunction collisionResolution) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(collisionResolution, "collisionResolution is null"); if (map.isEmpty()) { return ofEntries.apply(Map.narrow(that)); } else if (that.isEmpty()) { return map; } else { return that.foldLeft(map, (result, entry) -> { final K key = entry._1; final U value = entry._2; final V newValue = result.get(key).map(v -> (V) collisionResolution.apply(v, value)).getOrElse(value); return (M) result.put(key, newValue); }); } } @SuppressWarnings("unchecked") static > M ofStream(M map, java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { Objects.requireNonNull(stream, "stream is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return Stream.ofAll(stream).foldLeft(map, (m, el) -> (M) m.put(keyMapper.apply(el), valueMapper.apply(el))); } @SuppressWarnings("unchecked") static > M ofStream(M map, java.util.stream.Stream stream, Function> entryMapper) { Objects.requireNonNull(stream, "stream is null"); Objects.requireNonNull(entryMapper, "entryMapper is null"); return Stream.ofAll(stream).foldLeft(map, (m, el) -> (M) m.put(entryMapper.apply(el))); } static > Tuple2 partition(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2>, Iterator>> p = map.iterator().partition(predicate); return Tuple.of(ofEntries.apply(p._1), ofEntries.apply(p._2)); } static > M peek(M map, Consumer> action) { Objects.requireNonNull(action, "action is null"); if (!map.isEmpty()) { action.accept(map.head()); } return map; } @SuppressWarnings("unchecked") static > M put(M map, K key, U value, BiFunction merge) { Objects.requireNonNull(merge, "the merge function is null"); final Option currentValue = map.get(key); if (currentValue.isEmpty()) { return (M) map.put(key, value); } else { return (M) map.put(key, merge.apply(currentValue.get(), value)); } } @SuppressWarnings("unchecked") static > M put(M map, Tuple2 entry) { Objects.requireNonNull(entry, "entry is null"); return (M) map.put(entry._1, entry._2); } static > M put(M map, Tuple2 entry, BiFunction merge) { Objects.requireNonNull(merge, "the merge function is null"); final Option currentValue = map.get(entry._1); if (currentValue.isEmpty()) { return put(map, entry); } else { return put(map, entry.map2(value -> merge.apply(currentValue.get(), value))); } } static > M reject(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(map, ofEntries, predicate.negate()); } static > M reject(M map, OfEntries ofEntries, BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(map, ofEntries, predicate.negate()); } static > M rejectKeys(M map, OfEntries ofEntries, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filterKeys(map, ofEntries, predicate.negate()); } static > M rejectValues(M map, OfEntries ofEntries, Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filterValues(map, ofEntries, predicate.negate()); } @SuppressWarnings("unchecked") static > M replace(M map, K key, V oldValue, V newValue) { return map.contains(Tuple(key, oldValue)) ? (M) map.put(key, newValue) : map; } @SuppressWarnings("unchecked") static > M replace(M map, Tuple2 currentElement, Tuple2 newElement) { Objects.requireNonNull(currentElement, "currentElement is null"); Objects.requireNonNull(newElement, "newElement is null"); return (M) (map.containsKey(currentElement._1) ? map.remove(currentElement._1).put(newElement) : map); } @SuppressWarnings("unchecked") static > M replaceAll(M map, BiFunction function) { return (M) map.map((k, v) -> Tuple(k, function.apply(k, v))); } static > M replaceAll(M map, Tuple2 currentElement, Tuple2 newElement) { return replace(map, currentElement, newElement); } @SuppressWarnings("unchecked") static > M replaceValue(M map, K key, V value) { return map.containsKey(key) ? (M) map.put(key, value) : map; } @SuppressWarnings("unchecked") static > M scan(M map, Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation, Function>, Traversable>> finisher) { return (M) Collections.scanLeft(map, zero, operation, finisher); } static > Iterator slideBy(M map, OfEntries ofEntries, Function, ?> classifier) { return map.iterator().slideBy(classifier).map(ofEntries); } static > Iterator sliding(M map, OfEntries ofEntries, int size) { return sliding(map, ofEntries, size, 1); } static > Iterator sliding(M map, OfEntries ofEntries, int size, int step) { return map.iterator().sliding(size, step).map(ofEntries); } static > Tuple2 span(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2>, Iterator>> t = map.iterator().span(predicate); return Tuple.of(ofEntries.apply(t._1), ofEntries.apply(t._2)); } @SuppressWarnings("unchecked") static > Option tailOption(M map) { return map.isEmpty() ? Option.none() : Option.some((M) map.tail()); } static > M take(M map, OfEntries ofEntries, int n) { if (n >= map.size()) { return map; } else { return ofEntries.apply(map.iterator().take(n)); } } static > M takeRight(M map, OfEntries ofEntries, int n) { if (n >= map.size()) { return map; } else { return ofEntries.apply(map.iterator().takeRight(n)); } } static > M takeUntil(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(map, ofEntries, predicate.negate()); } static > M takeWhile(M map, OfEntries ofEntries, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate is null"); final M taken = ofEntries.apply(map.iterator().takeWhile(predicate)); return taken.size() == map.size() ? map : taken; } @FunctionalInterface interface OfEntries> extends Function>, M> { } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Multimap.java000066400000000000000000000662501342074374400243540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.io.Serializable; import java.util.*; import java.util.function.*; /** * An immutable {@code Multimap} interface. * *

* Basic operations: * *

    *
  • {@link #containsKey(Object)}
  • *
  • {@link #containsValue(Object)}
  • *
  • {@link #get(Object)}
  • *
  • {@link #getContainerType()}
  • *
  • {@link #keySet()}
  • *
  • {@link #merge(Multimap)}
  • *
  • {@link #merge(Multimap, BiFunction)}
  • *
  • {@link #put(Object, Object)}
  • *
  • {@link #put(Tuple2)}
  • *
  • {@link #values()}
  • *
* * Conversion: *
    *
  • {@link #toJavaMap()}
  • *
* * Filtering: * *
    *
  • {@link #filter(BiPredicate)}
  • *
  • {@link #filterKeys(Predicate)}
  • *
  • {@link #filterValues(Predicate)}
  • *
  • {@link #reject(BiPredicate)}
  • *
  • {@link #rejectKeys(Predicate)}
  • *
  • {@link #rejectValues(Predicate)}
  • *
  • {@link #remove(Object)}
  • *
  • {@link #remove(Object, Object)}
  • *
  • {@link #removeAll(Iterable)}
  • *
* * Iteration: * *
    *
  • {@link #forEach(BiConsumer)}
  • *
  • {@link #iterator(BiFunction)}
  • *
* * Transformation: * *
    *
  • {@link #bimap(Function, Function)}
  • *
  • {@link #flatMap(BiFunction)}
  • *
  • {@link #map(BiFunction)}
  • *
  • {@link #mapValues(Function)}
  • *
  • {@link #transform(Function)}
  • *
  • {@link #unzip(BiFunction)}
  • *
  • {@link #unzip3(BiFunction)}
  • *
* * @param Key type * @param Value type * @author Ruslan Sennov */ public interface Multimap extends Traversable>, PartialFunction>, Serializable { long serialVersionUID = 1L; @SuppressWarnings("unchecked") enum ContainerType { SET( (Traversable set, Object elem) -> ((Set) set).add(elem), (Traversable set, Object elem) -> ((Set) set).remove(elem), java.util.HashSet::new ), SORTED_SET( (Traversable set, Object elem) -> ((Set) set).add(elem), (Traversable set, Object elem) -> ((Set) set).remove(elem), java.util.TreeSet::new ), SEQ( (Traversable seq, Object elem) -> ((io.vavr.collection.List) seq).append(elem), (Traversable seq, Object elem) -> ((io.vavr.collection.List) seq).remove(elem), java.util.ArrayList::new ); private final BiFunction, Object, Traversable> add; private final BiFunction, Object, Traversable> remove; private final Supplier> instantiate; ContainerType( BiFunction, Object, Traversable> add, BiFunction, Object, Traversable> remove, Supplier> instantiate) { this.add = add; this.remove = remove; this.instantiate = instantiate; } Traversable add(Traversable container, T elem) { return (Traversable) add.apply(container, elem); } Traversable remove(Traversable container, T elem) { return (Traversable) remove.apply(container, elem); } Collection instantiate() { return (Collection) instantiate.get(); } } /** * Narrows a widened {@code Multimap} to {@code Multimap} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param map A {@code Multimap}. * @param Key type * @param Value type * @return the given {@code multimap} instance as narrowed type {@code Multimap}. */ @SuppressWarnings("unchecked") static Multimap narrow(Multimap map) { return (Multimap) map; } // -- non-static API @Deprecated @Override default Traversable apply(K key) { return get(key).getOrElseThrow(NoSuchElementException::new); } /** * Converts this {@code Multimap} to a {@code Map} * * @return {@code Map>} */ Map> asMap(); /** * Turns this {@code Multimap} into a {@link PartialFunction} which is defined at a specific index, if this {@code Multimap} * contains the given key. When applied to a defined key, the partial function will return * the {@link Traversable} of this {@code Multimap} that is associated with the key. * * @return a new {@link PartialFunction} * @throws NoSuchElementException when a non-existing key is applied to the partial function */ default PartialFunction> asPartialFunction() throws IndexOutOfBoundsException { return new PartialFunction>() { private static final long serialVersionUID = 1L; @Override public Traversable apply(K key) { return get(key).getOrElseThrow(NoSuchElementException::new); } @Override public boolean isDefinedAt(K key) { return containsKey(key); } }; } /** * Maps this {@code Multimap} to a new {@code Multimap} with different component type by applying a function to its elements. * * @param key's component type of the multimap result * @param value's component type of the multimap result * @param keyMapper a {@code Function} that maps the keys of type {@code K} to keys of type {@code K2} * @param valueMapper a {@code Function} that the values of type {@code V} to values of type {@code V2} * @return a new {@code Multimap} * @throws NullPointerException if {@code keyMapper} or {@code valueMapper} is null */ Multimap bimap(Function keyMapper, Function valueMapper); @Override default Seq collect(PartialFunction, ? extends R> partialFunction) { return Vector.ofAll(iterator(). collect(partialFunction)); } @Override default boolean contains(Tuple2 element) { return get(element._1).map(v -> v.contains(element._2)).getOrElse(false); } /** * Returns true if this multimap contains a mapping for the specified key. * * @param key key whose presence in this multimap is to be tested * @return true if this multimap contains a mapping for the specified key */ boolean containsKey(K key); /** * Returns true if this multimap maps one or more keys to the * specified value. This operation will require time linear in the map size. * * @param value value whose presence in this multimap is to be tested * @return true if this multimap maps one or more keys to the * specified value */ default boolean containsValue(V value) { return iterator().map(Tuple2::_2).contains(value); } /** * Returns a new Multimap consisting of all elements which satisfy the given predicate. * * @param predicate the predicate used to test elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ Multimap filter(BiPredicate predicate); /** * Returns a new Multimap consisting of all elements which do not satisfy the given predicate. * * @param predicate the predicate used to test elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ Multimap reject(BiPredicate predicate); /** * Returns a new Multimap consisting of all elements with keys which satisfy the given predicate. * * @param predicate the predicate used to test keys of elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ Multimap filterKeys(Predicate predicate); /** * Returns a new Multimap consisting of all elements with keys which do not satisfy the given predicate. * * @param predicate the predicate used to test keys of elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ Multimap rejectKeys(Predicate predicate); /** * Returns a new Multimap consisting of all elements with values which satisfy the given predicate. * * @param predicate the predicate used to test values of elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ Multimap filterValues(Predicate predicate); /** * Returns a new Multimap consisting of all elements with values which do not satisfy the given predicate. * * @param predicate the predicate used to test values of elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ Multimap rejectValues(Predicate predicate); /** * FlatMaps this {@code Multimap} to a new {@code Multimap} with different component type. * * @param mapper A mapper * @param key's component type of the mapped {@code Multimap} * @param value's component type of the mapped {@code Multimap} * @return A new {@code Multimap}. * @throws NullPointerException if {@code mapper} is null */ Multimap flatMap(BiFunction>> mapper); /** * Performs an action on key, value pair. * * @param action A {@code BiConsumer} * @throws NullPointerException if {@code action} is null */ default void forEach(BiConsumer action) { Objects.requireNonNull(action, "action is null"); for (Tuple2 t : this) { action.accept(t._1, t._2); } } /** * Returns the {@code Some} of value to which the specified key * is mapped, or {@code None} if this multimap contains no mapping for the key. * * @param key the key whose associated value is to be returned * @return the {@code Some} of value to which the specified key * is mapped, or {@code None} if this multimap contains no mapping * for the key */ Option> get(K key); /** * Returns the value associated with a key, or a default value if the key is not contained in the map * * @param key the key * @param defaultValue a default value * @return the value associated with key if it exists, otherwise the result of the default value */ Traversable getOrElse(K key, Traversable defaultValue); /** * Returns the type of the {@code Traversable} value container of this {@code MultiMap}. * * @return an enum value representing the container type */ ContainerType getContainerType(); @Override default boolean hasDefiniteSize() { return true; } @Deprecated @Override default boolean isDefinedAt(K key) { return containsKey(key); } @Override default boolean isDistinct() { return true; } @Override default boolean isTraversableAgain() { return true; } @Override Iterator> iterator(); /** * Iterates this Multimap sequentially, mapping the (key, value) pairs to elements. * * @param mapper A function that maps (key, value) pairs to elements of type U * @param The type of the resulting elements * @return An iterator through the mapped elements. */ default Iterator iterator(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return iterator().map(t -> mapper.apply(t._1, t._2)); } /** * Returns the keys contained in this multimap. * * @return {@code Set} of the keys contained in this multimap. */ Set keySet(); @Override default int length() { return size(); } /** * Maps the entries of this {@code Multimap} to form a new {@code Multimap}. * * @param key's component type of the multimap result * @param value's component type of the multimap result * @param mapper a {@code Function} that maps entries of type {@code (K, V)} to entries of type {@code (K2, V2)} * @return a new {@code Multimap} * @throws NullPointerException if {@code mapper} is null */ Multimap map(BiFunction> mapper); /** * Maps the {@code Multimap} entries to a sequence of values. *

* Please use {@link #map(BiFunction)} if the result has to be of type {@code Multimap}. * * @param mapper A mapper * @param Component type * @return A sequence of mapped values. */ @SuppressWarnings("unchecked") @Override default Seq map(Function, ? extends U> mapper) { Objects.requireNonNull(mapper, "mapper is null"); // don't remove cast, doesn't compile in Eclipse without it return (Seq) iterator().map(mapper).toStream(); } /** * Maps the values of this {@code Multimap} while preserving the corresponding keys. * * @param the new value type * @param valueMapper a {@code Function} that maps values of type {@code V} to values of type {@code V2} * @return a new {@code Multimap} * @throws NullPointerException if {@code valueMapper} is null */ Multimap mapValues(Function valueMapper); /** * Creates a new multimap which by merging the entries of {@code this} multimap and {@code that} multimap. *

* If collisions occur, the value of {@code this} multimap is taken. * * @param that the other multimap * @return A merged multimap * @throws NullPointerException if that multimap is null */ Multimap merge(Multimap that); /** * Creates a new multimap which by merging the entries of {@code this} multimap and {@code that} multimap. *

* Uses the specified collision resolution function if two keys are the same. * The collision resolution function will always take the first argument from this multimap * and the second from that multimap. * * @param key type of that Multimap * @param value type of that Multimap * @param that the other multimap * @param collisionResolution the collision resolution function * @return A merged multimap * @throws NullPointerException if that multimap or the given collision resolution function is null */ Multimap merge(Multimap that, BiFunction, Traversable, Traversable> collisionResolution); /** * Associates the specified value with the specified key in this multimap. * If the map previously contained a mapping for the key, the old value is * replaced by the specified value. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return A new Multimap containing these elements and that entry. */ Multimap put(K key, V value); /** * Convenience method for {@code put(entry._1, entry._2)}. * * @param entry A Tuple2 containing the key and value * @return A new Multimap containing these elements and that entry. */ Multimap put(Tuple2 entry); /** * Removes the mapping for a key from this multimap if it is present. * * @param key key whose mapping is to be removed from the multimap * @return A new Multimap containing these elements without the entry * specified by that key. */ Multimap remove(K key); /** * Removes the key-value pair from this multimap if it is present. * * @param key key whose mapping is to be removed from the multimap * @param value value whose mapping is to be removed from the multimap * @return A new Multimap containing these elements without the entry * specified by that key and value. */ Multimap remove(K key, V value); /** * Returns a new Multimap consisting of all elements which do not satisfy the given predicate. * * @deprecated Please use {@link #reject(BiPredicate)} * @param predicate the predicate used to test elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ @Deprecated Multimap removeAll(BiPredicate predicate); /** * Removes the mapping for a key from this multimap if it is present. * * @param keys keys are to be removed from the multimap * @return A new Multimap containing these elements without the entries * specified by that keys. */ Multimap removeAll(Iterable keys); /** * Returns a new Multimap consisting of all elements with keys which do not satisfy the given predicate. * * @deprecated Please use {@link #rejectKeys(Predicate)} * @param predicate the predicate used to test keys of elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ @Deprecated Multimap removeKeys(Predicate predicate); /** * Returns a new Multimap consisting of all elements with values which do not satisfy the given predicate. * * @deprecated Please use {@link #rejectValues(Predicate)} * @param predicate the predicate used to test values of elements * @return a new Multimap * @throws NullPointerException if {@code predicate} is null */ @Deprecated Multimap removeValues(Predicate predicate); @Override default Seq scanLeft(U zero, BiFunction, ? extends U> operation) { return Collections.scanLeft(this, zero, operation, Iterator::toVector); } @Override default Seq scanRight(U zero, BiFunction, ? super U, ? extends U> operation) { return Collections.scanRight(this, zero, operation, Iterator::toVector); } @Override int size(); /** * Converts this Vavr {@code Map} to a {@code java.util.Map} while preserving characteristics * like insertion order ({@code LinkedHashMultimap}) and sort order ({@code SortedMultimap}). * * @return a new {@code java.util.Map} instance */ java.util.Map> toJavaMap(); /** * Transforms this {@code Multimap}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } default Tuple2, Seq> unzip(BiFunction> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return unzip(entry -> unzipper.apply(entry._1, entry._2)); } @Override default Tuple2, Seq> unzip(Function, Tuple2> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip(unzipper).map(Stream::ofAll, Stream::ofAll); } default Tuple3, Seq, Seq> unzip3(BiFunction> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return unzip3(entry -> unzipper.apply(entry._1, entry._2)); } @Override default Tuple3, Seq, Seq> unzip3( Function, Tuple3> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map(Stream::ofAll, Stream::ofAll, Stream::ofAll); } Traversable values(); @Override default Seq, U>> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override default Seq, U>> zipAll(Iterable that, Tuple2 thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return Stream.ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override default Seq zipWith(Iterable that, BiFunction, ? super U, ? extends R> mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWith(that, mapper)); } @Override default Seq, Integer>> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override default Seq zipWithIndex(BiFunction, ? super Integer, ? extends U> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWithIndex(mapper)); } // -- Adjusted return types of Traversable methods @Override Multimap distinct(); @Override Multimap distinctBy(Comparator> comparator); @Override Multimap distinctBy(Function, ? extends U> keyExtractor); @Override Multimap drop(int n); @Override Multimap dropRight(int n); @Override Multimap dropUntil(Predicate> predicate); @Override Multimap dropWhile(Predicate> predicate); @Override Multimap filter(Predicate> predicate); @Override Multimap reject(Predicate> predicate); /** * Flat-maps this entries to a sequence of values. *

* Please use {@link #flatMap(BiFunction)} if the result should be a {@code Multimap} * * @param mapper A mapper * @param Component type * @return A sequence of flat-mapped values. */ @SuppressWarnings("unchecked") @Override default Seq flatMap(Function, ? extends Iterable> mapper) { Objects.requireNonNull(mapper, "mapper is null"); // don't remove cast, doesn't compile in Eclipse without it return (Seq) iterator().flatMap(mapper).toStream(); } @Override default U foldRight(U zero, BiFunction, ? super U, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return iterator().foldRight(zero, f); } @Override Map> groupBy(Function, ? extends C> classifier); @Override Iterator> grouped(int size); @Override Multimap init(); @Override Option> initOption(); @Override Multimap orElse(Iterable> other); @Override Multimap orElse(Supplier>> supplier); @Override Tuple2, ? extends Multimap> partition(Predicate> predicate); @Override Multimap peek(Consumer> action); @Override Multimap replace(Tuple2 currentElement, Tuple2 newElement); @Override Multimap replaceAll(Tuple2 currentElement, Tuple2 newElement); /** * Replaces the entry for the specified key only if it is currently mapped to some value. * * @param key the key of the element to be substituted * @param value the new value to be associated with the key * @return a new map containing key mapped to value if key was contained before. The old map otherwise */ Multimap replaceValue(K key, V value); /** * Replaces the entry with the specified key and oldValue. * * @param key the key of the element to be substituted * @param oldValue the expected current value associated with the key * @param newValue the new value to be associated with the key * @return a new map containing key mapped to newValue if key was contained before and oldValue was associated with the key. The old map otherwise. */ Multimap replace(K key, V oldValue, V newValue); /** * Replaces each entry's values with the result of invoking the given function on that each tuple until all entries have been processed or the function throws an exception. * * @param function function transforming key and current value to a new value * @return a new map with the same keySet but transformed values */ Multimap replaceAll(BiFunction function); @Override Multimap retainAll(Iterable> elements); @Override Multimap scan(Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation); @Override Iterator> slideBy(Function, ?> classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override Tuple2, ? extends Multimap> span(Predicate> predicate); @Override Multimap tail(); @Override Option> tailOption(); @Override Multimap take(int n); @Override Multimap takeRight(int n); @Override Multimap takeUntil(Predicate> predicate); @Override Multimap takeWhile(Predicate> predicate); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Multimaps.java000066400000000000000000000046621342074374400245360ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple2; import java.util.Objects; import java.util.function.Function; /** * INTERNAL: Common {@code Multimap} functions (not intended to be public). * * @author Ruslan Sennov, Daniel Dietrich */ class Multimaps { @SuppressWarnings("unchecked") static > M ofJavaMap(M source, java.util.Map map) { Objects.requireNonNull(map, "map is null"); return Stream.ofAll(map.entrySet()).foldLeft(source, (m, el) -> (M) m.put(el.getKey(), el.getValue())); } @SuppressWarnings("unchecked") static > M ofStream(M source, java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { Objects.requireNonNull(stream, "stream is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return Stream.ofAll(stream).foldLeft(source, (m, el) -> (M) m.put(keyMapper.apply(el), valueMapper.apply(el))); } @SuppressWarnings("unchecked") static > M ofStream(M source, java.util.stream.Stream stream, Function> entryMapper) { Objects.requireNonNull(stream, "stream is null"); Objects.requireNonNull(entryMapper, "entryMapper is null"); return Stream.ofAll(stream).foldLeft(source, (m, el) -> (M) m.put(entryMapper.apply(el))); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Ordered.java000066400000000000000000000022361342074374400241420ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import java.util.Comparator; /** * An ordered collection interface. * * @param Component type * @author Ruslan Sennov, Daniel Dietrich */ public interface Ordered { /** * Returns the comparator which defines the order of the elements contained in this collection. * * @return The comparator that defines the order of this collection's elements. */ Comparator comparator(); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/PriorityQueue.java000066400000000000000000001002151342074374400254000ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.collection.PriorityQueueBase.*; import java.io.Serializable; import java.util.*; import java.util.function.*; import java.util.stream.Collector; import static io.vavr.collection.PriorityQueueBase.*; /** * A PriorityQueue. * * @author Pap Lőrinc */ public final class PriorityQueue extends io.vavr.collection.AbstractQueue> implements Serializable, Ordered { private static final long serialVersionUID = 1L; private final Comparator comparator; private final Seq> forest; private final int size; private PriorityQueue(Comparator comparator, Seq> forest, int size) { this.comparator = comparator; this.forest = forest; this.size = size; } private PriorityQueue with(Seq> forest, int size) { return new PriorityQueue<>(comparator, forest, size); } @Override public PriorityQueue collect(PartialFunction partialFunction) { return ofAll(Comparators.naturalComparator(), iterator(). collect(partialFunction)); } /** * Enqueues a new element. * * @param element The new element * @return a new {@code PriorityQueue} instance, containing the new element */ @Override public PriorityQueue enqueue(T element) { final Seq> result = insert(comparator, element, forest); return with(result, size + 1); } /** * Enqueues the given elements. A queue has FIFO order, i.e. the first of the given elements is * the first which will be retrieved. * * @param elements An {@link PriorityQueue} of elements, may be empty * @return a new {@link PriorityQueue} instance, containing the new elements * @throws NullPointerException if elements is null */ @Override public PriorityQueue enqueueAll(Iterable elements) { return merge(ofAll(comparator, elements)); } /** * Returns the first element of a non-empty {@link PriorityQueue}. * * @return The first element of this {@link PriorityQueue}. * @throws NoSuchElementException if this is empty */ @Override public T head() { if (isEmpty()) { throw new NoSuchElementException("head of empty " + stringPrefix()); } else { return findMin(comparator, forest).root; } } /** * Drops the first element of a non-empty {@link PriorityQueue}. * * @return A new instance of PriorityQueue containing all elements except the first. * @throws UnsupportedOperationException if this is empty */ @Override public PriorityQueue tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty " + stringPrefix()); } else { return dequeue()._2; } } @Override public Tuple2> dequeue() { if (isEmpty()) { throw new NoSuchElementException("dequeue of empty " + stringPrefix()); } else { final Tuple2>> dequeue = deleteMin(comparator, this.forest); return Tuple.of(dequeue._1, with(dequeue._2, this.size - 1)); } } public PriorityQueue merge(PriorityQueue target) { final Seq> meld = meld(comparator, this.forest, target.forest); return with(meld, this.size + target.size); } /** * A {@code PriorityQueue} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return size == 0; } /** * A {@code PriorityQueue} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isOrdered() { return true; } /** * Returns the empty PriorityQueue. * * @param Component type * @return The empty PriorityQueue. */ public static > PriorityQueue empty() { return empty(Comparators.naturalComparator()); } public static PriorityQueue empty(Comparator comparator) { return new PriorityQueue<>(comparator, io.vavr.collection.List.empty(), 0); } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a {@code PriorityQueue}. * * @param Component type of the {@code PriorityQueue}. * @return A {@code PriorityQueue} Collector. */ public static Collector, PriorityQueue> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, PriorityQueue> finisher = values -> ofAll(Comparators.naturalComparator(), values); return Collector.of(supplier, accumulator, combiner, finisher); } /** * Narrows a widened {@code PriorityQueue} to {@code PriorityQueue} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param queue An {@code PriorityQueue}. * @param Component type of the {@code PriorityQueue}. * @return the given {@code PriorityQueue} instance as narrowed type {@code PriorityQueue}. */ @SuppressWarnings("unchecked") public static PriorityQueue narrow(PriorityQueue queue) { return (PriorityQueue) queue; } public static > PriorityQueue of(T element) { return of(Comparators.naturalComparator(), element); } @SuppressWarnings("unchecked") public static > PriorityQueue of(T... elements) { return ofAll(Comparators.naturalComparator(), io.vavr.collection.List.of(elements)); } public static PriorityQueue of(Comparator comparator, T element) { return ofAll(comparator, io.vavr.collection.List.of(element)); } @SuppressWarnings("unchecked") public static PriorityQueue of(Comparator comparator, T... elements) { return ofAll(comparator, io.vavr.collection.List.of(elements)); } public static > PriorityQueue ofAll(Iterable elements) { return ofAll(Comparators.naturalComparator(), elements); } @SuppressWarnings("unchecked") public static PriorityQueue ofAll(Comparator comparator, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof PriorityQueue && ((PriorityQueue) elements).comparator == comparator) { return (PriorityQueue) elements; } else { int size = 0; Seq> forest = io.vavr.collection.List.empty(); for (T value : elements) { forest = insert(comparator, value, forest); size++; } return new PriorityQueue<>(comparator, forest, size); } } public static > PriorityQueue ofAll(java.util.stream.Stream javaStream) { return ofAll(Comparators.naturalComparator(), io.vavr.collection.Iterator.ofAll(javaStream.iterator())); } public static PriorityQueue ofAll(Comparator comparator, java.util.stream.Stream javaStream) { return ofAll(comparator, io.vavr.collection.Iterator.ofAll(javaStream.iterator())); } /** * Returns a {@link PriorityQueue} containing {@code size} values of a given Function {@code function} * over a range of integer values from {@code 0} to {@code size - 1}. * * @param Component type of the {@link PriorityQueue} * @param size The number of elements in the {@link PriorityQueue} * @param function The Function computing element values * @return A {@link PriorityQueue} consisting of elements {@code function(0),function(1), ..., function(size - 1)} * @throws NullPointerException if {@code function} is null */ @GwtIncompatible public static PriorityQueue tabulate(int size, Function function) { Objects.requireNonNull(function, "function is null"); final Comparator comparator = Comparators.naturalComparator(); return io.vavr.collection.Collections.tabulate(size, function, empty(comparator), values -> ofAll(comparator, io.vavr.collection.List.of(values))); } /** * Returns a {@link PriorityQueue} containing {@code size} values supplied by a given Supplier {@code supplier}. * * @param Component type of the {@link PriorityQueue} * @param size The number of elements in the {@link PriorityQueue} * @param supplier The Supplier computing element values * @return A {@link PriorityQueue} of size {@code size}, where each element contains the result supplied by {@code supplier}. * @throws NullPointerException if {@code supplier} is null */ @GwtIncompatible @SuppressWarnings("unchecked") public static PriorityQueue fill(int size, Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); final Comparator comparator = Comparators.naturalComparator(); return io.vavr.collection.Collections.fill(size, supplier, empty(comparator), values -> ofAll(comparator, io.vavr.collection.List.of(values))); } /** * Returns a {@link PriorityQueue} containing {@code n} times the given {@code element} * * @param Component type of the {@link PriorityQueue} * @param size The number of elements in the {@link PriorityQueue} * @param element The element * @return A {@link PriorityQueue} of size {@code size}, where each element is the given {@code element}. */ @GwtIncompatible @SuppressWarnings("unchecked") public static PriorityQueue fill(int size, T element) { final Comparator comparator = Comparators.naturalComparator(); return io.vavr.collection.Collections.fillObject(size, element, empty(comparator), values -> ofAll(comparator, io.vavr.collection.List.of(values))); } @Override public io.vavr.collection.List toList() { io.vavr.collection.List results = io.vavr.collection.List.empty(); for (PriorityQueue queue = this; !queue.isEmpty(); ) { final Tuple2> dequeue = queue.dequeue(); results = results.prepend(dequeue._1); queue = dequeue._2; } return results.reverse(); } @Override public PriorityQueue distinct() { return distinctBy(comparator); } @Override public PriorityQueue distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return isEmpty() ? this : ofAll(comparator, iterator().distinctBy(comparator)); } @Override public PriorityQueue distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return isEmpty() ? this : ofAll(comparator, iterator().distinctBy(keyExtractor)); } @Override public PriorityQueue drop(int n) { if (n <= 0 || isEmpty()) { return this; } else if (n >= length()) { return empty(comparator); } else { return ofAll(comparator, iterator().drop(n)); } } @Override public PriorityQueue dropRight(int n) { if (n <= 0 || isEmpty()) { return this; } else if (n >= length()) { return empty(comparator); } else { return ofAll(comparator, iterator().dropRight(n)); } } @Override public PriorityQueue dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); PriorityQueue result = this; while (!result.isEmpty() && predicate.test(result.head())) { result = result.tail(); } return result; } @Override public PriorityQueue filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return this; } else { return ofAll(comparator, iterator().filter(predicate)); } } @Override public PriorityQueue flatMap(Function> mapper) { return flatMap(Comparators.naturalComparator(), mapper); } public PriorityQueue flatMap(Comparator comparator, Function> mapper) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(mapper, "mapper is null"); return ofAll(comparator, iterator().flatMap(mapper)); } /** * Accumulates the elements of this {@link PriorityQueue} by successively calling the given function {@code f} from the right, * starting with a value {@code zero} of type B. *

* Example: {@code PriorityQueue.of("a", "b", "c").foldRight("", (x, xs) -> x + xs) = "abc"} * * @param zero Value to start the accumulation with. * @param accumulator The accumulator function. * @return an accumulated version of this. * @throws NullPointerException if {@code f} is null */ @Override public U foldRight(U zero, BiFunction accumulator) { Objects.requireNonNull(zero, "zero is null"); Objects.requireNonNull(accumulator, "accumulator is null"); return toList().foldRight(zero, accumulator); } @Override public Map> groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(this, classifier, (elements) -> ofAll(comparator, elements)); } @Override public io.vavr.collection.Iterator> grouped(int size) { return sliding(size, size); } /** * Checks if this {@link PriorityQueue} is known to have a finite size. *

* This method should be implemented by classes only, i.e. not by interfaces. * * @return true, if this {@link PriorityQueue} is known to have a finite size, false otherwise. */ @Override public boolean hasDefiniteSize() { return true; } /** * Dual of {@linkplain #tail()}, returning all elements except the last. * * @return a new instance containing all elements except the last. * @throws UnsupportedOperationException if this is empty */ @Override public PriorityQueue init() { return ofAll(comparator, iterator().init()); } /** * Checks if this {@link PriorityQueue} can be repeatedly traversed. *

* This method should be implemented by classes only, i.e. not by interfaces. * * @return true, if this {@link PriorityQueue} is known to be traversable repeatedly, false otherwise. */ @Override public boolean isTraversableAgain() { return true; } @Override public T last() { return Collections.last(this); } /** * Computes the number of elements of this {@link PriorityQueue}. *

* Same as {@link #size()}. * * @return the number of elements */ @Override public int length() { return size; } @Override public PriorityQueue map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return map(Comparators.naturalComparator(), mapper); } public PriorityQueue map(Comparator comparator, Function mapper) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(mapper, "mapper is null"); return ofAll(comparator, iterator().map(mapper)); } /** * Returns this {@code PriorityQueue} if it is nonempty, * otherwise {@code PriorityQueue} created from iterable, using existing comparator. * * @param other An alternative {@code Traversable} * @return this {@code PriorityQueue} if it is nonempty, * otherwise {@code PriorityQueue} created from iterable, using existing comparator. */ @Override public PriorityQueue orElse(Iterable other) { return isEmpty() ? ofAll(comparator, other) : this; } /** * Returns this {@code PriorityQueue} if it is nonempty, * otherwise {@code PriorityQueue} created from result of evaluating supplier, using existing comparator. * * @param supplier An alternative {@code Traversable} * @return this {@code PriorityQueue} if it is nonempty, * otherwise {@code PriorityQueue} created from result of evaluating supplier, using existing comparator. */ @Override public PriorityQueue orElse(Supplier> supplier) { return isEmpty() ? ofAll(comparator, supplier.get()) : this; } @Override public Tuple2, ? extends PriorityQueue> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); PriorityQueue left = empty(comparator), right = left; for (T t : this) { if (predicate.test(t)) { left = left.enqueue(t); } else { right = right.enqueue(t); } } return Tuple.of(left, right); } @Override public PriorityQueue replace(T currentElement, T newElement) { Objects.requireNonNull(currentElement, "currentElement is null"); Objects.requireNonNull(newElement, "newElement is null"); return ofAll(comparator, iterator().replace(currentElement, newElement)); } @Override public PriorityQueue replaceAll(T currentElement, T newElement) { Objects.requireNonNull(currentElement, "currentElement is null"); Objects.requireNonNull(newElement, "newElement is null"); return ofAll(comparator, iterator().replaceAll(currentElement, newElement)); } @Override public PriorityQueue scan(T zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, it -> ofAll(comparator, it)); } @Override public PriorityQueue scanLeft(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, it -> ofAll(Comparators.naturalComparator(), it)); } @Override public PriorityQueue scanRight(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, it -> ofAll(Comparators.naturalComparator(), it)); } @Override public io.vavr.collection.Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(v -> ofAll(comparator, v)); } @Override public io.vavr.collection.Iterator> sliding(int size) { return iterator().sliding(size).map(v -> ofAll(comparator, v)); } @Override public io.vavr.collection.Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(v -> ofAll(comparator, v)); } @Override public Tuple2, ? extends PriorityQueue> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Tuple.of(takeWhile(predicate), dropWhile(predicate)); } @Override public PriorityQueue take(int n) { if (n >= size() || isEmpty()) { return this; } else if (n <= 0) { return empty(comparator); } else { return ofAll(comparator, iterator().take(n)); } } @Override public PriorityQueue takeRight(int n) { if (n >= size() || isEmpty()) { return this; } else if (n <= 0) { return empty(comparator); } else { return ofAll(comparator, toArray().takeRight(n)); } } @Override public PriorityQueue takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return isEmpty() ? this : ofAll(comparator, iterator().takeUntil(predicate)); } @Override public Tuple2, ? extends PriorityQueue> unzip(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Tuple2, io.vavr.collection.Iterator> unzip = iterator().unzip(unzipper); return Tuple.of(ofAll(Comparators.naturalComparator(), unzip._1), ofAll(Comparators.naturalComparator(), unzip._2)); } @Override public Tuple3, ? extends PriorityQueue, ? extends PriorityQueue> unzip3(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Tuple3, io.vavr.collection.Iterator, io.vavr.collection.Iterator> unzip3 = iterator().unzip3(unzipper); return Tuple.of(ofAll(Comparators.naturalComparator(), unzip3._1), ofAll(Comparators.naturalComparator(), unzip3._2), ofAll(Comparators.naturalComparator(), unzip3._3)); } @Override public PriorityQueue> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public PriorityQueue zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return ofAll(Comparators.naturalComparator(), iterator().zipWith(that, mapper)); } @Override public PriorityQueue> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public PriorityQueue> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public PriorityQueue zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return ofAll(Comparators.naturalComparator(), iterator().zipWithIndex(mapper)); } @Override public String stringPrefix() { return "PriorityQueue"; } @Override public boolean equals(Object o) { return o == this || o instanceof PriorityQueue && io.vavr.collection.Collections.areEqual(this, (Iterable) o); } @Override public int hashCode() { return io.vavr.collection.Collections.hashOrdered(this); } @Override @SuppressWarnings("unchecked") public Comparator comparator() { return (Comparator) comparator; } } final class PriorityQueueBase { /** * fun deleteMin [] = raise EMPTY * * | deleteMin ts = * * val (Node (x,r,c), ts) = getMin ts * * val (ts',xs') = split ([],[],c) * * in fold insert xs' (meld (ts, ts')) end **/ static Tuple2>> deleteMin(Comparator comparator, Seq> forest) { /* get the minimum tree and the rest of the forest */ final Node minTree = findMin(comparator, forest); final Seq> forestTail = (minTree == forest.head()) ? forest.tail() : forest.remove(minTree); final Seq> newForest = rebuild(comparator, minTree.children); return Tuple.of(minTree.root, meld(comparator, newForest, forestTail)); } /** * fun insert (x, ts as t1 :: t2 :: rest) = * * if rank t1 = rank t2 then skewLink(Node(x,0,[]),t1,t2) :: rest * * else Node (x,0,[]) :: ts * * | insert (x, ts) = Node (x,0,[]) :: ts **/ static Seq> insert(Comparator comparator, T element, Seq> forest) { final Node tree = Node.of(element, 0, io.vavr.collection.List.empty()); if (forest.size() >= 2) { final Seq> tail = forest.tail(); final Node t1 = forest.head(), t2 = tail.head(); if (t1.rank == t2.rank) { return tree.skewLink(comparator, t1, t2).appendTo(tail.tail()); } } return tree.appendTo(forest); } /** fun meld (ts, ts') = meldUniq (uniqify ts, uniqify ts') */ static Seq> meld(Comparator comparator, Seq> source, Seq> target) { return meldUnique(comparator, uniqify(comparator, source), uniqify(comparator, target)); } /** * Find the minimum root in the forest *

* fun findMin [] = raise EMPTY * * | findMin [t] = root t * * | findMin (t :: ts) = * * let val x = findMin ts * * in if Elem.leq (root t, x) then root t else x end */ static Node findMin(Comparator comparator, Seq> forest) { final io.vavr.collection.Iterator> iterator = forest.iterator(); Node min = iterator.next(); for (Node node : iterator) { if (comparator.compare(node.root, min.root) < 0) { min = node; } } return min; } /** * Separate the rank 0 trees from the rest, rebuild the 0 rank ones and merge them back *

* fun split (ts,xs,[]) = (ts, xs) * * | split (ts,xs,t :: c) = * * if rank t = 0 then split (ts,root t :: xs,c) * * else split (t :: ts,xs,c) */ private static Seq> rebuild(Comparator comparator, Seq> forest) { Seq> nonZeroRank = io.vavr.collection.List.empty(), zeroRank = io.vavr.collection.List.empty(); for (; !forest.isEmpty(); forest = forest.tail()) { final Node initialForestHead = forest.head(); if (initialForestHead.rank == 0) { zeroRank = insert(comparator, initialForestHead.root, zeroRank); } else { nonZeroRank = initialForestHead.appendTo(nonZeroRank); } } return meld(comparator, nonZeroRank, zeroRank); } /** * fun uniqify [] = [] * * | uniqify (t :: ts) = ins (t, ts) (∗ eliminate initial duplicate ∗) **/ private static Seq> uniqify(Comparator comparator, Seq> forest) { return forest.isEmpty() ? forest : ins(comparator, forest.head(), forest.tail()); } /** * fun ins (t, []) = [t] * * | ins (t, t' :: ts) = (∗ rank t ≤ rank t' ∗) * * if rank t < rank t' then t :: t' :: ts * * else ins (link (t, t'), ts) */ private static Seq> ins(Comparator comparator, Node tree, Seq> forest) { while (!forest.isEmpty() && tree.rank == forest.head().rank) { tree = tree.link(comparator, forest.head()); forest = forest.tail(); } return tree.appendTo(forest); } /** * fun meldUniq ([], ts) = ts * * | meldUniq (ts, []) = ts * * | meldUniq (t1 :: ts1, t2 :: ts2) = * * if rank t1 < rank t2 then t1 :: meldUniq (ts1, t2 :: ts2) * * else if rank t2 < rank t1 then t2 :: meldUniq (t1 :: ts1, ts2) * * else ins (link (t1, t2), meldUniq (ts1, ts2)) **/ private static Seq> meldUnique(Comparator comparator, Seq> forest1, Seq> forest2) { if (forest1.isEmpty()) { return forest2; } else if (forest2.isEmpty()) { return forest1; } else { final Node tree1 = forest1.head(), tree2 = forest2.head(); if (tree1.rank == tree2.rank) { final Node tree = tree1.link(comparator, tree2); final Seq> forest = meldUnique(comparator, forest1.tail(), forest2.tail()); return ins(comparator, tree, forest); } else { if (tree1.rank < tree2.rank) { final Seq> forest = meldUnique(comparator, forest1.tail(), forest2); return tree1.appendTo(forest); } else { final Seq> forest = meldUnique(comparator, forest1, forest2.tail()); return tree2.appendTo(forest); } } } } /* Based on http://www.brics.dk/RS/96/37/BRICS-RS-96-37.pdf */ static final class Node implements Serializable { private static final long serialVersionUID = 1L; final T root; final int rank; final Seq> children; private Node(T root, int rank, Seq> children) { this.root = root; this.rank = rank; this.children = children; } static Node of(T value, int rank, Seq> children) { return new Node<>(value, rank, children); } /* * fun link (t1 as Node (x1,r1,c1), t2 as Node (x2,r2,c2)) = (∗ r1 = r2 ∗) * * if Elem.leq (x1,x2) then Node (x1,r1+1,t2 :: c1) * * else Node (x2,r2+1,t1 :: c2 */ Node link(Comparator comparator, Node tree) { return comparator.compare(this.root, tree.root) <= 0 ? of(this.root, this.rank + 1, tree.appendTo(this.children)) : of(tree.root, tree.rank + 1, this.appendTo(tree.children)); } /* * fun skewLink (t0 as Node (x0,r0, _), t1 as Node (x1,r1,c1), t2 as Node (x2,r2,c2)) = * * if Elem.leq (x1,x0) andalso Elem.leq (x1,x2) then Node (x1,r1+1,t0 :: t2 :: c1) * * else if Elem.leq (x2,x0) andalso Elem.leq (x2,x1) then Node (x2,r2+1,t0 :: t1 :: c2) * * else Node (x0,r1+1,[t1, t2]) */ Node skewLink(Comparator comparator, Node left, Node right) { if (comparator.compare(left.root, root) <= 0 && comparator.compare(left.root, right.root) <= 0) { return of(left.root, left.rank + 1, appendTo(right.appendTo(left.children))); } else if (comparator.compare(right.root, root) <= 0) { return of(right.root, right.rank + 1, appendTo(left.appendTo(right.children))); } else { return of(root, left.rank + 1, io.vavr.collection.List.of(left, right)); } } Seq> appendTo(Seq> forest) { return forest.prepend(this); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Queue.java000066400000000000000000001347261342074374400236540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.util.*; import java.util.function.*; import java.util.stream.Collector; import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE; import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE; /** * An immutable {@code Queue} stores elements allowing a first-in-first-out (FIFO) retrieval. *

* Queue API: * *

    *
  • {@link #dequeue()}
  • *
  • {@link #dequeueOption()}
  • *
  • {@link #enqueue(Object)}
  • *
  • {@link #enqueue(Object[])}
  • *
  • {@link #enqueueAll(Iterable)}
  • *
  • {@link #peek()}
  • *
  • {@link #peekOption()}
  • *
* * A Queue internally consists of a front List containing the front elements of the Queue in the correct order and a * rear List containing the rear elements of the Queue in reverse order. *

* When the front list is empty, front and rear are swapped and rear is reversed. This implies the following queue * invariant: {@code front.isEmpty() => rear.isEmpty()}. *

* See Okasaki, Chris: Purely Functional Data Structures (p. 42 ff.). Cambridge, 2003. * * @param Component type of the Queue * @author Daniel Dietrich */ public final class Queue extends AbstractQueue> implements LinearSeq { private static final long serialVersionUID = 1L; private static final Queue EMPTY = new Queue<>(io.vavr.collection.List.empty(), io.vavr.collection.List.empty()); private final io.vavr.collection.List front; private final io.vavr.collection.List rear; /** * Creates a Queue consisting of a front List and a rear List. *

* For a {@code Queue(front, rear)} the following invariant holds: {@code Queue is empty <=> front is empty}. * In other words: If the Queue is not empty, the front List contains at least one element. * * @param front A List of front elements, in correct order. * @param rear A List of rear elements, in reverse order. */ private Queue(io.vavr.collection.List front, io.vavr.collection.List rear) { final boolean frontIsEmpty = front.isEmpty(); this.front = frontIsEmpty ? rear.reverse() : front; this.rear = frontIsEmpty ? front : rear; } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link Queue} * . * * @param Component type of the Queue. * @return A io.vavr.collection.Queue Collector. */ public static Collector, Queue> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, Queue> finisher = Queue::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Returns the empty Queue. * * @param Component type * @return The empty Queue. */ @SuppressWarnings("unchecked") public static Queue empty() { return (Queue) EMPTY; } /** * Narrows a widened {@code Queue} to {@code Queue} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param queue An {@code Queue}. * @param Component type of the {@code Queue}. * @return the given {@code queue} instance as narrowed type {@code Queue}. */ @SuppressWarnings("unchecked") public static Queue narrow(Queue queue) { return (Queue) queue; } /** * Returns a singleton {@code Queue}, i.e. a {@code Queue} of one element. * * @param element An element. * @param The component type * @return A new Queue instance containing the given element */ public static Queue of(T element) { return ofAll(io.vavr.collection.List.of(element)); } /** * Creates a Queue of the given elements. * * @param Component type of the Queue. * @param elements Zero or more elements. * @return A queue containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("varargs") @SafeVarargs public static Queue of(T... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.of(elements)); } /** * Creates a Queue of the given elements. * * @param Component type of the Queue. * @param elements An Iterable of elements. * @return A queue containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("unchecked") public static Queue ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof Queue) { return (Queue) elements; } else if (!elements.iterator().hasNext()) { return empty(); } else if (elements instanceof io.vavr.collection.List) { return new Queue<>((io.vavr.collection.List) elements, io.vavr.collection.List.empty()); } else { return new Queue<>(io.vavr.collection.List.ofAll(elements), io.vavr.collection.List.empty()); } } /** * Creates a Queue that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return A Queue containing the given elements in the same order. */ public static Queue ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return new Queue<>(io.vavr.collection.List.ofAll(javaStream), io.vavr.collection.List.empty()); } /** * Creates a Queue from boolean values. * * @param elements boolean values * @return A new Queue of Boolean values * @throws NullPointerException if elements is null */ public static Queue ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Creates a Queue from byte values. * * @param elements byte values * @return A new Queue of Byte values * @throws NullPointerException if elements is null */ public static Queue ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Creates a Queue from char values. * * @param elements char values * @return A new Queue of Character values * @throws NullPointerException if elements is null */ public static Queue ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Creates a Queue from double values. * * @param elements double values * @return A new Queue of Double values * @throws NullPointerException if elements is null */ public static Queue ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Creates a Queue from float values. * * @param elements float values * @return A new Queue of Float values * @throws NullPointerException if elements is null */ public static Queue ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Creates a Queue from int values. * * @param elements int values * @return A new Queue of Integer values * @throws NullPointerException if elements is null */ public static Queue ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Creates a Queue from long values. * * @param elements long values * @return A new Queue of Long values * @throws NullPointerException if elements is null */ public static Queue ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Creates a Queue from short values. * * @param elements short values * @return A new Queue of Short values * @throws NullPointerException if elements is null */ public static Queue ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(io.vavr.collection.List.ofAll(elements)); } /** * Returns a Queue containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the Queue * @param n The number of elements in the Queue * @param f The Function computing element values * @return A Queue consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static Queue tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return io.vavr.collection.Collections.tabulate(n, f, empty(), Queue::of); } /** * Returns a Queue containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the Queue * @param n The number of elements in the Queue * @param s The Supplier computing element values * @return An Queue of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static Queue fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return io.vavr.collection.Collections.fill(n, s, empty(), Queue::of); } /** * Returns a Queue containing {@code n} times the given {@code element} * * @param Component type of the Queue * @param n The number of elements in the Queue * @param element The element * @return An Queue of size {@code n}, where each element is the given {@code element}. */ public static Queue fill(int n, T element) { return io.vavr.collection.Collections.fillObject(n, element, empty(), Queue::of); } public static Queue range(char from, char toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } public static Queue rangeBy(char from, char toExclusive, int step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } @GwtIncompatible public static Queue rangeBy(double from, double toExclusive, double step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a Queue of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Queue.range(0, 0)  // = Queue()
     * Queue.range(2, 0)  // = Queue()
     * Queue.range(-2, 2) // = Queue(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or {@code Nil} if {@code from >= toExclusive} */ public static Queue range(int from, int toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } /** * Creates a Queue of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Queue.rangeBy(1, 3, 1)  // = Queue(1, 2)
     * Queue.rangeBy(1, 4, 2)  // = Queue(1, 3)
     * Queue.rangeBy(4, 1, -2) // = Queue(4, 2)
     * Queue.rangeBy(4, 1, 2)  // = Queue()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or {@code Nil} if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Queue rangeBy(int from, int toExclusive, int step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a Queue of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Queue.range(0L, 0L)  // = Queue()
     * Queue.range(2L, 0L)  // = Queue()
     * Queue.range(-2L, 2L) // = Queue(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or {@code Nil} if {@code from >= toExclusive} */ public static Queue range(long from, long toExclusive) { return ofAll(Iterator.range(from, toExclusive)); } /** * Creates a Queue of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Queue.rangeBy(1L, 3L, 1L)  // = Queue(1L, 2L)
     * Queue.rangeBy(1L, 4L, 2L)  // = Queue(1L, 3L)
     * Queue.rangeBy(4L, 1L, -2L) // = Queue(4L, 2L)
     * Queue.rangeBy(4L, 1L, 2L)  // = Queue()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or {@code Nil} if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Queue rangeBy(long from, long toExclusive, long step) { return ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static Queue rangeClosed(char from, char toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } public static Queue rangeClosedBy(char from, char toInclusive, int step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @GwtIncompatible public static Queue rangeClosedBy(double from, double toInclusive, double step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a Queue of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Queue.rangeClosed(0, 0)  // = Queue(0)
     * Queue.rangeClosed(2, 0)  // = Queue()
     * Queue.rangeClosed(-2, 2) // = Queue(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or {@code Nil} if {@code from > toInclusive} */ public static Queue rangeClosed(int from, int toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a Queue of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Queue.rangeClosedBy(1, 3, 1)  // = Queue(1, 2, 3)
     * Queue.rangeClosedBy(1, 4, 2)  // = Queue(1, 3)
     * Queue.rangeClosedBy(4, 1, -2) // = Queue(4, 2)
     * Queue.rangeClosedBy(4, 1, 2)  // = Queue()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or {@code Nil} if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Queue rangeClosedBy(int from, int toInclusive, int step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a Queue of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Queue.rangeClosed(0L, 0L)  // = Queue(0L)
     * Queue.rangeClosed(2L, 0L)  // = Queue()
     * Queue.rangeClosed(-2L, 2L) // = Queue(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or {@code Nil} if {@code from > toInclusive} */ public static Queue rangeClosed(long from, long toInclusive) { return ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Transposes the rows and columns of a {@link Queue} matrix. * * @param matrix element type * @param matrix to be transposed. * @return a transposed {@link Queue} matrix. * @throws IllegalArgumentException if the row lengths of {@code matrix} differ. * *

* ex: {@code * Queue.transpose(Queue(Queue(1,2,3), Queue(4,5,6))) → Queue(Queue(1,4), Queue(2,5), Queue(3,6)) * } */ public static Queue> transpose(Queue> matrix) { return io.vavr.collection.Collections.transpose(matrix, Queue::ofAll, Queue::of); } /** * Creates a Queue of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Queue.rangeClosedBy(1L, 3L, 1L)  // = Queue(1L, 2L, 3L)
     * Queue.rangeClosedBy(1L, 4L, 2L)  // = Queue(1L, 3L)
     * Queue.rangeClosedBy(4L, 1L, -2L) // = Queue(4L, 2L)
     * Queue.rangeClosedBy(4L, 1L, 2L)  // = Queue()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or {@code Nil} if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Queue rangeClosedBy(long from, long toInclusive, long step) { return ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a Queue from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Queue, otherwise {@code Some} {@code Tuple} * of the element for the next call and the value to add to the * resulting Queue. *

* Example: *

     * 
     * Queue.unfoldRight(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x, x-1)));
     * // Queue(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Queue with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Queue unfoldRight(T seed, Function>> f) { return Iterator.unfoldRight(seed, f).toQueue(); } /** * Creates a Queue from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Queue, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting Queue and * the element for the next call. *

* Example: *

     * 
     * Queue.unfoldLeft(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // Queue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Queue with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Queue unfoldLeft(T seed, Function>> f) { return Iterator.unfoldLeft(seed, f).toQueue(); } /** * Creates a Queue from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Queue, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting Queue and * the element for the next call. *

* Example: *

     * 
     * Queue.unfold(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // Queue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds and unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Queue with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Queue unfold(T seed, Function>> f) { return Iterator.unfold(seed, f).toQueue(); } /** * Enqueues a new element. * * @param element The new element * @return a new {@code Queue} instance, containing the new element */ @Override public Queue enqueue(T element) { return new Queue<>(front, rear.prepend(element)); } /** * Enqueues the given elements. A queue has FIFO order, i.e. the first of the given elements is * the first which will be retrieved. * * @param elements An Iterable of elements, may be empty * @return a new {@code Queue} instance, containing the new elements * @throws NullPointerException if elements is null */ @SuppressWarnings("unchecked") public Queue enqueueAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() && elements instanceof Queue) { return (Queue) elements; } else { return io.vavr.collection.List.ofAll(elements).foldLeft(this, Queue::enqueue); } } // -- Adjusted return types of Seq methods @Override public Queue append(T element) { return enqueue(element); } @Override public Queue appendAll(Iterable elements) { return enqueueAll(elements); } @GwtIncompatible @Override public java.util.List asJava() { return JavaConverters.asJava(this, IMMUTABLE); } @GwtIncompatible @Override public Queue asJava(Consumer> action) { return Collections.asJava(this, action, IMMUTABLE); } @GwtIncompatible @Override public java.util.List asJavaMutable() { return JavaConverters.asJava(this, MUTABLE); } @GwtIncompatible @Override public Queue asJavaMutable(Consumer> action) { return Collections.asJava(this, action, MUTABLE); } @Override public Queue collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } @Override public Queue> combinations() { return ofAll(toList().combinations().map(Queue::ofAll)); } @Override public Queue> combinations(int k) { return ofAll(toList().combinations(k).map(Queue::ofAll)); } @Override public Iterator> crossProduct(int power) { return io.vavr.collection.Collections.crossProduct(empty(), this, power); } @Override public Queue distinct() { return ofAll(toList().distinct()); } @Override public Queue distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return ofAll(toList().distinctBy(comparator)); } @Override public Queue distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return ofAll(toList().distinctBy(keyExtractor)); } @Override public Queue drop(int n) { if (n <= 0) { return this; } if (n >= length()) { return empty(); } return new Queue<>(front.drop(n), rear.dropRight(n - front.length())); } @Override public Queue dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final List dropped = toList().dropWhile(predicate); return ofAll(dropped.length() == length() ? this : dropped); } @Override public Queue dropRight(int n) { if (n <= 0) { return this; } if (n >= length()) { return empty(); } return new Queue<>(front.dropRight(n - rear.length()), rear.drop(n)); } @Override public Queue dropRightUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reverse().dropUntil(predicate).reverse(); } @Override public Queue dropRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropRightUntil(predicate.negate()); } @Override public Queue filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final io.vavr.collection.List filtered = toList().filter(predicate); if (filtered.isEmpty()) { return empty(); } else if (filtered.length() == length()) { return this; } else { return ofAll(filtered); } } @Override public Queue flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { return new Queue<>(front.flatMap(mapper), rear.flatMap(mapper)); } } @Override public T get(int index) { if (isEmpty()) { throw new IndexOutOfBoundsException("get(" + index + ") on empty Queue"); } if (index < 0) { throw new IndexOutOfBoundsException("get(" + index + ")"); } final int length = front.length(); if (index < length) { return front.get(index); } else { final int rearIndex = index - length; final int rearLength = rear.length(); if (rearIndex < rearLength) { final int reverseRearIndex = rearLength - rearIndex - 1; return rear.get(reverseRearIndex); } else { throw new IndexOutOfBoundsException("get(" + index + ") on Queue of length " + length()); } } } @Override public Map> groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(this, classifier, Queue::ofAll); } @Override public Iterator> grouped(int size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public T head() { if (isEmpty()) { throw new NoSuchElementException("head of empty " + stringPrefix()); } else { return front.head(); } } @Override public int indexOf(T element, int from) { final int frontIndex = front.indexOf(element, from); if (frontIndex != -1) { return frontIndex; } else { // we need to reverse because we search the first occurrence final int rearIndex = rear.reverse().indexOf(element, from - front.length()); return (rearIndex == -1) ? -1 : rearIndex + front.length(); } } @Override public Queue init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty " + stringPrefix()); } else if (rear.isEmpty()) { return new Queue<>(front.init(), rear); } else { return new Queue<>(front, rear.tail()); } } @Override public Queue insert(int index, T element) { if (index < 0) { throw new IndexOutOfBoundsException("insert(" + index + ", element)"); } final int length = front.length(); if (index <= length) { return new Queue<>(front.insert(index, element), rear); } else { final int rearIndex = index - length; final int rearLength = rear.length(); if (rearIndex <= rearLength) { final int reverseRearIndex = rearLength - rearIndex; return new Queue<>(front, rear.insert(reverseRearIndex, element)); } else { throw new IndexOutOfBoundsException("insert(" + index + ", element) on Queue of length " + length()); } } } @SuppressWarnings("unchecked") @Override public Queue insertAll(int index, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (index < 0) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements)"); } final int length = front.length(); if (index <= length) { if (isEmpty() && elements instanceof Queue) { return (Queue) elements; } else { final io.vavr.collection.List newFront = front.insertAll(index, elements); return (newFront == front) ? this : new Queue<>(newFront, rear); } } else { final int rearIndex = index - length; final int rearLength = rear.length(); if (rearIndex <= rearLength) { final int reverseRearIndex = rearLength - rearIndex; final io.vavr.collection.List newRear = rear.insertAll(reverseRearIndex, io.vavr.collection.List.ofAll(elements).reverse()); return (newRear == rear) ? this : new Queue<>(front, newRear); } else { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements) on Queue of length " + length()); } } } @Override public Queue intersperse(T element) { if (isEmpty()) { return this; } else if (rear.isEmpty()) { return new Queue<>(front.intersperse(element), rear); } else { return new Queue<>(front.intersperse(element), rear.intersperse(element).append(element)); } } /** * A {@code Queue} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return front.isEmpty(); } /** * A {@code Queue} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } @Override public T last() { return rear.isEmpty() ? front.last() : rear.head(); } @Override public int lastIndexOf(T element, int end) { return toList().lastIndexOf(element, end); } @Override public int length() { return front.length() + rear.length(); } @Override public Queue map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return new Queue<>(front.map(mapper), rear.map(mapper)); } @Override public Queue orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override public Queue orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override public Queue padTo(int length, T element) { final int actualLength = length(); if (length <= actualLength) { return this; } else { return ofAll(toList().padTo(length, element)); } } @Override public Queue leftPadTo(int length, T element) { final int actualLength = length(); if (length <= actualLength) { return this; } else { return ofAll(toList().leftPadTo(length, element)); } } @Override public Queue patch(int from, Iterable that, int replaced) { from = from < 0 ? 0 : from; replaced = replaced < 0 ? 0 : replaced; Queue result = take(from).appendAll(that); from += replaced; result = result.appendAll(drop(from)); return result; } @Override public Tuple2, Queue> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return toList().partition(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue); } @Override public Queue> permutations() { return ofAll(toList().permutations().map(io.vavr.collection.List::toQueue)); } @Override public Queue prepend(T element) { return new Queue<>(front.prepend(element), rear); } @SuppressWarnings("unchecked") @Override public Queue prependAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() && elements instanceof Queue) { return (Queue) elements; } else { final io.vavr.collection.List newFront = front.prependAll(elements); return (newFront == front) ? this : new Queue<>(newFront, rear); } } @Override public Queue remove(T element) { final io.vavr.collection.List removed = toList().remove(element); return ofAll(removed.length() == length() ? this : removed); } @Override public Queue removeFirst(Predicate predicate) { final io.vavr.collection.List removed = toList().removeFirst(predicate); return ofAll(removed.length() == length() ? this : removed); } @Override public Queue removeLast(Predicate predicate) { final io.vavr.collection.List removed = toList().removeLast(predicate); return ofAll(removed.length() == length() ? this : removed); } @Override public Queue removeAt(int index) { return ofAll(toList().removeAt(index)); } @Override public Queue removeAll(T element) { return io.vavr.collection.Collections.removeAll(this, element); } @Override public Queue replace(T currentElement, T newElement) { final io.vavr.collection.List newFront = front.replace(currentElement, newElement); final io.vavr.collection.List newRear = rear.replace(currentElement, newElement); return newFront.size() + newRear.size() == 0 ? empty() : newFront == front && newRear == rear ? this : new Queue<>(newFront, newRear); } @Override public Queue replaceAll(T currentElement, T newElement) { final io.vavr.collection.List newFront = front.replaceAll(currentElement, newElement); final io.vavr.collection.List newRear = rear.replaceAll(currentElement, newElement); return newFront.size() + newRear.size() == 0 ? empty() : newFront == front && newRear == rear ? this : new Queue<>(newFront, newRear); } @Override public Queue reverse() { return isEmpty() ? this : ofAll(toList().reverse()); } @Override public Queue rotateLeft(int n) { return Collections.rotateLeft(this, n); } @Override public Queue rotateRight(int n) { return Collections.rotateRight(this, n); } @Override public Queue scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override public Queue scanLeft(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, Iterator::toQueue); } @Override public Queue scanRight(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, Iterator::toQueue); } @Override public Queue shuffle() { return io.vavr.collection.Collections.shuffle(this, Queue::ofAll); } @Override public Queue slice(int beginIndex, int endIndex) { return ofAll(toList().slice(beginIndex, endIndex)); } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(Queue::ofAll); } @Override public Iterator> sliding(int size) { return sliding(size, 1); } @Override public Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(Queue::ofAll); } @Override public Queue sorted() { return ofAll(toList().sorted()); } @Override public Queue sorted(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return ofAll(toList().sorted(comparator)); } @Override public > Queue sortBy(Function mapper) { return sortBy(U::compareTo, mapper); } @Override public Queue sortBy(Comparator comparator, Function mapper) { return Collections.sortBy(this, comparator, mapper, collector()); } @Override public Tuple2, Queue> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return toList().span(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue); } @Override public Tuple2, Queue> splitAt(int n) { return toList().splitAt(n).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue); } @Override public Tuple2, Queue> splitAt(Predicate predicate) { return toList().splitAt(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue); } @Override public Tuple2, Queue> splitAtInclusive(Predicate predicate) { return toList().splitAtInclusive(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue); } @Override public boolean startsWith(Iterable that, int offset) { return toList().startsWith(that, offset); } @Override public Queue subSequence(int beginIndex) { if (beginIndex < 0 || beginIndex > length()) { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ")"); } else { return drop(beginIndex); } } @Override public Queue subSequence(int beginIndex, int endIndex) { Collections.subSequenceRangeCheck(beginIndex, endIndex, length()); if (beginIndex == endIndex) { return empty(); } else if (beginIndex == 0 && endIndex == length()) { return this; } else { return ofAll(toList().subSequence(beginIndex, endIndex)); } } @Override public Queue tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty " + stringPrefix()); } else { return new Queue<>(front.tail(), rear); } } @Override public Queue take(int n) { if (n <= 0) { return empty(); } if (n >= length()) { return this; } final int frontLength = front.length(); if (n < frontLength) { return new Queue<>(front.take(n), io.vavr.collection.List.empty()); } else if (n == frontLength) { return new Queue<>(front, io.vavr.collection.List.empty()); } else { return new Queue<>(front, rear.takeRight(n - frontLength)); } } @Override public Queue takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final io.vavr.collection.List taken = toList().takeUntil(predicate); return taken.length() == length() ? this : ofAll(taken); } @Override public Queue takeRight(int n) { if (n <= 0) { return empty(); } if (n >= length()) { return this; } final int rearLength = rear.length(); if (n < rearLength) { return new Queue<>(rear.take(n).reverse(), io.vavr.collection.List.empty()); } else if (n == rearLength) { return new Queue<>(rear.reverse(), io.vavr.collection.List.empty()); } else { return new Queue<>(front.takeRight(n - rearLength), rear); } } @Override public Queue takeRightUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final io.vavr.collection.List taken = toList().takeRightUntil(predicate); return taken.length() == length() ? this : ofAll(taken); } @Override public Queue takeRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeRightUntil(predicate.negate()); } /** * Transforms this {@code Queue}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public Tuple2, Queue> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return toList().unzip(unzipper).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue); } @Override public Tuple3, Queue, Queue> unzip3(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return toList().unzip3(unzipper).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue); } @Override public Queue update(int index, T element) { return ofAll(toList().update(index, element)); } @Override public Queue update(int index, Function updater) { Objects.requireNonNull(updater, "updater is null"); return update(index, updater.apply(get(index))); } @Override public Queue> zip(Iterable that) { return zipWith(that, Tuple::of); } @SuppressWarnings("unchecked") @Override public Queue zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return ofAll(toList().zipWith(that, mapper)); } @Override public Queue> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return ofAll(toList().zipAll(that, thisElem, thatElem)); } @Override public Queue> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public Queue zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return ofAll(toList().zipWithIndex(mapper)); } private Object readResolve() { return isEmpty() ? EMPTY : this; } @Override public String stringPrefix() { return "Queue"; } @Override public boolean equals(Object o) { return io.vavr.collection.Collections.equals(this, o); } @Override public int hashCode() { return io.vavr.collection.Collections.hashOrdered(this); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/RedBlackTree.java000066400000000000000000001043211342074374400250430ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.collection.RedBlackTreeModule.Empty; import io.vavr.collection.RedBlackTreeModule.Node; import io.vavr.control.Option; import java.io.Serializable; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import static io.vavr.collection.RedBlackTree.Color.BLACK; import static io.vavr.collection.RedBlackTree.Color.RED; /** * Purely functional Red/Black Tree, inspired by Kazu Yamamoto's Haskell implementation. *

* Based on *

* * @param Component type * @author Daniel Dietrich */ interface RedBlackTree extends Iterable { static RedBlackTree empty(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return new Empty<>(comparator); } static RedBlackTree of(Comparator comparator, T value) { Objects.requireNonNull(comparator, "comparator is null"); final Empty empty = new Empty<>(comparator); return new Node<>(BLACK, 1, empty, value, empty, empty); } @SafeVarargs static RedBlackTree of(Comparator comparator, T... values) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(values, "values is null"); RedBlackTree tree = empty(comparator); for (T value : values) { tree = tree.insert(value); } return tree; } @SuppressWarnings("unchecked") static RedBlackTree ofAll(Comparator comparator, Iterable values) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(values, "values is null"); // function equality is not computable => same object check if (values instanceof RedBlackTree && ((RedBlackTree) values).comparator() == comparator) { return (RedBlackTree) values; } else { RedBlackTree tree = empty(comparator); for (T value : values) { tree = tree.insert(value); } return tree; } } /** * Inserts a new value into this tree. * * @param value A value. * @return A new tree if this tree does not contain the given value, otherwise the same tree instance. */ default RedBlackTree insert(T value) { return Node.insert(this, value).color(BLACK); } /** * Return the {@link Color} of this Red/Black Tree node. *

* An empty node is {@code BLACK} by definition. * * @return Either {@code RED} or {@code BLACK}. */ Color color(); /** * Returns the underlying {@link java.util.Comparator} of this RedBlackTree. * * @return The comparator. */ Comparator comparator(); /** * Checks, if this {@code RedBlackTree} contains the given {@code value}. * * @param value A value. * @return true, if this tree contains the value, false otherwise. */ boolean contains(T value); /** * Deletes a value from this RedBlackTree. * * @param value A value * @return A new RedBlackTree if the value is present, otherwise this. */ default RedBlackTree delete(T value) { final RedBlackTree tree = Node.delete(this, value)._1; return Node.color(tree, BLACK); } default RedBlackTree difference(RedBlackTree tree) { Objects.requireNonNull(tree, "tree is null"); if (isEmpty() || tree.isEmpty()) { return this; } else { final Node that = (Node) tree; final Tuple2, RedBlackTree> split = Node.split(this, that.value); return Node.merge(split._1.difference(that.left), split._2.difference(that.right)); } } /** * Returns the empty instance of this RedBlackTree. * * @return An empty ReadBlackTree */ RedBlackTree emptyInstance(); /** * Finds the value stored in this tree, if exists, by applying the underlying comparator to the tree elements and * the given element. *

* Especially the value returned may differ from the given value, even if the underlying comparator states that * both are equal. * * @param value A value * @return Some value, if this tree contains a value equal to the given value according to the underlying comparator. Otherwise None. */ Option find(T value); default RedBlackTree intersection(RedBlackTree tree) { Objects.requireNonNull(tree, "tree is null"); if (isEmpty()) { return this; } else if (tree.isEmpty()) { return tree; } else { final Node that = (Node) tree; final Tuple2, RedBlackTree> split = Node.split(this, that.value); if (contains(that.value)) { return Node.join(split._1.intersection(that.left), that.value, split._2.intersection(that.right)); } else { return Node.merge(split._1.intersection(that.left), split._2.intersection(that.right)); } } } /** * Checks if this {@code RedBlackTree} is empty, i.e. an instance of {@code Leaf}. * * @return true, if it is empty, false otherwise. */ boolean isEmpty(); /** * Returns the left child if this is a non-empty node, otherwise throws. * * @return The left child. * @throws UnsupportedOperationException if this RedBlackTree is empty */ RedBlackTree left(); /** * Returns the maximum element of this tree according to the underlying comparator. * * @return Some element, if this is not empty, otherwise None */ default Option max() { return isEmpty() ? Option.none() : Option.some(Node.maximum((Node) this)); } /** * Returns the minimum element of this tree according to the underlying comparator. * * @return Some element, if this is not empty, otherwise None */ default Option min() { return isEmpty() ? Option.none() : Option.some(Node.minimum((Node) this)); } /** * Returns the right child if this is a non-empty node, otherwise throws. * * @return The right child. * @throws UnsupportedOperationException if this RedBlackTree is empty */ RedBlackTree right(); /** * Returns the size of this tree. * * @return the number of nodes of this tree and 0 if this is the empty tree */ int size(); /** * Adds all of the elements of the given {@code tree} to this tree, if not already present. * * @param tree The RedBlackTree to form the union with. * @return A new RedBlackTree that contains all distinct elements of this and the given {@code tree}. */ default RedBlackTree union(RedBlackTree tree) { Objects.requireNonNull(tree, "tree is null"); if (tree.isEmpty()) { return this; } else { final Node that = (Node) tree; if (isEmpty()) { return that.color(BLACK); } else { final Tuple2, RedBlackTree> split = Node.split(this, that.value); return Node.join(split._1.union(that.left), that.value, split._2.union(that.right)); } } } /** * Returns the value of the current tree node or throws if this is empty. * * @return The value. * @throws NoSuchElementException if this is the empty node. */ T value(); /** * Returns an Iterator that iterates elements in the order induced by the underlying Comparator. *

* Internally an in-order traversal of the RedBlackTree is performed. *

* Example: * *


     *       4
     *      / \
     *     2   6
     *    / \ / \
     *   1  3 5  7
     * 
* * Iteration order: 1, 2, 3, 4, 5, 6, 7 *

* See also Implement Iterator for BinaryTree I (In-order). */ @Override default Iterator iterator() { if (isEmpty()) { return Iterator.empty(); } else { final Node that = (Node) this; return new AbstractIterator() { List> stack = pushLeftChildren(List.empty(), that); @Override public boolean hasNext() { return !stack.isEmpty(); } @Override public T getNext() { final Tuple2, ? extends List>> result = stack.pop2(); final Node node = result._1; stack = node.right.isEmpty() ? result._2 : pushLeftChildren(result._2, (Node) node.right); return result._1.value; } private List> pushLeftChildren(List> initialStack, Node that) { List> stack = initialStack; RedBlackTree tree = that; while (!tree.isEmpty()) { final Node node = (Node) tree; stack = stack.push(node); tree = node.left; } return stack; } }; } } /** * Returns a Lisp like representation of this tree. * * @return This Tree as Lisp like String. */ @Override String toString(); enum Color { RED, BLACK; @Override public String toString() { return (this == RED) ? "R" : "B"; } } } interface RedBlackTreeModule { /** * A non-empty tree node. * * @param Component type */ final class Node implements RedBlackTree, Serializable { private static final long serialVersionUID = 1L; final Color color; final int blackHeight; final RedBlackTree left; final T value; final RedBlackTree right; final Empty empty; final int size; // This is no public API! The RedBlackTree takes care of passing the correct Comparator. Node(Color color, int blackHeight, RedBlackTree left, T value, RedBlackTree right, Empty empty) { this.color = color; this.blackHeight = blackHeight; this.left = left; this.value = value; this.right = right; this.empty = empty; this.size = left.size() + right.size() + 1; } @Override public Color color() { return color; } @Override public Comparator comparator() { return empty.comparator; } @Override public boolean contains(T value) { final int result = empty.comparator.compare(value, this.value); if (result < 0) { return left.contains(value); } else if (result > 0) { return right.contains(value); } else { return true; } } @Override public Empty emptyInstance() { return empty; } @Override public Option find(T value) { final int result = empty.comparator.compare(value, this.value); if (result < 0) { return left.find(value); } else if (result > 0) { return right.find(value); } else { return Option.some(this.value); } } @Override public boolean isEmpty() { return false; } @Override public RedBlackTree left() { return left; } @Override public RedBlackTree right() { return right; } @Override public int size() { return size; } @Override public T value() { return value; } @Override public String toString() { return isLeaf() ? "(" + color + ":" + value + ")" : toLispString(this); } private static String toLispString(RedBlackTree tree) { if (tree.isEmpty()) { return ""; } else { final Node node = (Node) tree; final String value = node.color + ":" + node.value; if (node.isLeaf()) { return value; } else { final String left = node.left.isEmpty() ? "" : " " + toLispString(node.left); final String right = node.right.isEmpty() ? "" : " " + toLispString(node.right); return "(" + value + left + right + ")"; } } } private boolean isLeaf() { return left.isEmpty() && right.isEmpty(); } Node color(Color color) { return (this.color == color) ? this : new Node<>(color, blackHeight, left, value, right, empty); } static RedBlackTree color(RedBlackTree tree, Color color) { return tree.isEmpty() ? tree : ((Node) tree).color(color); } private static Node balanceLeft(Color color, int blackHeight, RedBlackTree left, T value, RedBlackTree right, Empty empty) { if (color == BLACK) { if (!left.isEmpty()) { final Node ln = (Node) left; if (ln.color == RED) { if (!ln.left.isEmpty()) { final Node lln = (Node) ln.left; if (lln.color == RED) { final Node newLeft = new Node<>(BLACK, blackHeight, lln.left, lln.value, lln.right, empty); final Node newRight = new Node<>(BLACK, blackHeight, ln.right, value, right, empty); return new Node<>(RED, blackHeight + 1, newLeft, ln.value, newRight, empty); } } if (!ln.right.isEmpty()) { final Node lrn = (Node) ln.right; if (lrn.color == RED) { final Node newLeft = new Node<>(BLACK, blackHeight, ln.left, ln.value, lrn.left, empty); final Node newRight = new Node<>(BLACK, blackHeight, lrn.right, value, right, empty); return new Node<>(RED, blackHeight + 1, newLeft, lrn.value, newRight, empty); } } } } } return new Node<>(color, blackHeight, left, value, right, empty); } private static Node balanceRight(Color color, int blackHeight, RedBlackTree left, T value, RedBlackTree right, Empty empty) { if (color == BLACK) { if (!right.isEmpty()) { final Node rn = (Node) right; if (rn.color == RED) { if (!rn.right.isEmpty()) { final Node rrn = (Node) rn.right; if (rrn.color == RED) { final Node newLeft = new Node<>(BLACK, blackHeight, left, value, rn.left, empty); final Node newRight = new Node<>(BLACK, blackHeight, rrn.left, rrn.value, rrn.right, empty); return new Node<>(RED, blackHeight + 1, newLeft, rn.value, newRight, empty); } } if (!rn.left.isEmpty()) { final Node rln = (Node) rn.left; if (rln.color == RED) { final Node newLeft = new Node<>(BLACK, blackHeight, left, value, rln.left, empty); final Node newRight = new Node<>(BLACK, blackHeight, rln.right, rn.value, rn.right, empty); return new Node<>(RED, blackHeight + 1, newLeft, rln.value, newRight, empty); } } } } } return new Node<>(color, blackHeight, left, value, right, empty); } private static Tuple2, Boolean> blackify(RedBlackTree tree) { if (tree instanceof Node) { final Node node = (Node) tree; if (node.color == RED) { return Tuple.of(node.color(BLACK), false); } } return Tuple.of(tree, true); } static Tuple2, Boolean> delete(RedBlackTree tree, T value) { if (tree.isEmpty()) { return Tuple.of(tree, false); } else { final Node node = (Node) tree; final int comparison = node.comparator().compare(value, node.value); if (comparison < 0) { final Tuple2, Boolean> deleted = delete(node.left, value); final RedBlackTree l = deleted._1; final boolean d = deleted._2; if (d) { return Node.unbalancedRight(node.color, node.blackHeight - 1, l, node.value, node.right, node.empty); } else { final Node newNode = new Node<>(node.color, node.blackHeight, l, node.value, node.right, node.empty); return Tuple.of(newNode, false); } } else if (comparison > 0) { final Tuple2, Boolean> deleted = delete(node.right, value); final RedBlackTree r = deleted._1; final boolean d = deleted._2; if (d) { return Node.unbalancedLeft(node.color, node.blackHeight - 1, node.left, node.value, r, node.empty); } else { final Node newNode = new Node<>(node.color, node.blackHeight, node.left, node.value, r, node.empty); return Tuple.of(newNode, false); } } else { if (node.right.isEmpty()) { if (node.color == BLACK) { return blackify(node.left); } else { return Tuple.of(node.left, false); } } else { final Node nodeRight = (Node) node.right; final Tuple3, Boolean, T> newRight = deleteMin(nodeRight); final RedBlackTree r = newRight._1; final boolean d = newRight._2; final T m = newRight._3; if (d) { return Node.unbalancedLeft(node.color, node.blackHeight - 1, node.left, m, r, node.empty); } else { final RedBlackTree newNode = new Node<>(node.color, node.blackHeight, node.left, m, r, node.empty); return Tuple.of(newNode, false); } } } } } private static Tuple3, Boolean, T> deleteMin(Node node) { if (node.color() == BLACK && node.left().isEmpty() && node.right.isEmpty()){ return Tuple.of(node.empty, true, node.value()); } else if (node.color() == BLACK && node.left().isEmpty() && node.right().color() == RED){ return Tuple.of(((Node)node.right()).color(BLACK), false, node.value()); } else if (node.color() == RED && node.left().isEmpty()){ return Tuple.of(node.right(), false, node.value()); } else{ final Node nodeLeft = (Node) node.left; final Tuple3, Boolean, T> newNode = deleteMin(nodeLeft); final RedBlackTree l = newNode._1; final boolean deleted = newNode._2; final T m = newNode._3; if (deleted) { final Tuple2, Boolean> tD = Node.unbalancedRight(node.color, node.blackHeight - 1, l, node.value, node.right, node.empty); return Tuple.of(tD._1, tD._2, m); } else { final Node tD = new Node<>(node.color, node.blackHeight, l, node.value, node.right, node.empty); return Tuple.of(tD, false, m); } } } static Node insert(RedBlackTree tree, T value) { if (tree.isEmpty()) { final Empty empty = (Empty) tree; return new Node<>(RED, 1, empty, value, empty, empty); } else { final Node node = (Node) tree; final int comparison = node.comparator().compare(value, node.value); if (comparison < 0) { final Node newLeft = insert(node.left, value); return (newLeft == node.left) ? node : Node.balanceLeft(node.color, node.blackHeight, newLeft, node.value, node.right, node.empty); } else if (comparison > 0) { final Node newRight = insert(node.right, value); return (newRight == node.right) ? node : Node.balanceRight(node.color, node.blackHeight, node.left, node.value, newRight, node.empty); } else { // DEV-NOTE: Even if there is no _comparison_ difference, the object may not be _equal_. // To save an equals() call, which may be expensive, we return a new instance. return new Node<>(node.color, node.blackHeight, node.left, value, node.right, node.empty); } } } private static boolean isRed(RedBlackTree tree) { return !tree.isEmpty() && ((Node) tree).color == RED; } static RedBlackTree join(RedBlackTree t1, T value, RedBlackTree t2) { if (t1.isEmpty()) { return t2.insert(value); } else if (t2.isEmpty()) { return t1.insert(value); } else { final Node n1 = (Node) t1; final Node n2 = (Node) t2; final int comparison = n1.blackHeight - n2.blackHeight; if (comparison < 0) { return Node.joinLT(n1, value, n2, n1.blackHeight).color(BLACK); } else if (comparison > 0) { return Node.joinGT(n1, value, n2, n2.blackHeight).color(BLACK); } else { return new Node<>(BLACK, n1.blackHeight + 1, n1, value, n2, n1.empty); } } } private static Node joinGT(Node n1, T value, Node n2, int h2) { if (n1.blackHeight == h2) { return new Node<>(RED, h2 + 1, n1, value, n2, n1.empty); } else { final Node node = joinGT((Node) n1.right, value, n2, h2); return Node.balanceRight(n1.color, n1.blackHeight, n1.left, n1.value, node, n2.empty); } } private static Node joinLT(Node n1, T value, Node n2, int h1) { if (n2.blackHeight == h1) { return new Node<>(RED, h1 + 1, n1, value, n2, n1.empty); } else { final Node node = joinLT(n1, value, (Node) n2.left, h1); return Node.balanceLeft(n2.color, n2.blackHeight, node, n2.value, n2.right, n2.empty); } } static RedBlackTree merge(RedBlackTree t1, RedBlackTree t2) { if (t1.isEmpty()) { return t2; } else if (t2.isEmpty()) { return t1; } else { final Node n1 = (Node) t1; final Node n2 = (Node) t2; final int comparison = n1.blackHeight - n2.blackHeight; if (comparison < 0) { final Node node = Node.mergeLT(n1, n2, n1.blackHeight); return Node.color(node, BLACK); } else if (comparison > 0) { final Node node = Node.mergeGT(n1, n2, n2.blackHeight); return Node.color(node, BLACK); } else { final Node node = Node.mergeEQ(n1, n2); return Node.color(node, BLACK); } } } private static Node mergeEQ(Node n1, Node n2) { final T m = Node.minimum(n2); final RedBlackTree t2 = Node.deleteMin(n2)._1; final int h2 = t2.isEmpty() ? 0 : ((Node) t2).blackHeight; if (n1.blackHeight == h2) { return new Node<>(RED, n1.blackHeight + 1, n1, m, t2, n1.empty); } else if (isRed(n1.left)) { final Node node = new Node<>(BLACK, n1.blackHeight, n1.right, m, t2, n1.empty); return new Node<>(RED, n1.blackHeight + 1, Node.color(n1.left, BLACK), n1.value, node, n1.empty); } else if (isRed(n1.right)) { final RedBlackTree rl = ((Node) n1.right).left; final T rx = ((Node) n1.right).value; final RedBlackTree rr = ((Node) n1.right).right; final Node left = new Node<>(RED, n1.blackHeight, n1.left, n1.value, rl, n1.empty); final Node right = new Node<>(RED, n1.blackHeight, rr, m, t2, n1.empty); return new Node<>(BLACK, n1.blackHeight, left, rx, right, n1.empty); } else { return new Node<>(BLACK, n1.blackHeight, n1.color(RED), m, t2, n1.empty); } } private static Node mergeGT(Node n1, Node n2, int h2) { if (n1.blackHeight == h2) { return Node.mergeEQ(n1, n2); } else { final Node node = Node.mergeGT((Node) n1.right, n2, h2); return Node.balanceRight(n1.color, n1.blackHeight, n1.left, n1.value, node, n1.empty); } } private static Node mergeLT(Node n1, Node n2, int h1) { if (n2.blackHeight == h1) { return Node.mergeEQ(n1, n2); } else { final Node node = Node.mergeLT(n1, (Node) n2.left, h1); return Node.balanceLeft(n2.color, n2.blackHeight, node, n2.value, n2.right, n2.empty); } } static T maximum(Node node) { Node curr = node; while (!curr.right.isEmpty()) { curr = (Node) curr.right; } return curr.value; } static T minimum(Node node) { Node curr = node; while (!curr.left.isEmpty()) { curr = (Node) curr.left; } return curr.value; } static Tuple2, RedBlackTree> split(RedBlackTree tree, T value) { if (tree.isEmpty()) { return Tuple.of(tree, tree); } else { final Node node = (Node) tree; final int comparison = node.comparator().compare(value, node.value); if (comparison < 0) { final Tuple2, RedBlackTree> split = Node.split(node.left, value); return Tuple.of(split._1, Node.join(split._2, node.value, Node.color(node.right, BLACK))); } else if (comparison > 0) { final Tuple2, RedBlackTree> split = Node.split(node.right, value); return Tuple.of(Node.join(Node.color(node.left, BLACK), node.value, split._1), split._2); } else { return Tuple.of(Node.color(node.left, BLACK), Node.color(node.right, BLACK)); } } } private static Tuple2, Boolean> unbalancedLeft(Color color, int blackHeight, RedBlackTree left, T value, RedBlackTree right, Empty empty) { if (!left.isEmpty()) { final Node ln = (Node) left; if (ln.color == BLACK) { final Node newNode = Node.balanceLeft(BLACK, blackHeight, ln.color(RED), value, right, empty); return Tuple.of(newNode, color == BLACK); } else if (color == BLACK && !ln.right.isEmpty()) { final Node lrn = (Node) ln.right; if (lrn.color == BLACK) { final Node newRightNode = Node.balanceLeft(BLACK, blackHeight, lrn.color(RED), value, right, empty); final Node newNode = new Node<>(BLACK, ln.blackHeight, ln.left, ln.value, newRightNode, empty); return Tuple.of(newNode, false); } } } throw new IllegalStateException("unbalancedLeft(" + color + ", " + blackHeight + ", " + left + ", " + value + ", " + right + ")"); } private static Tuple2, Boolean> unbalancedRight(Color color, int blackHeight, RedBlackTree left, T value, RedBlackTree right, Empty empty) { if (!right.isEmpty()) { final Node rn = (Node) right; if (rn.color == BLACK) { final Node newNode = Node.balanceRight(BLACK, blackHeight, left, value, rn.color(RED), empty); return Tuple.of(newNode, color == BLACK); } else if (color == BLACK && !rn.left.isEmpty()) { final Node rln = (Node) rn.left; if (rln.color == BLACK) { final Node newLeftNode = Node.balanceRight(BLACK, blackHeight, left, value, rln.color(RED), empty); final Node newNode = new Node<>(BLACK, rn.blackHeight, newLeftNode, rn.value, rn.right, empty); return Tuple.of(newNode, false); } } } throw new IllegalStateException("unbalancedRight(" + color + ", " + blackHeight + ", " + left + ", " + value + ", " + right + ")"); } } /** * The empty tree node. It can't be a singleton because it depends on a {@link Comparator}. * * @param Component type */ final class Empty implements RedBlackTree, Serializable { private static final long serialVersionUID = 1L; final Comparator comparator; // This is no public API! The RedBlackTree takes care of passing the correct Comparator. @SuppressWarnings("unchecked") Empty(Comparator comparator) { this.comparator = (Comparator) comparator; } @Override public Color color() { return BLACK; } @Override public Comparator comparator() { return comparator; } @Override public boolean contains(T value) { return false; } @Override public Empty emptyInstance() { return this; } @Override public Option find(T value) { return Option.none(); } @Override public boolean isEmpty() { return true; } @Override public RedBlackTree left() { throw new UnsupportedOperationException("left on empty"); } @Override public RedBlackTree right() { throw new UnsupportedOperationException("right on empty"); } @Override public int size() { return 0; } @Override public T value() { throw new NoSuchElementException("value on empty"); } @Override public String toString() { return "()"; } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Seq.java000066400000000000000000001356101342074374400233110ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.*; /** * Interface for immutable sequential data structures. *

* Basic operations: * *

    *
  • {@link #append(Object)}
  • *
  • {@link #appendAll(Iterable)}
  • *
  • {@link #insert(int, Object)}
  • *
  • {@link #insertAll(int, Iterable)}
  • *
  • {@link #prepend(Object)}
  • *
  • {@link #prependAll(Iterable)}
  • *
  • {@link #update(int, Object)}
  • *
* * Conversion: * *
    *
  • {@link #asPartialFunction}
  • *
* * Filtering: * *
    *
  • {@link #remove(Object)}
  • *
  • {@link #removeAll(Object)}
  • *
  • {@link #removeAll(Iterable)}
  • *
  • {@link #removeAt(int)}
  • *
  • {@link #removeFirst(Predicate)}
  • *
  • {@link #removeLast(Predicate)}
  • *
* * Selection: * *
    *
  • {@link #get(int)}
  • *
  • {@link #indexOf(Object)}
  • *
  • {@link #indexOf(Object, int)}
  • *
  • {@link #lastIndexOf(Object)}
  • *
  • {@link #lastIndexOf(Object, int)}
  • *
  • {@link #slice(int, int)}
  • *
  • {@link #subSequence(int)}
  • *
  • {@link #subSequence(int, int)}
  • *
* * Transformation: * *
    *
  • {@link #crossProduct()}
  • *
  • {@link #crossProduct(int)}
  • *
  • {@link #crossProduct(Iterable)}
  • *
  • {@link #combinations()}
  • *
  • {@link #combinations(int)}
  • *
  • {@link #intersperse(Object)}
  • *
  • {@link #padTo(int, Object)}
  • *
  • {@link #permutations()}
  • *
  • {@link #reverse()}
  • *
  • {@link #shuffle()}
  • *
  • {@link #sorted()}
  • *
  • {@link #sorted(Comparator)}
  • *
  • {@link #splitAt(int)}
  • *
  • {@link #unzip(Function)}
  • *
  • {@link #zip(Iterable)}
  • *
  • {@link #zipAll(Iterable, Object, Object)}
  • *
  • {@link #zipWithIndex()}
  • *
* * Traversal: * *
    *
  • {@link #iterator(int)}
  • *
* * Views: * *
    *
  • {@link #asJava()}
  • *
  • {@link #asJava(Consumer)}
  • *
  • {@link #asJavaMutable()}
  • *
  • {@link #asJavaMutable(Consumer)}
  • *
* * @param Component type * @author Daniel Dietrich */ public interface Seq extends Traversable, PartialFunction, Serializable { long serialVersionUID = 1L; /** * Narrows a widened {@code Seq} to {@code Seq} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param seq A {@code Seq}. * @param Component type of the {@code Seq}. * @return the given {@code seq} instance as narrowed type {@code Seq}. */ @SuppressWarnings("unchecked") static Seq narrow(Seq seq) { return (Seq) seq; } /** * Appends an element to this. * * @param element An element * @return A new Seq containing the given element appended to this elements */ Seq append(T element); /** * Appends all given elements to this. * * @param elements An Iterable of elements * @return A new Seq containing the given elements appended to this elements * @throws NullPointerException if {@code elements} is null */ Seq appendAll(Iterable elements); /** * A {@code Seq} is a partial function which returns the element at the specified index by calling * {@linkplain #get(int)}. * * @param index an index * @return the element at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() * @deprecated Will be removed */ @Deprecated @Override default T apply(Integer index) { return get(index); } /** * Creates an immutable {@link java.util.List} view on top of this {@code Seq}, * i.e. calling mutators will result in {@link UnsupportedOperationException} at runtime. *

* The difference to conversion methods {@code toJava*()} is that * *

    *
  • A view is created in O(1) (constant time) whereas conversion takes O(n) (linear time), with n = collection size.
  • *
  • The operations on a view have the same performance characteristics than the underlying persistent Vavr collection whereas the performance characteristics of a converted collection are those of the Java standard collections.
  • *
* * Please note that our immutable {@code java.util.List} view throws {@code UnsupportedOperationException} before * checking method arguments. Java does handle this case inconsistently. * * @return A new immutable {@link java.util.Collection} view on this {@code Traversable}. */ @GwtIncompatible java.util.List asJava(); /** * Creates an immutable {@link java.util.List} view on top of this {@code Seq} * that is passed to the given {@code action}. * * @param action A side-effecting unit of work that operates on an immutable {@code java.util.List} view. * @return this instance * @see Seq#asJava() */ @GwtIncompatible Seq asJava(Consumer> action); /** * Creates a mutable {@link java.util.List} view on top of this {@code Seq}, * i.e. all mutator methods of the {@link java.util.List} are implemented. * * @return A new mutable {@link java.util.Collection} view on this {@code Traversable}. * @see Seq#asJava() */ @GwtIncompatible java.util.List asJavaMutable(); /** * Creates a mutable {@link java.util.List} view on top of this {@code Seq} * that is passed to the given {@code action}. * * @param action A side-effecting unit of work that operates on a mutable {@code java.util.List} view. * @return this instance, if only read operations are performed on the {@code java.util.List} view or a new instance of this type, if write operations are performed on the {@code java.util.List} view. * @see Seq#asJavaMutable() */ @GwtIncompatible Seq asJavaMutable(Consumer> action); /** * Turns this {@code Seq} into a {@link PartialFunction} which is defined at a specific index, if this {@code Seq} * contains at least index + 1 elements. When applied to a defined index, the partial function will return * the value of this {@code Seq} at the specified index. * * @return a new {@link PartialFunction} * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ PartialFunction asPartialFunction() throws IndexOutOfBoundsException; @Override Seq collect(PartialFunction partialFunction); /** * Returns the union of all combinations from k = 0 to length(). *

* Examples: *

     * 
     * [].combinations() = [[]]
     *
     * [1,2,3].combinations() = [
     *   [],                  // k = 0
     *   [1], [2], [3],       // k = 1
     *   [1,2], [1,3], [2,3], // k = 2
     *   [1,2,3]              // k = 3
     * ]
     * 
     * 
* * @return the combinations of this */ Seq> combinations(); /** * Returns the k-combination of this traversable, i.e. all subset of this of k distinct elements. * * @param k Size of subsets * @return the k-combination of this elements * @see Combination */ Seq> combinations(int k); /** * Tests whether this sequence contains a given sequence as a slice. *

* Note: may not terminate for infinite sequences. * * @param that the sequence to test * @return true if this sequence contains a slice with the same elements as that, otherwise false. * @throws NullPointerException if {@code that} is null. */ default boolean containsSlice(Iterable that) { Objects.requireNonNull(that, "that is null"); return indexOfSlice(that) >= 0; } /** * Calculates the cross product (, i.e. square) of {@code this x this}. *

* Example: *

     * 
     * // = List of Tuples (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)
     * List.of(1, 2, 3).crossProduct();
     * 
     * 
* * @return a new Iterator containing the square of {@code this} */ default Iterator> crossProduct() { return crossProduct(this); } /** * Calculates the n-ary cartesian power (or cross product or simply product) of this. *

* Example: *

     * 
     * // = ((A,A), (A,B), (A,C), ..., (B,A), (B,B), ..., (Z,Y), (Z,Z))
     * CharSeq.rangeClosed('A', 'Z').crossProduct(2);
     * 
     * 
*

* Cartesian power of negative value will return empty iterator. *

* Example: *

     * 
     * // = ()
     * CharSeq.rangeClosed('A', 'Z').crossProduct(-1);
     * 
     * 
* * @param power the number of cartesian multiplications * @return A new Iterator representing the n-ary cartesian power of this */ Iterator> crossProduct(int power); /** * Calculates the cross product {@code this x that}. *

* Example: *

     * 
     * // = List of Tuples (1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b')
     * List.of(1, 2, 3).crossProduct(List.of('a', 'b');
     * 
     * 
* * @param that Another iterable * @param Component type * @return a new Iterator containing the cross product {@code this x that} * @throws NullPointerException if that is null */ default Iterator> crossProduct(Iterable that) { Objects.requireNonNull(that, "that is null"); final Stream other = Stream.ofAll(that); return Iterator.ofAll(this).flatMap(a -> other.map(b -> Tuple.of(a, b))); } /** * Tests whether this sequence ends with the given sequence. *

* Note: If the both the receiver object this and the argument that are infinite sequences this method may not terminate. * * @param that the sequence to test * @return true if this sequence has that as a suffix, false otherwise. */ default boolean endsWith(Seq that) { Objects.requireNonNull(that, "that is null"); final Iterator i = this.iterator().drop(length() - that.length()); final Iterator j = that.iterator(); while (i.hasNext() && j.hasNext()) { if (!Objects.equals(i.next(), j.next())) { return false; } } return !j.hasNext(); } /** * Returns the element at the specified index. * * @param index an index * @return the element at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ T get(int index); /** * Returns the index of the first occurrence of the given element or -1 if this does not contain the given element. * * @param element an element * @return the index of the first occurrence of the given element */ default int indexOf(T element) { return indexOf(element, 0); } /** * Returns the index of the first occurrence of the given element as an {@code Option} * * @param element an element * @return {@code Some(index)} or {@code None} if not found. */ default Option indexOfOption(T element) { return Collections.indexOption(indexOf(element)); } /** * Returns the index of the first occurrence of the given element after or at some start index * or -1 if this does not contain the given element. * * @param element an element * @param from start index * @return the index of the first occurrence of the given element */ int indexOf(T element, int from); /** * Returns the index of the first occurrence of the given element, * after or at some start index as an {@code Option} * * @param element an element * @param from start index * @return {@code Some(index)} or {@code None} if not found. */ default Option indexOfOption(T element, int from) { return Collections.indexOption(indexOf(element, from)); } /** * Finds first index where this sequence contains a given sequence as a slice. *

* Note: may not terminate for infinite sequences. * * @param that the sequence to test * @return the first index such that the elements of this sequence starting at this index match * the elements of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ default int indexOfSlice(Iterable that) { return indexOfSlice(that, 0); } /** * Finds first index where this sequence contains a given sequence as an {@code Option} of a slice. *

* Note: may not terminate for infinite sequences. * * @param that the sequence to test * @return {@code Some(index)} or {@code None} if not found. */ default Option indexOfSliceOption(Iterable that) { return Collections.indexOption(indexOfSlice(that)); } /** * Finds first index after or at a start index where this sequence contains a given sequence as a slice. * Note: may not terminate for infinite sequences. * * @param that the sequence to test * @param from the start index * @return the first index >= from such that the elements of this sequence starting at this index match * the elements of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ int indexOfSlice(Iterable that, int from); /** * Finds first index after or at a start index where this sequence contains a given sequence as an {@code Option} of a slice. * Note: may not terminate for infinite sequences. * * @param that the sequence to test * @param from the start index * @return {@code Some(index)} or {@code None} if not found. */ default Option indexOfSliceOption(Iterable that, int from) { return Collections.indexOption(indexOfSlice(that, from)); } /** * Finds index of first element satisfying some predicate. * * @param predicate the predicate used to test elements. * @return the index of the first element of this Seq that satisfies the given * {@code predicate}, or {@code -1}, if none exists. */ default int indexWhere(Predicate predicate) { return indexWhere(predicate, 0); } /** * Finds index of first element satisfying some predicate as an {@code Option}. * * @param predicate the predicate used to test elements. * @return {@code Some(index)} or {@code None} if not found. */ default Option indexWhereOption(Predicate predicate) { return Collections.indexOption(indexWhere(predicate)); } /** * Finds index of the first element satisfying some predicate after or at * some start index. * * @param predicate the predicate used to test elements. * @param from the start index * @return the index {@code >= from} of the first element of this Seq that * satisfies the given {@code predicate}, or {@code -1}, if none exists. */ int indexWhere(Predicate predicate, int from); /** * Finds index of the first element satisfying some predicate after or at * some start index as an {@code Option}. * * @param predicate the predicate used to test elements. * @param from the start index * @return {@code Some(index)} or {@code None} if not found. */ default Option indexWhereOption(Predicate predicate, int from) { return Collections.indexOption(indexWhere(predicate, from)); } /** * Inserts the given element at the specified index. * * @param index an index * @param element an element * @return a new Seq, where the given element is inserted into this at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq insert(int index, T element); /** * Inserts the given elements at the specified index. * * @param index an index * @param elements An Iterable of elements * @return a new Seq, where the given elements are inserted into this at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq insertAll(int index, Iterable elements); /** * Inserts an element between all elements of this Traversable. * * @param element An element. * @return an interspersed version of this */ Seq intersperse(T element); /** * Returns an iterator of this elements starting at the given index. * The result is equivalent to {@code this.subSequence(index).iterator()}. * * @param index an index * @return a new Iterator, starting with the element at the given index or the empty Iterator, if index = length() * @throws IndexOutOfBoundsException if index < 0 or index > length() */ default Iterator iterator(int index) { return subSequence(index).iterator(); } /** * Returns the index of the last occurrence of the given element or -1 if this does not contain the given element. * * @param element an element * @return the index of the last occurrence of the given element */ default int lastIndexOf(T element) { return lastIndexOf(element, Integer.MAX_VALUE); } /** * Returns the index of the last occurrence of the given element as an {@code Option}. * * @param element an element * @return {@code Some(index)} or {@code None} if not found. */ default Option lastIndexOfOption(T element) { return Collections.indexOption(lastIndexOf(element)); } /** * Finds index of last element satisfying some predicate. * * @param predicate the predicate used to test elements. * @return the index of the last element of this Seq that satisfies the given {@code predicate}, or {@code -1}, * if none exists. */ default int lastIndexWhere(Predicate predicate) { return lastIndexWhere(predicate, length() - 1); } /** * Finds index of last element satisfying some predicate as an {@code Option}. * * @param predicate the predicate used to test elements. * @return {@code Some(index)} or {@code None} if not found. */ default Option lastIndexWhereOption(Predicate predicate) { return Collections.indexOption(lastIndexWhere(predicate)); } /** * Finds index of last element satisfying some predicate before or at given * end index. * * @param predicate the predicate used to test elements. * @param end the maximum index of the search * @return the index {@code <= end} of the last element of this Seq that * satisfies the given {@code predicate}, or {@code -1}, if none exists. */ int lastIndexWhere(Predicate predicate, int end); /** * Finds index of last element satisfying some predicate before or at given end index as an {@code Option}. * * @param predicate the predicate used to test elements. * @param end the maximum index of the search * @return {@code Some(index)} or {@code None} if not found. */ default Option lastIndexWhereOption(Predicate predicate, int end) { return Collections.indexOption(lastIndexWhere(predicate, end)); } /** * Turns this sequence into a plain function returning an Option result. * * @return a function that takes an index i and returns the value of * this sequence in a Some if the index is within bounds, otherwise a None. * @deprecated Will be removed */ @Deprecated default Function1> lift() { return i -> (i >= 0 && i < length()) ? Option.some(apply(i)) : Option.none(); } /** * Returns the index of the last occurrence of the given element before or at a given end index * or -1 if this does not contain the given element. * * @param element an element * @param end the end index * @return the index of the last occurrence of the given element */ int lastIndexOf(T element, int end); /** * Returns the index of the last occurrence of the given element before or at a given end index as an {@code Option}. * * @param element an element * @param end the end index * @return {@code Some(index)} or {@code None} if not found. */ default Option lastIndexOfOption(T element, int end) { return Collections.indexOption(lastIndexOf(element, end)); } /** * Finds last index where this sequence contains a given sequence as a slice. *

* Note: will not terminate for infinite sequences. * * @param that the sequence to test * @return the last index such that the elements of this sequence starting a this index match the elements * of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ default int lastIndexOfSlice(Iterable that) { return lastIndexOfSlice(that, Integer.MAX_VALUE); } /** * Finds last index where this sequence contains a given sequence as a slice as an {@code Option}. * * @param that the sequence to test * @return {@code Some(index)} or {@code None} if not found. */ default Option lastIndexOfSliceOption(Iterable that) { return Collections.indexOption(lastIndexOfSlice(that)); } /** * Finds last index before or at a given end index where this sequence contains a given sequence as a slice. * * @param that the sequence to test * @param end the end index * @return the last index <= end such that the elements of this sequence starting at this index match * the elements of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ int lastIndexOfSlice(Iterable that, int end); /** * Finds last index before or at a given end index where this sequence contains a given sequence as a slice as an {@code Option}. * * @param that the sequence to test * @param end the end index * @return {@code Some(index)} or {@code None} if not found. */ default Option lastIndexOfSliceOption(Iterable that, int end) { return Collections.indexOption(lastIndexOfSlice(that, end)); } /** * A copy of this sequence with an element appended until a given target length is reached. *

* Note: lazily-evaluated Seq implementations need to process all elements in order to gather the overall length. * * @param length the target length * @param element the padding element * @return a new sequence consisting of all elements of this sequence followed by the minimal number * of occurrences of element so that the resulting sequence has a length of at least length. */ Seq padTo(int length, T element); /** * A copy of this sequence with an element prepended until a given target length is reached. *

* Note: lazily-evaluated Seq implementations need to process all elements in order to gather the overall length. * * @param length the target length * @param element the padding element * @return a new sequence consisting of all elements of this sequence prepended by the minimal number * of occurrences of element so that the resulting sequence has a length of at least length. */ Seq leftPadTo(int length, T element); /** * Produces a new list where a slice of elements in this list is replaced by another sequence. * * @param from the index of the first replaced element * @param that sequence for replacement * @param replaced the number of elements to drop in the original list * @return a new sequence. */ Seq patch(int from, Iterable that, int replaced); /** * Computes all unique permutations. *

* Example: *

     * 
     * [].permutations() = []
     *
     * [1,2,3].permutations() = [
     *   [1,2,3],
     *   [1,3,2],
     *   [2,1,3],
     *   [2,3,1],
     *   [3,1,2],
     *   [3,2,1]
     * ]
     * 
     * 
* * @return this unique permutations */ Seq> permutations(); /** * Returns the length of the longest prefix whose elements all satisfy some predicate. * * Note: may not terminate for infinite-sized collections. * * @param predicate the predicate used to test elements. * @return the length of the longest prefix of this general sequence such that every * element of the segment satisfies the predicate p. */ default int prefixLength(Predicate predicate) { return segmentLength(predicate, 0); } /** * Prepends an element to this. * * @param element An element * @return A new Seq containing the given element prepended to this elements */ Seq prepend(T element); /** * Prepends all given elements to this. * * @param elements An Iterable of elements * @return A new Seq containing the given elements prepended to this elements */ Seq prependAll(Iterable elements); /** * Removes the first occurrence of the given element. * * @param element An element to be removed from this Seq. * @return a Seq containing all elements of this without the first occurrence of the given element. */ Seq remove(T element); /** * Removes all occurrences of the given element. * * @param element An element to be removed from this Seq. * @return a Seq containing all elements of this but not the given element. */ Seq removeAll(T element); /** * Removes all occurrences of the given elements. * * @param elements Elements to be removed from this Seq. * @return a Seq containing all elements of this but none of the given elements. * @throws NullPointerException if {@code elements} is null */ Seq removeAll(Iterable elements); /** * Returns a new Seq consisting of all elements which do not satisfy the given predicate. * * @deprecated Please use {@link #reject(Predicate)} * @param predicate the predicate used to test elements * @return a new Seq * @throws NullPointerException if {@code predicate} is null */ @Deprecated Seq removeAll(Predicate predicate); /** * Removes the element at the specified position in this sequence. Shifts any subsequent elements to the left * (subtracts one from their indices). * * @param index position of element to remove * @return a sequence containing all elements of this without the element at the specified position. * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq removeAt(int index); /** * Removes the first occurrence that satisfy predicate * * @param predicate an predicate * @return a new Seq */ Seq removeFirst(Predicate predicate); /** * Removes the last occurrence that satisfy predicate * * @param predicate an predicate * @return a new Seq */ Seq removeLast(Predicate predicate); /** * Reverses the order of elements. * * @return the reversed elements. */ Seq reverse(); /** * An iterator yielding elements in reversed order. *

* Note: {@code xs.reverseIterator()} is the same as {@code xs.reverse().iterator()} but might * be more efficient. * * @return an iterator yielding the elements of this Seq in reversed order */ Iterator reverseIterator(); /** * Circular rotates the elements by the specified distance to the left direction. * *

{@code
     * // = List(3, 4, 5, 1, 2)
     * List.of(1, 2, 3, 4, 5).rotateLeft(2);
     * }
* * @param n distance of left rotation * @return the rotated elements. */ Seq rotateLeft(int n); /** * Circular rotates the elements by the specified distance to the right direction. * *
{@code
     * // = List(4, 5, 1, 2, 3)
     * List.of(1, 2, 3, 4, 5).rotateRight(2);
     * }
* * @param n distance of right rotation * @return the rotated elements. */ Seq rotateRight(int n); /** * Computes length of longest segment whose elements all satisfy some predicate. *

* Note: may not terminate for infinite sequences. * * @param predicate the predicate used to test elements. * @param from the index where the search starts. * @return the length of the longest segment of this sequence starting from index * from such that every element of the segment satisfies the predicate p. */ int segmentLength(Predicate predicate, int from); /** * Randomize the order of the elements in the current sequence. * * @return a sequence with the same elements as the current sequence in a random order. */ Seq shuffle(); /** * Returns a Seq that is a slice of this. The slice begins with the element at the specified * {@code beginIndex} and extends to the element at index {@code endIndex - 1}. *

* Examples: * *

     * 
     * List.of(1, 2, 3, 4).slice(1, 3); // = (2, 3)
     * List.of(1, 2, 3, 4).slice(0, 4); // = (1, 2, 3, 4)
     * List.of(1, 2, 3, 4).slice(2, 2); // = ()
     * List.of(1, 2).slice(1, 0);       // = ()
     * List.of(1, 2).slice(-10, 10);    // = (1, 2)
     * 
     * 
* * See also {@link #subSequence(int, int)} which throws in some cases instead of returning a sequence. * * @param beginIndex the beginning index, inclusive * @param endIndex the end index, exclusive * @return the specified slice */ Seq slice(int beginIndex, int endIndex); /** * Sorts this elements according to their natural order. If this elements are not * {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown. * * @return A sorted version of this * @throws ClassCastException if this elements are not {@code Comparable} */ Seq sorted(); /** * Sorts this elements according to the provided {@code Comparator}. If this elements are not * {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown. * * @param comparator A comparator * @return a sorted version of this */ Seq sorted(Comparator comparator); /** * Sorts this elements by comparing the elements in a different domain, using the given {@code mapper}. * * @param mapper A mapper * @param The domain where elements are compared * @return a sorted version of this * @throws NullPointerException if {@code mapper} is null */ > Seq sortBy(Function mapper); /** * Sorts this elements by comparing the elements in a different domain, using the given {@code mapper}. * * @param comparator A comparator * @param mapper A mapper * @param The domain where elements are compared * @return a sorted version of this * @throws NullPointerException if {@code comparator} or {@code mapper} is null */ Seq sortBy(Comparator comparator, Function mapper); /** * Splits a Seq at the specified index. The result of {@code splitAt(n)} is equivalent to * {@code Tuple.of(take(n), drop(n))}. * * @param n An index. * @return A {@link Tuple} containing the first n and the remaining elements. */ Tuple2, ? extends Seq> splitAt(int n); /** * Splits a sequence at the first element which satisfies the {@link Predicate}, e.g. Tuple(init, element+tail). * * @param predicate An predicate * @return A {@link Tuple} containing divided sequences */ Tuple2, ? extends Seq> splitAt(Predicate predicate); /** * Splits a sequence at the first element which satisfies the {@link Predicate}, e.g. Tuple(init+element, tail). * * @param predicate An predicate * @return A {@link Tuple} containing divided sequences */ Tuple2, ? extends Seq> splitAtInclusive(Predicate predicate); /** * Tests whether this list starts with the given sequence. * * @param that the sequence to test * @return true if that is empty or that is prefix of this collection, false otherwise. */ default boolean startsWith(Iterable that) { return startsWith(that, 0); } /** * Tests whether this list contains the given sequence at a given index. *

* Note: If the both the receiver object this and the argument that are infinite sequences this method may not terminate. * * @param that the sequence to test * @param offset the index where the sequence is searched. * @return true if that is empty or that is prefix of this collection starting from the given offset, false otherwise. */ default boolean startsWith(Iterable that, int offset) { Objects.requireNonNull(that, "that is null"); if (offset < 0) { return false; } final Iterator i = this.iterator().drop(offset); final java.util.Iterator j = that.iterator(); while (i.hasNext() && j.hasNext()) { if (!Objects.equals(i.next(), j.next())) { return false; } } return !j.hasNext(); } /** * Returns a Seq that is a subsequence of this. The subsequence begins with the element at the specified * {@code beginIndex} and extends to the end of this Seq. *

* Examples: * *

     * 
     * List.of(1, 2).subSequence(0);     // = (1, 2)
     * List.of(1, 2).subSequence(1);     // = (2)
     * List.of(1, 2).subSequence(2);     // = ()
     * List.of(1, 2).subSequence(10);    // throws IndexOutOfBoundsException
     * List.of(1, 2).subSequence(-10);   // throws IndexOutOfBoundsException
     * 
     * 
* * See also {@link #drop(int)} which is similar but does not throw. * * @param beginIndex the beginning index, inclusive * @return the specified subsequence * @throws IndexOutOfBoundsException if {@code beginIndex} is negative or larger than the length of this * {@code String} object. */ Seq subSequence(int beginIndex); /** * Returns a Seq that is a subsequence of this. The subsequence begins with the element at the specified * {@code beginIndex} and extends to the element at index {@code endIndex - 1}. *

* Examples: * *

     * 
     * List.of(1, 2, 3, 4).subSequence(1, 3); // = (2, 3)
     * List.of(1, 2, 3, 4).subSequence(0, 4); // = (1, 2, 3, 4)
     * List.of(1, 2, 3, 4).subSequence(2, 2); // = ()
     * List.of(1, 2).subSequence(1, 0);       // throws IndexOutOfBoundsException
     * List.of(1, 2).subSequence(-10, 1);     // throws IndexOutOfBoundsException
     * List.of(1, 2).subSequence(0, 10);      // throws IndexOutOfBoundsException
     * 
     * 
* * See also {@link #slice(int, int)} which returns an empty sequence instead of throwing. * * @param beginIndex the beginning index, inclusive * @param endIndex the end index, exclusive * @return the specified subsequence * @throws IndexOutOfBoundsException if {@code beginIndex} or {@code endIndex} is negative or * if {@code endIndex} is greater than {@code length()} * @throws IllegalArgumentException if {@code beginIndex} is greater than {@code endIndex} */ Seq subSequence(int beginIndex, int endIndex); /** * Updates the given element at the specified index. * * @param index an index * @param element an element * @return a new Seq consisting of all previous elements, with a single one (at the given index), changed to the new value. * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq update(int index, T element); /** * Updates the given element at the specified index using the specified function. * * @param index an index * @param updater a function transforming the previous value * @return a new Seq consisting of all previous elements, with a single one (at the given index), changed to the new value. * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq update(int index, Function updater); /** * Searches this sequence for a specific element. The sequence must already be sorted into ascending natural * order. If it is not sorted, the results are undefined. *

* If this sequence is an `IndexedSeq`, a binary search is used. Otherwise, a linear search is used. * * @param element the element to find * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. * @throws ClassCastException if T cannot be cast to {@code Comparable} */ int search(T element); /** * Searches this sequence for a specific element. The sequence must already be sorted into ascending order * according to the specified comparator. If it is not sorted, the results are undefined. *

* If this sequence is an `IndexedSeq`, a binary search is used. Otherwise, a linear search is used. * * @param element the element to find * @param comparator the comparator by which this sequence is ordered * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. */ int search(T element, Comparator comparator); // -- Adjusted return types of Traversable methods @Override Seq distinct(); @Override Seq distinctBy(Comparator comparator); @Override Seq distinctBy(Function keyExtractor); @Override Seq drop(int n); @Override Seq dropUntil(Predicate predicate); @Override Seq dropWhile(Predicate predicate); @Override Seq dropRight(int n); /** * Drops elements until the predicate holds for the current element, starting from the end. * * @param predicate A condition tested subsequently for this elements, starting from the end. * @return a new instance consisting of all elements until and including the last one which does satisfy the given * predicate. * @throws NullPointerException if {@code predicate} is null */ Seq dropRightUntil(Predicate predicate); /** * Drops elements while the predicate holds for the current element, starting from the end. *

* Note: This is essentially the same as {@code dropRightUntil(predicate.negate())}. * It is intended to be used with method references, which cannot be negated directly. * * @param predicate A condition tested subsequently for this elements, starting from the end. * @return a new instance consisting of all elements until and including the last one which does not satisfy the * given predicate. * @throws NullPointerException if {@code predicate} is null */ Seq dropRightWhile(Predicate predicate); @Override Seq filter(Predicate predicate); @Override Seq reject(Predicate predicate); @Override Seq flatMap(Function> mapper); @Override default U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return reverse().foldLeft(zero, (xs, x) -> f.apply(x, xs)); } @Override Map> groupBy(Function classifier); @Override Iterator> grouped(int size); @Override Seq init(); @Override Option> initOption(); @Override Seq map(Function mapper); @Override Seq orElse(Iterable other); @Override Seq orElse(Supplier> supplier); @Override Tuple2, ? extends Seq> partition(Predicate predicate); @Override Seq peek(Consumer action); @Override Seq replace(T currentElement, T newElement); @Override Seq replaceAll(T currentElement, T newElement); @Override Seq retainAll(Iterable elements); @Override Seq scan(T zero, BiFunction operation); @Override Seq scanLeft(U zero, BiFunction operation); @Override Seq scanRight(U zero, BiFunction operation); @Override Iterator> slideBy(Function classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override Tuple2, ? extends Seq> span(Predicate predicate); @Override Seq tail(); @Override Option> tailOption(); @Override Seq take(int n); @Override Seq takeUntil(Predicate predicate); @Override Seq takeWhile(Predicate predicate); @Override Seq takeRight(int n); /** * Takes elements until the predicate holds for the current element, starting from the end. * * @param predicate A condition tested subsequently for this elements, starting from the end. * @return a new instance consisting of all elements after the last one which does satisfy the given predicate. * @throws NullPointerException if {@code predicate} is null */ Seq takeRightUntil(Predicate predicate); /** * Takes elements while the predicate holds for the current element, starting from the end. *

* Note: This is essentially the same as {@code takeRightUntil(predicate.negate())}. * It is intended to be used with method references, which cannot be negated directly. * * @param predicate A condition tested subsequently for this elements, starting from the end. * @return a new instance consisting of all elements after the last one which does not satisfy the given predicate. * @throws NullPointerException if {@code predicate} is null */ Seq takeRightWhile(Predicate predicate); @Override Tuple2, ? extends Seq> unzip(Function> unzipper); @Override Tuple3, ? extends Seq, ? extends Seq> unzip3(Function> unzipper); @Override Seq> zip(Iterable that); @Override Seq zipWith(Iterable that, BiFunction mapper); @Override Seq> zipAll(Iterable that, T thisElem, U thatElem); @Override Seq> zipWithIndex(); @Override Seq zipWithIndex(BiFunction mapper); /** * Turns this sequence from a partial function into a total function that * returns defaultValue for all indexes that are out of bounds. * * @param defaultValue default value to return for out of bound indexes * @return a total function from index to T * @deprecated Will be removed */ @Deprecated default Function1 withDefaultValue(T defaultValue) { return i -> (i >= 0 && i < length()) ? apply(i) : defaultValue; } /** * Turns this sequence from a partial function into a total function that * returns a value computed by defaultFunction for all indexes that are out of bounds. * * @param defaultFunction function to evaluate for all out of bounds indexes. * @return a total function from index to T * @deprecated Will be removed */ @Deprecated default Function1 withDefault(Function defaultFunction) { return i -> (i >= 0 && i < length()) ? apply(i) : defaultFunction.apply(i); } @Override default boolean isSequential() { return true; } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Set.java000066400000000000000000000222261342074374400233120ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Function1; import io.vavr.PartialFunction; import io.vavr.Tuple3; import io.vavr.Tuple2; import io.vavr.control.Option; import java.io.Serializable; import java.util.Comparator; import java.util.function.*; /** * An immutable {@code Set} interface. *

* CAUTION: The Vavr {@code Set} implementations generally support {@code null} elements. However {@code SortedSet} * implementations require an element {@code Comparator}, which may not support {@code null} elements. *

* Examples: * *

{@code Set addNull(Set set) {
 *
 *     // CAUTION: Do not expect a Set to accept null values in general!
 *     return set.add(null);
 *
 * }
 *
 * void test() {
 *
 *     // ok
 *     addNull(HashSet.of(1));
 *
 *     // ok
 *     addNull(TreeSet.of(nullsFirst(naturalOrder()), 1));
 *
 *     // ok
 *     addNull(TreeSet.empty());
 *
 *     // throws NPE!
 *     addNull(TreeSet.of(1));
 *
 * }}
* *

* Basic operations: * *

    *
  • {@link #add(Object)}
  • *
  • {@link #addAll(Iterable)}
  • *
  • {@link #diff(Set)}
  • *
  • {@link #intersect(Set)}
  • *
  • {@link #remove(Object)}
  • *
  • {@link #removeAll(Iterable)}
  • *
  • {@link #union(Set)}
  • *
* * Conversion: * *
    *
  • {@link #toJavaSet()}
  • *
* * @param Component type * @author Daniel Dietrich, Ruslan Sennov */ public interface Set extends Traversable, Function1, Serializable { long serialVersionUID = 1L; /** * Narrows a widened {@code Set} to {@code Set} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param set A {@code Set}. * @param Component type of the {@code Set}. * @return the given {@code set} instance as narrowed type {@code Set}. */ @SuppressWarnings("unchecked") static Set narrow(Set set) { return (Set) set; } /** * Add the given element to this set, if it is not already contained. * * @param element The element to be added. * @return A new set containing all elements of this set and also {@code element}. */ Set add(T element); /** * Adds all of the given elements to this set, if not already contained. * * @param elements The elements to be added. * @return A new set containing all elements of this set and the given {@code elements}, if not already contained. */ Set addAll(Iterable elements); /** * Tests if a given {@code element} is contained in this {@code Set}. *

* This method is equivalent to {@link #contains(Object)}. * * @param element the element to test for membership. * @return {@code true} if the given {@code element} is contained, {@code false} otherwise. * @deprecated Will be removed */ @Override @Deprecated default Boolean apply(T element) { return contains(element); } /** * Calculates the difference between this set and another set. *

* See also {@link #removeAll(Iterable)}. * * @param that Elements to be removed from this set. * @return A new Set containing all elements of this set which are not located in {@code that} set. */ Set diff(Set that); /** * Computes the intersection between this set and another set. *

* See also {@link #retainAll(Iterable)}. * * @param that the set to intersect with. * @return A new Set consisting of all elements that are both in this set and in the given set {@code that}. */ Set intersect(Set that); /** * Removes a specific element from this set, if present. * * @param element The element to be removed from this set. * @return A new set consisting of the elements of this set, without the given {@code element}. */ Set remove(T element); /** * Removes all of the given elements from this set, if present. * * @param elements The elements to be removed from this set. * @return A new set consisting of the elements of this set, without the given {@code elements}. */ Set removeAll(Iterable elements); /** * Converts this Vavr {@code Set} to a {@code java.util.Set} while preserving characteristics * like insertion order ({@code LinkedHashSet}) and sort order ({@code SortedSet}). * * @return a new {@code java.util.Set} instance */ @Override java.util.Set toJavaSet(); /** * Adds all of the elements of {@code that} set to this set, if not already present. *

* See also {@link #addAll(Iterable)}. * * @param that The set to form the union with. * @return A new set that contains all distinct elements of this and {@code that} set. */ Set union(Set that); // -- Adjusted return types of Traversable methods @Override Set collect(PartialFunction partialFunction); @Override boolean contains(T element); @Override Set distinct(); @Override Set distinctBy(Comparator comparator); @Override Set distinctBy(Function keyExtractor); @Override Set drop(int n); @Override Set dropRight(int n); @Override Set dropUntil(Predicate predicate); @Override Set dropWhile(Predicate predicate); @Override Set filter(Predicate predicate); @Override Set reject(Predicate predicate); @Override Set flatMap(Function> mapper); @Override Map> groupBy(Function classifier); @Override Iterator> grouped(int size); @Override Set init(); @Override Option> initOption(); @Override default boolean isDistinct() { return true; } @Override Iterator iterator(); @Override int length(); @Override Set map(Function mapper); @Override Set orElse(Iterable other); @Override Set orElse(Supplier> supplier); @Override Tuple2, ? extends Set> partition(Predicate predicate); @Override Set peek(Consumer action); @Override Set replace(T currentElement, T newElement); @Override Set replaceAll(T currentElement, T newElement); @Override Set retainAll(Iterable elements); @Override Set scan(T zero, BiFunction operation); @Override Set scanLeft(U zero, BiFunction operation); @Override Set scanRight(U zero, BiFunction operation); @Override Iterator> slideBy(Function classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override Tuple2, ? extends Set> span(Predicate predicate); @Override Set tail(); @Override Option> tailOption(); @Override Set take(int n); @Override Set takeRight(int n); @Override Set takeUntil(Predicate predicate); @Override Set takeWhile(Predicate predicate); @Override Tuple2, ? extends Set> unzip(Function> unzipper); @Override Tuple3, ? extends Set, ? extends Set> unzip3(Function> unzipper); @Override Set> zip(Iterable that); @Override Set zipWith(Iterable that, BiFunction mapper); @Override Set> zipAll(Iterable that, T thisElem, U thatElem); @Override Set> zipWithIndex(); @Override Set zipWithIndex(BiFunction mapper); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/SortedMap.java000066400000000000000000000232411342074374400244530ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple2; import io.vavr.control.Option; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.function.*; /** * An immutable {@code SortedMap} interface. * * @param Key type * @param Value type * @author Daniel Dietrich */ public interface SortedMap extends Map, Ordered { long serialVersionUID = 1L; /** * Narrows a widened {@code SortedMap} to {@code SortedMap} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. *

* CAUTION: If {@code K} is narrowed, the underlying {@code Comparator} might fail! * * @param sortedMap A {@code SortedMap}. * @param Key type * @param Value type * @return the given {@code sortedMap} instance as narrowed type {@code SortedMap}. */ @SuppressWarnings("unchecked") static SortedMap narrow(SortedMap sortedMap) { return (SortedMap) sortedMap; } /** * Same as {@link #bimap(Function, Function)}, using a specific comparator for keys of the codomain of the given * {@code keyMapper}. * * @param key's component type of the map result * @param value's component type of the map result * @param keyComparator A comparator for keys of type K2 * @param keyMapper a {@code Function} that maps the keys of type {@code K} to keys of type {@code K2} * @param valueMapper a {@code Function} that the values of type {@code V} to values of type {@code V2} * @return a new {@code SortedMap} * @throws NullPointerException if {@code keyMapper} or {@code valueMapper} is null */ SortedMap bimap(Comparator keyComparator, Function keyMapper, Function valueMapper); /** * Same as {@link #flatMap(BiFunction)} but using a specific comparator for values of the codomain of the given * {@code mapper}. * * @param keyComparator A comparator for keys of type U * @param mapper A function which maps key/value pairs to Iterables map entries * @param New key type * @param New value type * @return A new Map instance containing mapped entries */ SortedMap flatMap(Comparator keyComparator, BiFunction>> mapper); /** * Same as {@link #map(BiFunction)}, using a specific comparator for keys of the codomain of the given * {@code mapper}. * * @param keyComparator A comparator for keys of type U * @param key's component type of the map result * @param value's component type of the map result * @param mapper a {@code Function} that maps entries of type {@code (K, V)} to entries of type {@code (K2, V2)} * @return a new {@code SortedMap} * @throws NullPointerException if {@code mapper} is null */ SortedMap map(Comparator keyComparator, BiFunction> mapper); // -- Adjusted return types of Map methods @Override SortedMap bimap(Function keyMapper, Function valueMapper); @Override Tuple2> computeIfAbsent(K key, Function mappingFunction); @Override Tuple2, ? extends SortedMap> computeIfPresent(K key, BiFunction remappingFunction); @Override SortedMap distinct(); @Override SortedMap distinctBy(Comparator> comparator); @Override SortedMap distinctBy(Function, ? extends U> keyExtractor); @Override SortedMap drop(int n); @Override SortedMap dropRight(int n); @Override SortedMap dropUntil(Predicate> predicate); @Override SortedMap dropWhile(Predicate> predicate); @Override SortedMap filter(Predicate> predicate); @Override SortedMap reject(Predicate> predicate); @Override SortedMap filter(BiPredicate predicate); @Override SortedMap reject(BiPredicate predicate); @Override SortedMap filterKeys(Predicate predicate); @Override SortedMap rejectKeys(Predicate predicate); @Override SortedMap filterValues(Predicate predicate); @Override SortedMap rejectValues(Predicate predicate); @Override @Deprecated SortedMap removeAll(BiPredicate predicate); @Override @Deprecated SortedMap removeKeys(Predicate predicate); @Override @Deprecated SortedMap removeValues(Predicate predicate); @Override SortedMap flatMap(BiFunction>> mapper); @Override Map> groupBy(Function, ? extends C> classifier); @Override Iterator> grouped(int size); @Override SortedMap init(); @Override Option> initOption(); @Override default boolean isOrdered() { return true; } @Override SortedSet keySet(); @Override default Tuple2 last() { return max().getOrElseThrow(() -> new NoSuchElementException("last on empty SortedMap")); } @Override SortedMap map(BiFunction> mapper); @Override SortedMap mapKeys(Function keyMapper); @Override SortedMap mapKeys(Function keyMapper, BiFunction valueMerge); @Override SortedMap mapValues(Function valueMapper); @Override SortedMap merge(Map that); @Override SortedMap merge(Map that, BiFunction collisionResolution); @Override SortedMap orElse(Iterable> other); @Override SortedMap orElse(Supplier>> supplier); @Override Tuple2, ? extends SortedMap> partition(Predicate> predicate); @Override SortedMap peek(Consumer> action); @Override SortedMap put(K key, V value); @Override SortedMap put(Tuple2 entry); @Override SortedMap put(K key, U value, BiFunction merge); @Override SortedMap put(Tuple2 entry, BiFunction merge); @Override SortedMap remove(K key); @Override SortedMap removeAll(Iterable keys); @Override SortedMap replace(K key, V oldValue, V newValue); @Override SortedMap replace(Tuple2 currentElement, Tuple2 newElement); @Override SortedMap replaceValue(K key, V value); @Override SortedMap replaceAll(BiFunction function); @Override SortedMap replaceAll(Tuple2 currentElement, Tuple2 newElement); @Override SortedMap retainAll(Iterable> elements); @Override SortedMap scan(Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation); @Override Iterator> slideBy(Function, ?> classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override Tuple2, ? extends SortedMap> span(Predicate> predicate); @Override SortedMap tail(); @Override Option> tailOption(); @Override SortedMap take(int n); @Override SortedMap takeRight(int n); @Override SortedMap takeUntil(Predicate> predicate); @Override SortedMap takeWhile(Predicate> predicate); @Override java.util.SortedMap toJavaMap(); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/SortedMultimap.java000066400000000000000000000144271342074374400255340ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.control.Option; import io.vavr.Tuple2; import java.util.Collection; import java.util.Comparator; import java.util.function.*; /** * An immutable {@code SortedMultimap} interface. * * @param Key type * @param Value type * @author Ruslan Sennov */ public interface SortedMultimap extends Multimap, Ordered { long serialVersionUID = 1L; /** * Narrows a widened {@code SortedMultimap} to {@code SortedMultimap} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param map A {@code SortedMultimap}. * @param Key type * @param Value type * @return the given {@code multimap} instance as narrowed type {@code SortedMultimap}. */ @SuppressWarnings("unchecked") static SortedMultimap narrow(SortedMultimap map) { return (SortedMultimap) map; } @Override SortedMultimap filter(BiPredicate predicate); @Override SortedMultimap reject(BiPredicate predicate); @Override SortedMultimap filterKeys(Predicate predicate); @Override SortedMultimap rejectKeys(Predicate predicate); @Override SortedMultimap filterValues(Predicate predicate); @Override SortedMultimap rejectValues(Predicate predicate); @Override SortedSet keySet(); @Override SortedMultimap merge(Multimap that); @Override SortedMultimap merge(Multimap that, BiFunction, Traversable, Traversable> collisionResolution); @Override SortedMultimap put(K key, V value); @Override SortedMultimap put(Tuple2 entry); @Override SortedMultimap remove(K key); @Override SortedMultimap remove(K key, V value); @Override @Deprecated SortedMultimap removeAll(BiPredicate predicate); @Override SortedMultimap removeAll(Iterable keys); @Override @Deprecated SortedMultimap removeKeys(Predicate predicate); @Override @Deprecated SortedMultimap removeValues(Predicate predicate); @Override java.util.SortedMap> toJavaMap(); @Override SortedMultimap distinct(); @Override SortedMultimap distinctBy(Comparator> comparator); @Override SortedMultimap distinctBy(Function, ? extends U> keyExtractor); @Override SortedMultimap drop(int n); @Override SortedMultimap dropRight(int n); @Override SortedMultimap dropUntil(Predicate> predicate); @Override SortedMultimap dropWhile(Predicate> predicate); @Override SortedMultimap filter(Predicate> predicate); @Override SortedMultimap reject(Predicate> predicate); @Override Map> groupBy(Function, ? extends C> classifier); @Override Iterator> grouped(int size); @Override SortedMultimap init(); @Override Option> initOption(); @Override SortedMultimap orElse(Iterable> other); @Override SortedMultimap orElse(Supplier>> supplier); @Override Tuple2, ? extends SortedMultimap> partition(Predicate> predicate); @Override SortedMultimap peek(Consumer> action); @Override SortedMultimap replace(Tuple2 currentElement, Tuple2 newElement); @Override SortedMultimap replaceAll(Tuple2 currentElement, Tuple2 newElement); @Override SortedMultimap replaceValue(K key, V value); @Override SortedMultimap replace(K key, V oldValue, V newValue); @Override SortedMultimap replaceAll(BiFunction function); @Override SortedMultimap retainAll(Iterable> elements); @Override SortedMultimap scan(Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation); @Override Iterator> slideBy(Function, ?> classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override Tuple2, ? extends SortedMultimap> span(Predicate> predicate); @Override SortedMultimap tail(); @Override Option> tailOption(); @Override SortedMultimap take(int n); @Override SortedMultimap takeRight(int n); @Override SortedMultimap takeUntil(Predicate> predicate); @Override SortedMultimap takeWhile(Predicate> predicate); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/SortedSet.java000066400000000000000000000165411342074374400244760ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple3; import io.vavr.Tuple2; import io.vavr.control.Option; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.function.*; /** * An immutable {@code SortedSet} interface. * *

* Specific SortedSet operations: * *

    *
  • {@link #comparator()}
  • *
  • {@link #flatMap(Comparator, Function)}
  • *
  • {@link #map(Comparator, Function)}
  • *
* * @param Component type * @author Daniel Dietrich */ public interface SortedSet extends Set, Ordered { long serialVersionUID = 1L; /** * Narrows a widened {@code SortedSet} to {@code SortedSet} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. *

* CAUTION: The underlying {@code Comparator} might fail! * * @param sortedSet A {@code SortedSet}. * @param Component type of the {@code SortedSet}. * @return the given {@code sortedSet} instance as narrowed type {@code SortedSet}. */ @SuppressWarnings("unchecked") static SortedSet narrow(SortedSet sortedSet) { return (SortedSet) sortedSet; } /** * Same as {@link #flatMap(Function)} but using a specific comparator for values of the codomain of the given * {@code mapper}. * * @param comparator A comparator for values of type U * @param mapper A function which maps values of type T to Iterables of values of type U * @param Type of flat-mapped values * @return A new Set instance containing mapped values */ SortedSet flatMap(Comparator comparator, Function> mapper); /** * Same as {@link #map(Function)} but using a specific comparator for values of the codomain of the given * {@code mapper}. * * @param comparator A comparator for values of type U * @param mapper A function which maps values of type T to values of type U * @param Type of mapped values * @return A new Set instance containing mapped values */ SortedSet map(Comparator comparator, Function mapper); // -- Adjusted return types of Set methods @Override SortedSet add(T element); @Override SortedSet addAll(Iterable elements); @Override SortedSet collect(PartialFunction partialFunction); @Override SortedSet diff(Set elements); @Override SortedSet distinct(); @Override SortedSet distinctBy(Comparator comparator); @Override SortedSet distinctBy(Function keyExtractor); @Override SortedSet drop(int n); @Override SortedSet dropRight(int n); @Override SortedSet dropUntil(Predicate predicate); @Override SortedSet dropWhile(Predicate predicate); @Override SortedSet filter(Predicate predicate); @Override SortedSet reject(Predicate predicate); @Override SortedSet flatMap(Function> mapper); @Override Map> groupBy(Function classifier); @Override Iterator> grouped(int size); @Override SortedSet init(); @Override Option> initOption(); @Override SortedSet intersect(Set elements); @Override default boolean isOrdered() { return true; } @Override SortedSet map(Function mapper); @Override SortedSet orElse(Iterable other); @Override SortedSet orElse(Supplier> supplier); @Override Tuple2, ? extends SortedSet> partition(Predicate predicate); @Override SortedSet peek(Consumer action); @Override SortedSet remove(T element); @Override SortedSet removeAll(Iterable elements); @Override SortedSet replace(T currentElement, T newElement); @Override SortedSet replaceAll(T currentElement, T newElement); @Override SortedSet retainAll(Iterable elements); @Override SortedSet scan(T zero, BiFunction operation); // DEV-NOTE: The return type is either Set or SortedSet, depending whether U is Comparable @Override Set scanLeft(U zero, BiFunction operation); // DEV-NOTE: The return type is either Set or SortedSet, depending whether U is Comparable @Override Set scanRight(U zero, BiFunction operation); @Override Iterator> slideBy(Function classifier); @Override Iterator> sliding(int size); @Override Iterator> sliding(int size, int step); @Override Tuple2, ? extends SortedSet> span(Predicate predicate); @Override SortedSet tail(); @Override Option> tailOption(); @Override SortedSet take(int n); @Override SortedSet takeRight(int n); @Override SortedSet takeUntil(Predicate predicate); @Override SortedSet takeWhile(Predicate predicate); @Override java.util.SortedSet toJavaSet(); @Override SortedSet union(Set elements); @Override Tuple2, ? extends SortedSet> unzip(Function> unzipper); @Override Tuple3, ? extends SortedSet, ? extends SortedSet> unzip3(Function> unzipper); @Override SortedSet> zip(Iterable that); @Override SortedSet zipWith(Iterable that, BiFunction mapper); @Override SortedSet> zipAll(Iterable that, T thisElem, U thatElem); @Override SortedSet> zipWithIndex(); @Override SortedSet zipWithIndex(BiFunction mapper); } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Stream.java000066400000000000000000002173471342074374400240240ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.collection.Stream.Cons; import io.vavr.collection.Stream.Empty; import io.vavr.collection.StreamModule.*; import io.vavr.control.Option; import java.io.*; import java.util.*; import java.util.function.*; import java.util.stream.Collector; import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE; import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE; /** * An immutable {@code Stream} is lazy sequence of elements which may be infinitely long. * Its immutability makes it suitable for concurrent programming. *

* A {@code Stream} is composed of a {@code head} element and a lazy evaluated {@code tail} {@code Stream}. *

* There are two implementations of the {@code Stream} interface: * *

    *
  • {@link Empty}, which represents the empty {@code Stream}.
  • *
  • {@link Cons}, which represents a {@code Stream} containing one or more elements.
  • *
* * Methods to obtain a {@code Stream}: * *
 * 
 * // factory methods
 * Stream.empty()                  // = Stream.of() = Nil.instance()
 * Stream.of(x)                    // = new Cons<>(x, Nil.instance())
 * Stream.of(Object...)            // e.g. Stream.of(1, 2, 3)
 * Stream.ofAll(Iterable)          // e.g. Stream.ofAll(List.of(1, 2, 3)) = 1, 2, 3
 * Stream.ofAll(<primitive array>) // e.g. List.ofAll(1, 2, 3) = 1, 2, 3
 *
 * // int sequences
 * Stream.from(0)                  // = 0, 1, 2, 3, ...
 * Stream.range(0, 3)              // = 0, 1, 2
 * Stream.rangeClosed(0, 3)        // = 0, 1, 2, 3
 *
 * // generators
 * Stream.cons(Object, Supplier)   // e.g. Stream.cons(current, () -> next(current));
 * Stream.continually(Supplier)    // e.g. Stream.continually(Math::random);
 * Stream.iterate(Object, Function)// e.g. Stream.iterate(1, i -> i * 2);
 * 
 * 
* * Factory method applications: * *
 * 
 * Stream<Integer>       s1 = Stream.of(1);
 * Stream<Integer>       s2 = Stream.of(1, 2, 3);
 *                       // = Stream.of(new Integer[] {1, 2, 3});
 *
 * Stream<int[]>         s3 = Stream.ofAll(1, 2, 3);
 * Stream<List<Integer>> s4 = Stream.ofAll(List.of(1, 2, 3));
 *
 * Stream<Integer>       s5 = Stream.ofAll(1, 2, 3);
 * Stream<Integer>       s6 = Stream.ofAll(List.of(1, 2, 3));
 *
 * // cuckoo's egg
 * Stream<Integer[]>     s7 = Stream.<Integer[]> of(new Integer[] {1, 2, 3});
 * 
 * 
* * Example: Generating prime numbers * *
 * 
 * // = Stream(2L, 3L, 5L, 7L, ...)
 * Stream.iterate(2L, PrimeNumbers::nextPrimeFrom)
 *
 * // helpers
 *
 * static long nextPrimeFrom(long num) {
 *     return Stream.from(num + 1).find(PrimeNumbers::isPrime).get();
 * }
 *
 * static boolean isPrime(long num) {
 *     return !Stream.rangeClosed(2L, (long) Math.sqrt(num)).exists(d -> num % d == 0);
 * }
 * 
 * 
* * See Okasaki, Chris: Purely Functional Data Structures (p. 34 ff.). Cambridge, 2003. * * @param component type of this Stream * @author Daniel Dietrich, Jörgen Andersson, Ruslan Sennov */ public interface Stream extends LinearSeq { long serialVersionUID = 1L; /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link Stream}. * * @param Component type of the Stream. * @return A io.vavr.collection.Stream Collector. */ static Collector, Stream> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, Stream> finisher = Stream::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Lazily creates a Stream in O(1) which traverses along the concatenation of the given iterables. * * @param iterables The iterables * @param Component type. * @return A new {@code Stream} */ @SuppressWarnings("varargs") @SafeVarargs static Stream concat(Iterable... iterables) { return Iterator.concat(iterables).toStream(); } /** * Lazily creates a Stream in O(1) which traverses along the concatenation of the given iterables. * * @param iterables The iterable of iterables * @param Component type. * @return A new {@code Stream} */ static Stream concat(Iterable> iterables) { return Iterator. concat(iterables).toStream(); } /** * Returns an infinitely long Stream of {@code int} values starting from {@code from}. *

* The {@code Stream} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}. * * @param value a start int value * @return a new Stream of int values starting from {@code from} */ static Stream from(int value) { return Stream.ofAll(Iterator.from(value)); } /** * Returns an infinite long Stream of {@code int} values starting from {@code value} and spaced by {@code step}. *

* The {@code Stream} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}. * * @param value a start int value * @param step the step by which to advance on each next value * @return a new {@code Stream} of int values starting from {@code from} */ static Stream from(int value, int step) { return Stream.ofAll(Iterator.from(value, step)); } /** * Returns an infinitely long Stream of {@code long} values starting from {@code from}. *

* The {@code Stream} extends to {@code Integer.MIN_VALUE} when passing {@code Long.MAX_VALUE}. * * @param value a start long value * @return a new Stream of long values starting from {@code from} */ static Stream from(long value) { return Stream.ofAll(Iterator.from(value)); } /** * Returns an infinite long Stream of {@code long} values starting from {@code value} and spaced by {@code step}. *

* The {@code Stream} extends to {@code Long.MIN_VALUE} when passing {@code Long.MAX_VALUE}. * * @param value a start long value * @param step the step by which to advance on each next value * @return a new {@code Stream} of long values starting from {@code from} */ static Stream from(long value, long step) { return Stream.ofAll(Iterator.from(value, step)); } /** * Generates an (theoretically) infinitely long Stream using a value Supplier. * * @param supplier A Supplier of Stream values * @param value type * @return A new Stream */ static Stream continually(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return Stream.ofAll(Iterator.continually(supplier)); } /** * Generates a (theoretically) infinitely long Stream using a function to calculate the next value * based on the previous. * * @param seed The first value in the Stream * @param f A function to calculate the next value based on the previous * @param value type * @return A new Stream */ static Stream iterate(T seed, Function f) { Objects.requireNonNull(f, "f is null"); return Stream.ofAll(Iterator.iterate(seed, f)); } /** * Generates a (theoretically) infinitely long Stream using a repeatedly invoked supplier * that provides a {@code Some} for each next value and a {@code None} for the end. * The {@code Supplier} will be invoked only that many times until it returns {@code None}, * and repeated iteration over the stream will produce the same values in the same order, * without any further invocations to the {@code Supplier}. * * @param supplier A Supplier of iterator values * @param value type * @return A new Stream */ static Stream iterate(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return Stream.ofAll(Iterator.iterate(supplier)); } /** * Constructs a Stream of a head element and a tail supplier. * * @param head The head element of the Stream * @param tailSupplier A supplier of the tail values. To end the stream, return {@link Stream#empty}. * @param value type * @return A new Stream */ @SuppressWarnings("unchecked") static Stream cons(T head, Supplier> tailSupplier) { Objects.requireNonNull(tailSupplier, "tailSupplier is null"); return new ConsImpl<>(head, (Supplier>) tailSupplier); } /** * Returns the single instance of Nil. Convenience method for {@code Nil.instance()}. *

* Note: this method intentionally returns type {@code Stream} and not {@code Nil}. This comes handy when folding. * If you explicitly need type {@code Nil} use {@linkplain Empty#instance()}. * * @param Component type of Nil, determined by type inference in the particular context. * @return The empty list. */ static Stream empty() { return Empty.instance(); } /** * Narrows a widened {@code Stream} to {@code Stream} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param stream A {@code Stream}. * @param Component type of the {@code Stream}. * @return the given {@code stream} instance as narrowed type {@code Stream}. */ @SuppressWarnings("unchecked") static Stream narrow(Stream stream) { return (Stream) stream; } /** * Returns a singleton {@code Stream}, i.e. a {@code Stream} of one element. * * @param element An element. * @param The component type * @return A new Stream instance containing the given element */ static Stream of(T element) { return cons(element, Empty::instance); } /** * Creates a Stream of the given elements. * *

  Stream.of(1, 2, 3, 4)
     * = Nil.instance().prepend(4).prepend(3).prepend(2).prepend(1)
     * = new Cons(1, new Cons(2, new Cons(3, new Cons(4, Nil.instance()))))
* * @param Component type of the Stream. * @param elements Zero or more elements. * @return A list containing the given elements in the same order. */ @SafeVarargs static Stream of(T... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(new Iterator() { int i = 0; @Override public boolean hasNext() { return i < elements.length; } @Override public T next() { return elements[i++]; } }); } /** * Returns a Stream containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the Stream * @param n The number of elements in the Stream * @param f The Function computing element values * @return A Stream consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ static Stream tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return Stream.ofAll(io.vavr.collection.Collections.tabulate(n, f)); } /** * Returns a Stream containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the Stream * @param n The number of elements in the Stream * @param s The Supplier computing element values * @return A Stream of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ static Stream fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return Stream.ofAll(io.vavr.collection.Collections.fill(n, s)); } /** * Returns a Stream containing {@code n} times the given {@code element} * * @param Component type of the Stream * @param n The number of elements in the Stream * @param element The element * @return A Stream of size {@code n}, where each element is the given {@code element}. */ static Stream fill(int n, T element) { return Stream.ofAll(io.vavr.collection.Collections.fillObject(n, element)); } /** * Creates a Stream of the given elements. * * @param Component type of the Stream. * @param elements An Iterable of elements. * @return A Stream containing the given elements in the same order. */ @SuppressWarnings("unchecked") static Stream ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof Stream) { return (Stream) elements; } else { return StreamFactory.create(elements.iterator()); } } /** * Creates a Stream that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return A Stream containing the given elements in the same order. */ static Stream ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return StreamFactory.create(javaStream.iterator()); } /** * Creates a Stream from boolean values. * * @param elements boolean values * @return A new Stream of Boolean values * @throws NullPointerException if elements is null */ static Stream ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } /** * Creates a Stream from byte values. * * @param elements byte values * @return A new Stream of Byte values * @throws NullPointerException if elements is null */ static Stream ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } /** * Creates a Stream from char values. * * @param elements char values * @return A new Stream of Character values * @throws NullPointerException if elements is null */ static Stream ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } /** * Creates a Stream values double values. * * @param elements double values * @return A new Stream of Double values * @throws NullPointerException if elements is null */ static Stream ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } /** * Creates a Stream from float values. * * @param elements float values * @return A new Stream of Float values * @throws NullPointerException if elements is null */ static Stream ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } /** * Creates a Stream from int values. * * @param elements int values * @return A new Stream of Integer values * @throws NullPointerException if elements is null */ static Stream ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } /** * Creates a Stream from long values. * * @param elements long values * @return A new Stream of Long values * @throws NullPointerException if elements is null */ static Stream ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } /** * Creates a Stream from short values. * * @param elements short values * @return A new Stream of Short values * @throws NullPointerException if elements is null */ static Stream ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return Stream.ofAll(Iterator.ofAll(elements)); } static Stream range(char from, char toExclusive) { return Stream.ofAll(Iterator.range(from, toExclusive)); } static Stream rangeBy(char from, char toExclusive, int step) { return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step)); } @GwtIncompatible static Stream rangeBy(double from, double toExclusive, double step) { return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a Stream of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Stream.range(0, 0)  // = Stream()
     * Stream.range(2, 0)  // = Stream()
     * Stream.range(-2, 2) // = Stream(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or {@code Nil} if {@code from >= toExclusive} */ static Stream range(int from, int toExclusive) { return Stream.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a Stream of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Stream.rangeBy(1, 3, 1)  // = Stream(1, 2)
     * Stream.rangeBy(1, 4, 2)  // = Stream(1, 3)
     * Stream.rangeBy(4, 1, -2) // = Stream(4, 2)
     * Stream.rangeBy(4, 1, 2)  // = Stream()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or {@code Nil} if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static Stream rangeBy(int from, int toExclusive, int step) { return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a Stream of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Stream.range(0L, 0L)  // = Stream()
     * Stream.range(2L, 0L)  // = Stream()
     * Stream.range(-2L, 2L) // = Stream(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or {@code Nil} if {@code from >= toExclusive} */ static Stream range(long from, long toExclusive) { return Stream.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a Stream of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Stream.rangeBy(1L, 3L, 1L)  // = Stream(1L, 2L)
     * Stream.rangeBy(1L, 4L, 2L)  // = Stream(1L, 3L)
     * Stream.rangeBy(4L, 1L, -2L) // = Stream(4L, 2L)
     * Stream.rangeBy(4L, 1L, 2L)  // = Stream()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or {@code Nil} if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static Stream rangeBy(long from, long toExclusive, long step) { return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step)); } static Stream rangeClosed(char from, char toInclusive) { return Stream.ofAll(Iterator.rangeClosed(from, toInclusive)); } static Stream rangeClosedBy(char from, char toInclusive, int step) { return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @GwtIncompatible static Stream rangeClosedBy(double from, double toInclusive, double step) { return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a Stream of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Stream.rangeClosed(0, 0)  // = Stream(0)
     * Stream.rangeClosed(2, 0)  // = Stream()
     * Stream.rangeClosed(-2, 2) // = Stream(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or {@code Nil} if {@code from > toInclusive} */ static Stream rangeClosed(int from, int toInclusive) { return Stream.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a Stream of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Stream.rangeClosedBy(1, 3, 1)  // = Stream(1, 2, 3)
     * Stream.rangeClosedBy(1, 4, 2)  // = Stream(1, 3)
     * Stream.rangeClosedBy(4, 1, -2) // = Stream(4, 2)
     * Stream.rangeClosedBy(4, 1, 2)  // = Stream()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or {@code Nil} if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static Stream rangeClosedBy(int from, int toInclusive, int step) { return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a Stream of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Stream.rangeClosed(0L, 0L)  // = Stream(0L)
     * Stream.rangeClosed(2L, 0L)  // = Stream()
     * Stream.rangeClosed(-2L, 2L) // = Stream(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or {@code Nil} if {@code from > toInclusive} */ static Stream rangeClosed(long from, long toInclusive) { return Stream.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a Stream of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Stream.rangeClosedBy(1L, 3L, 1L)  // = Stream(1L, 2L, 3L)
     * Stream.rangeClosedBy(1L, 4L, 2L)  // = Stream(1L, 3L)
     * Stream.rangeClosedBy(4L, 1L, -2L) // = Stream(4L, 2L)
     * Stream.rangeClosedBy(4L, 1L, 2L)  // = Stream()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or {@code Nil} if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ static Stream rangeClosedBy(long from, long toInclusive, long step) { return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Transposes the rows and columns of a {@link Stream} matrix. * * @param matrix element type * @param matrix to be transposed. * @return a transposed {@link Stream} matrix. * @throws IllegalArgumentException if the row lengths of {@code matrix} differ. *

* ex: {@code * Stream.transpose(Stream(Stream(1,2,3), Stream(4,5,6))) → Stream(Stream(1,4), Stream(2,5), Stream(3,6)) * } */ static Stream> transpose(Stream> matrix) { return io.vavr.collection.Collections.transpose(matrix, Stream::ofAll, Stream::of); } /** * Creates a Stream from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Stream, otherwise {@code Some} {@code Tuple} * of the element for the next call and the value to add to the * resulting Stream. *

* Example: *

     * 
     * Stream.unfoldRight(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x, x-1)));
     * // Stream(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Stream with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static Stream unfoldRight(T seed, Function>> f) { return Iterator.unfoldRight(seed, f).toStream(); } /** * Creates a Stream from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Stream, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting Stream and * the element for the next call. *

* Example: *

     * 
     * Stream.unfoldLeft(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // Stream(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Stream with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static Stream unfoldLeft(T seed, Function>> f) { return Iterator.unfoldLeft(seed, f).toStream(); } /** * Creates a Stream from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Stream, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting Stream and * the element for the next call. *

* Example: *

     * 
     * Stream.unfold(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // Stream(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds and unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Stream with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ static Stream unfold(T seed, Function>> f) { return Iterator.unfold(seed, f).toStream(); } /** * Repeats an element infinitely often. * * @param t An element * @param Element type * @return A new Stream containing infinite {@code t}'s. */ static Stream continually(T t) { return Stream.ofAll(Iterator.continually(t)); } @Override default Stream append(T element) { return isEmpty() ? Stream.of(element) : new AppendElements<>(head(), io.vavr.collection.Queue.of(element), this::tail); } @Override default Stream appendAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (Collections.isEmpty(elements)) { return this; } else if (isEmpty()) { return Stream.ofAll(elements); } else { return Stream.ofAll(Iterator.concat(this, elements)); } } /** * Appends itself to the end of stream with {@code mapper} function. *

* Example: *

* Well known Scala code for Fibonacci infinite sequence *

     * 
     * val fibs:Stream[Int] = 0 #:: 1 #:: (fibs zip fibs.tail).map{ t => t._1 + t._2 }
     * 
     * 
* can be transformed to *
     * 
     * Stream.of(0, 1).appendSelf(self -> self.zip(self.tail()).map(t -> t._1 + t._2));
     * 
     * 
* * @param mapper an mapper * @return a new Stream */ default Stream appendSelf(Function, ? extends Stream> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? this : new AppendSelf<>((Cons) this, mapper).stream(); } @GwtIncompatible @Override default java.util.List asJava() { return JavaConverters.asJava(this, IMMUTABLE); } @GwtIncompatible @Override default Stream asJava(Consumer> action) { return Collections.asJava(this, action, IMMUTABLE); } @GwtIncompatible @Override default java.util.List asJavaMutable() { return JavaConverters.asJava(this, MUTABLE); } @GwtIncompatible @Override default Stream asJavaMutable(Consumer> action) { return Collections.asJava(this, action, MUTABLE); } @Override default Stream collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } @Override default Stream> combinations() { return Stream.rangeClosed(0, length()).map(this::combinations).flatMap(Function.identity()); } @Override default Stream> combinations(int k) { return Combinations.apply(this, Math.max(k, 0)); } @Override default Iterator> crossProduct(int power) { return io.vavr.collection.Collections.crossProduct(Stream.empty(), this, power); } /** * Repeat the elements of this Stream infinitely. *

* Example: *

     * 
     * // = 1, 2, 3, 1, 2, 3, 1, 2, 3, ...
     * Stream.of(1, 2, 3).cycle();
     * 
     * 
* * @return A new Stream containing this elements cycled. */ default Stream cycle() { return isEmpty() ? this : appendSelf(Function.identity()); } /** * Repeat the elements of this Stream {@code count} times. *

* Example: *

     * 
     * // = empty
     * Stream.of(1, 2, 3).cycle(0);
     *
     * // = 1, 2, 3
     * Stream.of(1, 2, 3).cycle(1);
     *
     * // = 1, 2, 3, 1, 2, 3, 1, 2, 3
     * Stream.of(1, 2, 3).cycle(3);
     * 
     * 
* * @param count the number of cycles to be performed * @return A new Stream containing this elements cycled {@code count} times. */ default Stream cycle(int count) { if (count <= 0 || isEmpty()) { return empty(); } else { final Stream self = this; return Stream.ofAll(new Iterator() { Stream stream = self; int i = count - 1; @Override public boolean hasNext() { return !stream.isEmpty() || i > 0; } @Override public T next() { if (stream.isEmpty()) { i--; stream = self; } final T result = stream.head(); stream = stream.tail(); return result; } }); } } @Override default Stream distinct() { return distinctBy(Function.identity()); } @Override default Stream distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final java.util.Set seen = new java.util.TreeSet<>(comparator); return filter(seen::add); } @Override default Stream distinctBy(Function keyExtractor) { final java.util.Set seen = new java.util.HashSet<>(); return filter(t -> seen.add(keyExtractor.apply(t))); } @Override default Stream drop(int n) { Stream stream = this; while (n-- > 0 && !stream.isEmpty()) { stream = stream.tail(); } return stream; } @Override default Stream dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override default Stream dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); Stream stream = this; while (!stream.isEmpty() && predicate.test(stream.head())) { stream = stream.tail(); } return stream; } @Override default Stream dropRight(int n) { if (n <= 0) { return this; } else { return DropRight.apply(take(n).toList(), List.empty(), drop(n)); } } @Override default Stream dropRightUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reverse().dropUntil(predicate).reverse(); } @Override default Stream dropRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropRightUntil(predicate.negate()); } @Override default Stream filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return this; } else { Stream stream = this; while (!stream.isEmpty() && !predicate.test(stream.head())) { stream = stream.tail(); } final Stream finalStream = stream; return stream.isEmpty() ? Stream.empty() : cons(stream.head(), () -> finalStream.tail().filter(predicate)); } } @Override default Stream reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Collections.reject(this, predicate); } @Override default Stream flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? Empty.instance() : Stream.ofAll(new FlatMapIterator<>(this.iterator(), mapper)); } @Override default T get(int index) { if (isEmpty()) { throw new IndexOutOfBoundsException("get(" + index + ") on Nil"); } if (index < 0) { throw new IndexOutOfBoundsException("get(" + index + ")"); } Stream stream = this; for (int i = index - 1; i >= 0; i--) { stream = stream.tail(); if (stream.isEmpty()) { throw new IndexOutOfBoundsException("get(" + index + ") on Stream of size " + (index - i)); } } return stream.head(); } @Override default Map> groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(this, classifier, Stream::ofAll); } @Override default Iterator> grouped(int size) { return sliding(size, size); } @Override default boolean hasDefiniteSize() { return false; } @Override default int indexOf(T element, int from) { int index = 0; for (Stream stream = this; !stream.isEmpty(); stream = stream.tail(), index++) { if (index >= from && Objects.equals(stream.head(), element)) { return index; } } return -1; } @Override default Stream init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty stream"); } else { final Stream tail = tail(); if (tail.isEmpty()) { return Empty.instance(); } else { return cons(head(), tail::init); } } } @Override default Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override default Stream insert(int index, T element) { if (index < 0) { throw new IndexOutOfBoundsException("insert(" + index + ", e)"); } else if (index == 0) { return cons(element, () -> this); } else if (isEmpty()) { throw new IndexOutOfBoundsException("insert(" + index + ", e) on Nil"); } else { return cons(head(), () -> tail().insert(index - 1, element)); } } @Override default Stream insertAll(int index, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (index < 0) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements)"); } else if (index == 0) { return isEmpty() ? Stream.ofAll(elements) : Stream. ofAll(elements).appendAll(this); } else if (isEmpty()) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements) on Nil"); } else { return cons(head(), () -> tail().insertAll(index - 1, elements)); } } @Override default Stream intersperse(T element) { if (isEmpty()) { return this; } else { return cons(head(), () -> { final Stream tail = tail(); return tail.isEmpty() ? tail : cons(element, () -> tail.intersperse(element)); }); } } /** * A {@code Stream} is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } /** * A {@code Stream} is computed lazily. * * @return true */ @Override default boolean isLazy() { return true; } @Override default boolean isTraversableAgain() { return true; } @Override default T last() { return Collections.last(this); } @Override default int lastIndexOf(T element, int end) { int result = -1, index = 0; for (Stream stream = this; index <= end && !stream.isEmpty(); stream = stream.tail(), index++) { if (Objects.equals(stream.head(), element)) { result = index; } } return result; } @Override default int length() { return foldLeft(0, (n, ignored) -> n + 1); } @Override default Stream map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return Empty.instance(); } else { return cons(mapper.apply(head()), () -> tail().map(mapper)); } } @Override default Stream padTo(int length, T element) { if (length <= 0) { return this; } else if (isEmpty()) { return Stream.continually(element).take(length); } else { return cons(head(), () -> tail().padTo(length - 1, element)); } } @Override default Stream leftPadTo(int length, T element) { final int actualLength = length(); if (length <= actualLength) { return this; } else { return Stream.continually(element).take(length - actualLength).appendAll(this); } } @Override default Stream orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override default Stream orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override default Stream patch(int from, Iterable that, int replaced) { from = from < 0 ? 0 : from; replaced = replaced < 0 ? 0 : replaced; Stream result = take(from).appendAll(that); from += replaced; result = result.appendAll(drop(from)); return result; } @Override default Tuple2, Stream> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Tuple.of(filter(predicate), filter(predicate.negate())); } @Override default Stream peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isEmpty()) { return this; } else { final T head = head(); action.accept(head); return cons(head, () -> tail().peek(action)); } } @Override default Stream> permutations() { if (isEmpty()) { return Empty.instance(); } else { final Stream tail = tail(); if (tail.isEmpty()) { return Stream.of(this); } else { final Stream> zero = Empty.instance(); return distinct().foldLeft(zero, (xs, x) -> { final Function, Stream> prepend = l -> l.prepend(x); return xs.appendAll(remove(x).permutations().map(prepend)); }); } } } @Override default Stream prepend(T element) { return cons(element, () -> this); } @Override default Stream prependAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { if (elements instanceof Stream) { @SuppressWarnings("unchecked") final Stream stream = (Stream) elements; return stream; } else { return Stream.ofAll(elements); } } else { return Stream. ofAll(elements).appendAll(this); } } @Override default Stream remove(T element) { if (isEmpty()) { return this; } else { final T head = head(); return Objects.equals(head, element) ? tail() : cons(head, () -> tail().remove(element)); } } @Override default Stream removeFirst(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return this; } else { final T head = head(); return predicate.test(head) ? tail() : cons(head, () -> tail().removeFirst(predicate)); } } @Override default Stream removeLast(Predicate predicate) { return isEmpty() ? this : reverse().removeFirst(predicate).reverse(); } @Override default Stream removeAt(int index) { if (index < 0) { throw new IndexOutOfBoundsException("removeAt(" + index + ")"); } else if (index == 0) { return tail(); } else if (isEmpty()) { throw new IndexOutOfBoundsException("removeAt() on Nil"); } else { return cons(head(), () -> tail().removeAt(index - 1)); } } @Override default Stream removeAll(T element) { return io.vavr.collection.Collections.removeAll(this, element); } @Override default Stream removeAll(Iterable elements) { return io.vavr.collection.Collections.removeAll(this, elements); } @Override @Deprecated default Stream removeAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override default Stream replace(T currentElement, T newElement) { if (isEmpty()) { return this; } else { final T head = head(); if (Objects.equals(head, currentElement)) { return cons(newElement, this::tail); } else { return cons(head, () -> tail().replace(currentElement, newElement)); } } } @Override default Stream replaceAll(T currentElement, T newElement) { if (isEmpty()) { return this; } else { final T head = head(); final T newHead = Objects.equals(head, currentElement) ? newElement : head; return cons(newHead, () -> tail().replaceAll(currentElement, newElement)); } } @Override default Stream retainAll(Iterable elements) { return io.vavr.collection.Collections.retainAll(this, elements); } @Override default Stream reverse() { return isEmpty() ? this : foldLeft(Stream.empty(), Stream::prepend); } @Override default Stream rotateLeft(int n) { return Collections.rotateLeft(this, n); } @Override default Stream rotateRight(int n) { return Collections.rotateRight(this, n); } @Override default Stream scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override default Stream scanLeft(U zero, BiFunction operation) { // lazily streams the elements of an iterator return io.vavr.collection.Collections.scanLeft(this, zero, operation, Iterator::toStream); } // not lazy! @Override default Stream scanRight(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, Iterator::toStream); } @Override default Stream shuffle() { return io.vavr.collection.Collections.shuffle(this, Stream::ofAll); } @Override default Stream slice(int beginIndex, int endIndex) { if (beginIndex >= endIndex || isEmpty()) { return empty(); } else { final int lowerBound = Math.max(beginIndex, 0); if (lowerBound == 0) { return cons(head(), () -> tail().slice(0, endIndex - 1)); } else { return tail().slice(lowerBound - 1, endIndex - 1); } } } @Override default Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(Stream::ofAll); } @Override default Iterator> sliding(int size) { return sliding(size, 1); } @Override default Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(Stream::ofAll); } @Override default Stream sorted() { return isEmpty() ? this : toJavaStream().sorted().collect(Stream.collector()); } @Override default Stream sorted(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return isEmpty() ? this : toJavaStream().sorted(comparator).collect(Stream.collector()); } @Override default > Stream sortBy(Function mapper) { return sortBy(U::compareTo, mapper); } @Override default Stream sortBy(Comparator comparator, Function mapper) { return Collections.sortBy(this, comparator, mapper, collector()); } @Override default Tuple2, Stream> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Tuple.of(takeWhile(predicate), dropWhile(predicate)); } @Override default Tuple2, Stream> splitAt(int n) { return Tuple.of(take(n), drop(n)); } @Override default Tuple2, Stream> splitAt(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Tuple.of(takeWhile(predicate.negate()), dropWhile(predicate.negate())); } @Override default Tuple2, Stream> splitAtInclusive(Predicate predicate) { final Tuple2, Stream> split = splitAt(predicate); if (split._2.isEmpty()) { return split; } else { return Tuple.of(split._1.append(split._2.head()), split._2.tail()); } } @Override default String stringPrefix() { return "Stream"; } @Override default Stream subSequence(int beginIndex) { if (beginIndex < 0) { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ")"); } Stream result = this; for (int i = 0; i < beginIndex; i++, result = result.tail()) { if (result.isEmpty()) { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ") on Stream of size " + i); } } return result; } @Override default Stream subSequence(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ", " + endIndex + ")"); } if (beginIndex > endIndex) { throw new IllegalArgumentException("subSequence(" + beginIndex + ", " + endIndex + ")"); } if (beginIndex == endIndex) { return Empty.instance(); } else if (isEmpty()) { throw new IndexOutOfBoundsException("subSequence of Nil"); } else if (beginIndex == 0) { return cons(head(), () -> tail().subSequence(0, endIndex - 1)); } else { return tail().subSequence(beginIndex - 1, endIndex - 1); } } @Override Stream tail(); @Override default Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override default Stream take(int n) { if (n < 1 || isEmpty()) { return empty(); } else if (n == 1) { return cons(head(), Stream::empty); } else { return cons(head(), () -> tail().take(n - 1)); } } @Override default Stream takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override default Stream takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Empty.instance(); } else { final T head = head(); if (predicate.test(head)) { return cons(head, () -> tail().takeWhile(predicate)); } else { return Empty.instance(); } } } @Override default Stream takeRight(int n) { Stream right = this; Stream remaining = drop(n); while (!remaining.isEmpty()) { right = right.tail(); remaining = remaining.tail(); } return right; } @Override default Stream takeRightUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reverse().takeUntil(predicate).reverse(); } @Override default Stream takeRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeRightUntil(predicate.negate()); } /** * Transforms this {@code Stream}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override default Tuple2, Stream> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Stream> stream = map(unzipper); final Stream stream1 = stream.map(t -> t._1); final Stream stream2 = stream.map(t -> t._2); return Tuple.of(stream1, stream2); } @Override default Tuple3, Stream, Stream> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); final Stream> stream = map(unzipper); final Stream stream1 = stream.map(t -> t._1); final Stream stream2 = stream.map(t -> t._2); final Stream stream3 = stream.map(t -> t._3); return Tuple.of(stream1, stream2, stream3); } @Override default Stream update(int index, T element) { if (isEmpty()) { throw new IndexOutOfBoundsException("update(" + index + ", e) on Nil"); } if (index < 0) { throw new IndexOutOfBoundsException("update(" + index + ", e)"); } Stream preceding = Empty.instance(); Stream tail = this; for (int i = index; i > 0; i--, tail = tail.tail()) { if (tail.isEmpty()) { throw new IndexOutOfBoundsException("update at " + index); } preceding = preceding.prepend(tail.head()); } if (tail.isEmpty()) { throw new IndexOutOfBoundsException("update at " + index); } // skip the current head element because it is replaced return preceding.reverse().appendAll(tail.tail().prepend(element)); } @Override default Stream update(int index, Function updater) { Objects.requireNonNull(updater, "updater is null"); return update(index, updater.apply(get(index))); } @Override default Stream> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override default Stream zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWith(that, mapper)); } @Override default Stream> zipAll(Iterable iterable, T thisElem, U thatElem) { Objects.requireNonNull(iterable, "iterable is null"); return Stream.ofAll(iterator().zipAll(iterable, thisElem, thatElem)); } @Override default Stream> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override default Stream zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWithIndex(mapper)); } /** * Extends (continues) this {@code Stream} with a constantly repeated value. * * @param next value with which the stream should be extended * @return new {@code Stream} composed from this stream extended with a Stream of provided value */ default Stream extend(T next) { return Stream.ofAll(this.appendAll(Stream.continually(next))); } /** * Extends (continues) this {@code Stream} with values provided by a {@code Supplier} * * @param nextSupplier a supplier which will provide values for extending a stream * @return new {@code Stream} composed from this stream extended with values provided by the supplier */ default Stream extend(Supplier nextSupplier) { Objects.requireNonNull(nextSupplier, "nextSupplier is null"); return Stream.ofAll(appendAll(Stream.continually(nextSupplier))); } /** * Extends (continues) this {@code Stream} with a Stream of values created by applying * consecutively provided {@code Function} to the last element of the original Stream. * * @param nextFunction a function which calculates the next value basing on the previous value * @return new {@code Stream} composed from this stream extended with values calculated by the provided function */ default Stream extend(Function nextFunction) { Objects.requireNonNull(nextFunction, "nextFunction is null"); if (isEmpty()) { return this; } else { final Stream that = this; return Stream.ofAll(new AbstractIterator() { Stream stream = that; T last = null; @Override protected T getNext() { if (stream.isEmpty()) { stream = Stream.iterate(nextFunction.apply(last), nextFunction); } last = stream.head(); stream = stream.tail(); return last; } @Override public boolean hasNext() { return true; } }); } } /** * The empty Stream. *

* This is a singleton, i.e. not Cloneable. * * @param Component type of the Stream. */ final class Empty implements Stream, Serializable { private static final long serialVersionUID = 1L; private static final Empty INSTANCE = new Empty<>(); // hidden private Empty() { } /** * Returns the singleton empty Stream instance. * * @param Component type of the Stream * @return The empty Stream */ @SuppressWarnings("unchecked") public static Empty instance() { return (Empty) INSTANCE; } @Override public T head() { throw new NoSuchElementException("head of empty stream"); } @Override public boolean isEmpty() { return true; } @Override public Iterator iterator() { return Iterator.empty(); } @Override public Stream tail() { throw new UnsupportedOperationException("tail of empty stream"); } @Override public boolean equals(Object o) { return io.vavr.collection.Collections.equals(this, o); } @Override public int hashCode() { return io.vavr.collection.Collections.hashOrdered(this); } @Override public String toString() { return stringPrefix() + "()"; } /** * Instance control for object serialization. * * @return The singleton instance of Nil. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } } /** * Non-empty {@code Stream}, consisting of a {@code head}, and {@code tail}. * * @param Component type of the Stream. */ abstract class Cons implements Stream { private static final long serialVersionUID = 1L; final T head; final Lazy> tail; Cons(T head, Supplier> tail) { Objects.requireNonNull(tail, "tail is null"); this.head = head; this.tail = Lazy.of(tail); } @Override public T head() { return head; } @Override public boolean isEmpty() { return false; } @Override public Iterator iterator() { return new StreamIterator<>(this); } @Override public boolean equals(Object o) { return io.vavr.collection.Collections.equals(this, o); } @Override public int hashCode() { return io.vavr.collection.Collections.hashOrdered(this); } @Override public String toString() { final StringBuilder builder = new StringBuilder(stringPrefix()).append("("); Stream stream = this; while (stream != null && !stream.isEmpty()) { final Cons cons = (Cons) stream; builder.append(cons.head); if (cons.tail.isEvaluated()) { stream = stream.tail(); if (!stream.isEmpty()) { builder.append(", "); } } else { builder.append(", ?"); stream = null; } } return builder.append(")").toString(); } } } interface StreamModule { final class ConsImpl extends Cons implements Serializable { private static final long serialVersionUID = 1L; ConsImpl(T head, Supplier> tail) { super(head, tail); } @Override public Stream tail() { return tail.get(); } @GwtIncompatible("The Java serialization protocol is explicitly not supported") private Object writeReplace() { return new SerializationProxy<>(this); } @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } } final class AppendElements extends Cons implements Serializable { private static final long serialVersionUID = 1L; private final io.vavr.collection.Queue queue; AppendElements(T head, io.vavr.collection.Queue queue, Supplier> tail) { super(head, tail); this.queue = queue; } @Override public Stream append(T element) { return new AppendElements<>(head, queue.append(element), tail); } @Override public Stream appendAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); return isEmpty() ? Stream.ofAll(queue) : new AppendElements<>(head, queue.appendAll(elements), tail); } @Override public Stream tail() { final Stream t = tail.get(); if (t.isEmpty()) { return Stream.ofAll(queue); } else { if (t instanceof ConsImpl) { final ConsImpl c = (ConsImpl) t; return new AppendElements<>(c.head(), queue, c.tail); } else { final AppendElements a = (AppendElements) t; return new AppendElements<>(a.head(), a.queue.appendAll(queue), a.tail); } } } @GwtIncompatible("The Java serialization protocol is explicitly not supported") private Object writeReplace() { return new SerializationProxy<>(this); } @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } } /** * A serialization proxy which, in this context, is used to deserialize immutable, linked Streams with final * instance fields. * * @param The component type of the underlying stream. */ // DEV NOTE: The serialization proxy pattern is not compatible with non-final, i.e. extendable, // classes. Also, it may not be compatible with circular object graphs. @GwtIncompatible("The Java serialization protocol is explicitly not supported") final class SerializationProxy implements Serializable { private static final long serialVersionUID = 1L; // the instance to be serialized/deserialized private transient Cons stream; /** * Constructor for the case of serialization. *

* The constructor of a SerializationProxy takes an argument that concisely represents the logical state of * an instance of the enclosing class. * * @param stream a Cons */ SerializationProxy(Cons stream) { this.stream = stream; } /** * Write an object to a serialization stream. * * @param s An object serialization stream. * @throws java.io.IOException If an error occurs writing to the stream. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(stream.length()); for (Stream l = stream; !l.isEmpty(); l = l.tail()) { s.writeObject(l.head()); } } /** * Read an object from a deserialization stream. * * @param s An object deserialization stream. * @throws ClassNotFoundException If the object's class read from the stream cannot be found. * @throws InvalidObjectException If the stream contains no stream elements. * @throws IOException If an error occurs reading from the stream. */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); final int size = s.readInt(); if (size <= 0) { throw new InvalidObjectException("No elements"); } Stream temp = Empty.instance(); for (int i = 0; i < size; i++) { @SuppressWarnings("unchecked") final T element = (T) s.readObject(); temp = temp.append(element); } // DEV-NOTE: Cons is deserialized stream = (Cons) temp; } /** * {@code readResolve} method for the serialization proxy pattern. *

* Returns a logically equivalent instance of the enclosing class. The presence of this method causes the * serialization system to translate the serialization proxy back into an instance of the enclosing class * upon deserialization. * * @return A deserialized instance of the enclosing class. */ private Object readResolve() { return stream; } } final class AppendSelf { private final Cons self; AppendSelf(Cons self, Function, ? extends Stream> mapper) { this.self = appendAll(self, mapper); } private Cons appendAll(Cons stream, Function, ? extends Stream> mapper) { return (Cons) Stream.cons(stream.head(), () -> { final Stream tail = stream.tail(); return tail.isEmpty() ? mapper.apply(self) : appendAll((Cons) tail, mapper); }); } Cons stream() { return self; } } interface Combinations { static Stream> apply(Stream elements, int k) { if (k == 0) { return Stream.of(Stream.empty()); } else { return elements.zipWithIndex().flatMap( t -> apply(elements.drop(t._2 + 1), (k - 1)).map((Stream c) -> c.prepend(t._1)) ); } } } interface DropRight { // works with infinite streams by buffering elements static Stream apply(io.vavr.collection.List front, io.vavr.collection.List rear, Stream remaining) { if (remaining.isEmpty()) { return remaining; } else if (front.isEmpty()) { return apply(rear.reverse(), io.vavr.collection.List.empty(), remaining); } else { return Stream.cons(front.head(), () -> apply(front.tail(), rear.prepend(remaining.head()), remaining.tail())); } } } interface StreamFactory { static Stream create(java.util.Iterator iterator) { return iterator.hasNext() ? Stream.cons(iterator.next(), () -> create(iterator)) : Empty.instance(); } } final class StreamIterator extends AbstractIterator { private Supplier> current; StreamIterator(Cons stream) { this.current = () -> stream; } @Override public boolean hasNext() { return !current.get().isEmpty(); } @Override public T getNext() { final Stream stream = current.get(); // DEV-NOTE: we make the stream even more lazy because the next head must not be evaluated on hasNext() current = stream::tail; return stream.head(); } } final class FlatMapIterator implements Iterator { final Function> mapper; final Iterator inputs; java.util.Iterator current = java.util.Collections.emptyIterator(); FlatMapIterator(Iterator inputs, Function> mapper) { this.inputs = inputs; this.mapper = mapper; } @Override public boolean hasNext() { boolean currentHasNext; while (!(currentHasNext = current.hasNext()) && inputs.hasNext()) { current = mapper.apply(inputs.next()).iterator(); } return currentHasNext; } @Override public U next() { return current.next(); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Traversable.java000066400000000000000000001747401342074374400250420ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.Value; import io.vavr.control.Option; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import java.util.function.*; import java.util.stream.DoubleStream; /** * An interface for inherently recursive, multi-valued data structures. The order of elements is determined by * {@link Iterable#iterator()}, which may vary each time it is called. * *

* Basic operations: * *

    *
  • {@link #collect(PartialFunction)}
  • *
  • {@link #contains(Object)}
  • *
  • {@link #containsAll(Iterable)}
  • *
  • {@link #head()}
  • *
  • {@link #headOption()}
  • *
  • {@link #init()}
  • *
  • {@link #initOption()}
  • *
  • {@link #isEmpty()}
  • *
  • {@link #last()}
  • *
  • {@link #lastOption()}
  • *
  • {@link #length()}
  • *
  • {@link #size()}
  • *
  • {@link #tail()}
  • *
  • {@link #tailOption()}
  • *
* * Iteration: * *
    *
  • {@link #forEachWithIndex(ObjIntConsumer)}
  • *
  • {@link #grouped(int)}
  • *
  • {@link #iterator()}
  • *
  • {@link #slideBy(Function)}
  • *
  • {@link #sliding(int)}
  • *
  • {@link #sliding(int, int)}
  • *
* * Numeric operations: * *
    *
  • {@link #average()}
  • *
  • {@link #max()}
  • *
  • {@link #maxBy(Comparator)}
  • *
  • {@link #maxBy(Function)}
  • *
  • {@link #min()}
  • *
  • {@link #minBy(Comparator)}
  • *
  • {@link #minBy(Function)}
  • *
  • {@link #product()}
  • *
  • {@link #sum()}
  • *
* * Reduction/Folding: * *
    *
  • {@link #count(Predicate)}
  • *
  • {@link #fold(Object, BiFunction)}
  • *
  • {@link #foldLeft(Object, BiFunction)}
  • *
  • {@link #foldRight(Object, BiFunction)}
  • *
  • {@link #mkString()}
  • *
  • {@link #mkString(CharSequence)}
  • *
  • {@link #mkString(CharSequence, CharSequence, CharSequence)}
  • *
  • {@link #reduce(BiFunction)}
  • *
  • {@link #reduceOption(BiFunction)}
  • *
  • {@link #reduceLeft(BiFunction)}
  • *
  • {@link #reduceLeftOption(BiFunction)}
  • *
  • {@link #reduceRight(BiFunction)}
  • *
  • {@link #reduceRightOption(BiFunction)}
  • *
* * Selection: * *
    *
  • {@link #drop(int)}
  • *
  • {@link #dropRight(int)}
  • *
  • {@link #dropUntil(Predicate)}
  • *
  • {@link #dropWhile(Predicate)}
  • *
  • {@link #filter(Predicate)}
  • *
  • {@link #reject(Predicate)}
  • *
  • {@link #find(Predicate)}
  • *
  • {@link #findLast(Predicate)}
  • *
  • {@link #groupBy(Function)}
  • *
  • {@link #partition(Predicate)}
  • *
  • {@link #retainAll(Iterable)}
  • *
  • {@link #take(int)}
  • *
  • {@link #takeRight(int)}
  • *
  • {@link #takeUntil(Predicate)}
  • *
  • {@link #takeWhile(Predicate)}
  • *
* * Tests: * *
    *
  • {@link #existsUnique(Predicate)}
  • *
  • {@link #hasDefiniteSize()}
  • *
  • {@link #isDistinct()}
  • *
  • {@link #isOrdered()}
  • *
  • {@link #isSequential()}
  • *
  • {@link #isTraversableAgain()}
  • *
* * Transformation: * *
    *
  • {@link #distinct()}
  • *
  • {@link #distinctBy(Comparator)}
  • *
  • {@link #distinctBy(Function)}
  • *
  • {@link #flatMap(Function)}
  • *
  • {@link #map(Function)}
  • *
  • {@link #replace(Object, Object)}
  • *
  • {@link #replaceAll(Object, Object)}
  • *
  • {@link #scan(Object, BiFunction)}
  • *
  • {@link #scanLeft(Object, BiFunction)}
  • *
  • {@link #scanRight(Object, BiFunction)}
  • *
  • {@link #span(Predicate)}
  • *
  • {@link #unzip(Function)}
  • *
  • {@link #unzip3(Function)}
  • *
  • {@link #zip(Iterable)}
  • *
  • {@link #zipAll(Iterable, Object, Object)}
  • *
  • {@link #zipWithIndex()}
  • *
* * @param Component type * @author Daniel Dietrich and others */ public interface Traversable extends Foldable, Value { /** * Narrows a widened {@code Traversable} to {@code Traversable} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param traversable An {@code Traversable}. * @param Component type of the {@code Traversable}. * @return the given {@code traversable} instance as narrowed type {@code Traversable}. */ @SuppressWarnings("unchecked") static Traversable narrow(Traversable traversable) { return (Traversable) traversable; } /** * Matches each element with a unique key that you extract from it. * If the same key is present twice, the function will return {@code None}. * * @param getKey A function which extracts a key from elements * @param key class type * @return A Map containing the elements arranged by their keys. * @throws NullPointerException if {@code getKey} is null. * @see #groupBy(Function) */ default Option> arrangeBy(Function getKey) { return Option.of(groupBy(getKey).mapValues(Traversable::singleOption)) .filter(map -> !map.exists(kv -> kv._2.isEmpty())) .map(map -> Map.narrow(map.mapValues(Option::get))); } /** * Calculates the average of this elements, assuming that the element type is {@link Number}. * * Since we do not know if the component type {@code T} is of type {@code Number}, the * {@code average()} call might throw at runtime (see examples below). *

* Examples: * *

{@code
     * List.empty().average()                       // = None
     * List.of(1, 2, 3).average()                   // = Some(2.0)
     * List.of(1.0, 10e100, 2.0, -10e100).average() // = Some(0.75)
     * List.of(1.0, Double.NaN).average()           // = NaN
     * List.of("apple", "pear").average()           // throws
     * }
* * Please note that Java's {@link DoubleStream#average()} uses the * Kahan summation algorithm * (also known as compensated summation), which has known limitations. *

* Vavr uses Neumaier's modification of the Kahan algorithm, which yields better results. * *

{@code
     * // = OptionalDouble(0.0) (wrong)
     * j.u.s.DoubleStream.of(1.0, 10e100, 2.0, -10e100).average()
     *
     * // = Some(0.75) (correct)
     * List.of(1.0, 10e100, 2.0, -10e100).average()
     * }
* * @return {@code Some(average)} or {@code None}, if there are no elements * @throws UnsupportedOperationException if this elements are not numeric */ default Option average() { try { final double[] sum = TraversableModule.neumaierSum(this, t -> ((Number) t).doubleValue()); final double count = sum[1]; return (count == 0) ? Option.none() : Option.some(sum[0] / count); } catch(ClassCastException x) { throw new UnsupportedOperationException("not numeric", x); } } /** * Collects all elements that are in the domain of the given {@code partialFunction} by mapping the elements to type {@code R}. *

* More specifically, for each of this elements in iteration order first it is checked * *

{@code
     * partialFunction.isDefinedAt(element)
     * }
* * If the elements makes it through that filter, the mapped instance is added to the result collection * *
{@code
     * R newElement = partialFunction.apply(element)
     * }
* * Note:If this {@code Traversable} is ordered (i.e. extends {@link Ordered}, * the caller of {@code collect} has to ensure that the elements are comparable (i.e. extend {@link Comparable}). * * @param partialFunction A function that is not necessarily defined of all elements of this traversable. * @param The new element type * @return A new {@code Traversable} instance containing elements of type {@code R} * @throws NullPointerException if {@code partialFunction} is null */ Traversable collect(PartialFunction partialFunction); /** * Tests if this Traversable contains all given elements. *

* The result is equivalent to * {@code elements.isEmpty() ? true : contains(elements.head()) && containsAll(elements.tail())} but implemented * without recursion. * * @param elements A List of values of type T. * @return true, if this List contains all given elements, false otherwise. * @throws NullPointerException if {@code elements} is null */ default boolean containsAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); for (T element : elements) { if (!contains(element)) { return false; } } return true; } /** * Counts the elements which satisfy the given predicate. * * @param predicate A predicate * @return A number {@code >= 0} * @throws NullPointerException if {@code predicate} is null. */ default int count(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return foldLeft(0, (i, t) -> predicate.test(t) ? i + 1 : i); } /** * Returns a new version of this which contains no duplicates. Elements are compared using {@code equals}. * * @return a new {@code Traversable} containing this elements without duplicates */ Traversable distinct(); /** * Returns a new version of this which contains no duplicates. Elements are compared using the given * {@code comparator}. * * @param comparator A comparator * @return a new {@code Traversable} containing this elements without duplicates * @throws NullPointerException if {@code comparator} is null. */ Traversable distinctBy(Comparator comparator); /** * Returns a new version of this which contains no duplicates. Elements mapped to keys which are compared using * {@code equals}. *

* The elements of the result are determined in the order of their occurrence - first match wins. * * @param keyExtractor A key extractor * @param key type * @return a new {@code Traversable} containing this elements without duplicates * @throws NullPointerException if {@code keyExtractor} is null */ Traversable distinctBy(Function keyExtractor); /** * Drops the first n elements of this or all elements, if this length < n. * * @param n The number of elements to drop. * @return a new instance consisting of all elements of this except the first n ones, or else the empty instance, * if this has less than n elements. */ Traversable drop(int n); /** * Drops the last n elements of this or all elements, if this length < n. * * @param n The number of elements to drop. * @return a new instance consisting of all elements of this except the last n ones, or else the empty instance, * if this has less than n elements. */ Traversable dropRight(int n); /** * Drops elements until the predicate holds for the current element. * * @param predicate A condition tested subsequently for this elements. * @return a new instance consisting of all elements starting from the first one which does satisfy the given * predicate. * @throws NullPointerException if {@code predicate} is null */ Traversable dropUntil(Predicate predicate); /** * Drops elements while the predicate holds for the current element. *

* Note: This is essentially the same as {@code dropUntil(predicate.negate())}. * It is intended to be used with method references, which cannot be negated directly. * * @param predicate A condition tested subsequently for this elements. * @return a new instance consisting of all elements starting from the first one which does not satisfy the * given predicate. * @throws NullPointerException if {@code predicate} is null */ Traversable dropWhile(Predicate predicate); /** * In Vavr there are four basic classes of collections: * *

    *
  • Seq (sequential elements)
  • *
  • Set (distinct elements)
  • *
  • Map (indexed elements)
  • *
  • Multimap (indexed collections)
  • *
* * Two collection instances of these classes are equal if and only if both collections * *
    *
  • belong to the same basic collection class (Seq, Set, Map or Multimap)
  • *
  • contain the same elements
  • *
  • have the same element order, if the collections are of type Seq
  • *
* * Two Map/Multimap elements, resp. entries, (key1, value1) and (key2, value2) are equal, * if the keys are equal and the values are equal. *

* Notes: * *

    *
  • No collection instance equals null, e.g. Queue(1) not equals null.
  • *
  • Nulls are allowed and handled as expected, e.g. List(null, 1) equals Stream(null, 1) * and HashMap((null, 1)) equals LinkedHashMap((null, 1)). *
  • *
  • The element order is taken into account for Seq only. * E.g. List(null, 1) not equals Stream(1, null) * and HashMap((null, 1), ("a", null)) equals LinkedHashMap(("a", null), (null, 1)). * The reason is, that we do not know which implementations we compare when having * two instances of type Map, Multimap or Set (see Liskov Substitution Principle).
  • *
  • Other collection classes are equal if their types are equal and their elements are equal (in iteration order).
  • *
  • Iterator equality is defined to be object reference equality.
  • *
* * @param obj an object, may be null * @return true, if this collection equals the given object according to the rules described above, false otherwise. */ boolean equals(Object obj); /** * Checks, if a unique elements exists such that the predicate holds. * * @param predicate A Predicate * @return true, if predicate holds for a unique element, false otherwise * @throws NullPointerException if {@code predicate} is null */ default boolean existsUnique(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); boolean exists = false; for (T t : this) { if (predicate.test(t)) { if (exists) { return false; } else { exists = true; } } } return exists; } /** * Returns a new traversable consisting of all elements which satisfy the given predicate. * * @param predicate A predicate * @return a new traversable * @throws NullPointerException if {@code predicate} is null */ Traversable filter(Predicate predicate); /** * Returns a new traversable consisting of all elements which do not satisfy the given predicate. *

* The default implementation is equivalent to *

{@code filter(predicate.negate()}
* * @param predicate A predicate * @return a new traversable * @throws NullPointerException if {@code predicate} is null */ default Traversable reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(predicate.negate()); } /** * Returns the first element of this which satisfies the given predicate. * * @param predicate A predicate. * @return Some(element) or None, where element may be null (i.e. {@code List.of(null).find(e -> e == null)}). * @throws NullPointerException if {@code predicate} is null */ default Option find(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (T a : this) { if (predicate.test(a)) { return Option.some(a); // may be Some(null) } } return Option.none(); } /** * Returns the last element of this which satisfies the given predicate. *

* Same as {@code reverse().find(predicate)}. * * @param predicate A predicate. * @return Some(element) or None, where element may be null (i.e. {@code List.of(null).find(e -> e == null)}). * @throws NullPointerException if {@code predicate} is null */ default Option findLast(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterator().findLast(predicate); } /** * FlatMaps this Traversable. * * @param mapper A mapper * @param The resulting component type. * @return A new Traversable instance. */ Traversable flatMap(Function> mapper); @Override default U foldLeft(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); U xs = zero; for (T x : this) { xs = f.apply(xs, x); } return xs; } @Override U foldRight(U zero, BiFunction f); /** * Performs an action on each element. In contrast to {@link #forEach(Consumer)}, * additionally the element's index is passed to the given {@code action}. *

* This is essentially the same as {@code iterator().zipWithIndex().forEach()} but performs better because * no intermediate {@code Tuple2} instances are created and no boxing of int values takes place. *

* Please note that subsequent calls to {@code forEachWithIndex} might lead to different iteration orders, * depending on the underlying {@code Traversable} implementation. *

* Please also note that {@code forEachWithIndex} might loop infinitely if the {@code Traversable} is lazily * evaluated, like {@link Stream}. * * @param action A {@link ObjIntConsumer} * @throws NullPointerException if {@code action} is null */ default void forEachWithIndex(ObjIntConsumer action) { Objects.requireNonNull(action, "action is null"); int index = 0; for (T t : this) { action.accept(t, index++); } } /** * Gets the first value in iteration order if this {@code Traversable} is not empty, otherwise throws. * * @return the first value * @throws NoSuchElementException if this {@code Traversable} is empty. */ @Override default T get() { return head(); } /** * Groups this elements by classifying the elements. * * @param classifier A function which classifies elements into classes * @param classified class type * @return A Map containing the grouped elements * @throws NullPointerException if {@code classifier} is null. * @see #arrangeBy(Function) */ Map> groupBy(Function classifier); /** * Groups this {@code Traversable} into fixed size blocks. *

* Let length be the length of this Iterable. Then grouped is defined as follows: *

    *
  • If {@code this.isEmpty()}, the resulting {@code Iterator} is empty.
  • *
  • If {@code size <= length}, the resulting {@code Iterator} will contain {@code length / size} blocks of size * {@code size} and maybe a non-empty block of size {@code length % size}, if there are remaining elements.
  • *
  • If {@code size > length}, the resulting {@code Iterator} will contain one block of size {@code length}.
  • *
* Examples: *
     * 
     * [].grouped(1) = []
     * [].grouped(0) throws
     * [].grouped(-1) throws
     * [1,2,3,4].grouped(2) = [[1,2],[3,4]]
     * [1,2,3,4,5].grouped(2) = [[1,2],[3,4],[5]]
     * [1,2,3,4].grouped(5) = [[1,2,3,4]]
     * 
     * 
* * Please note that {@code grouped(int)} is a special case of {@linkplain #sliding(int, int)}, i.e. * {@code grouped(size)} is the same as {@code sliding(size, size)}. * * @param size a positive block size * @return A new Iterator of grouped blocks of the given size * @throws IllegalArgumentException if {@code size} is negative or zero */ Iterator> grouped(int size); /** * Checks if this Traversable is known to have a finite size. *

* This method should be implemented by classes only, i.e. not by interfaces. * * @return true, if this Traversable is known to have a finite size, false otherwise. */ boolean hasDefiniteSize(); /** * Returns the first element of a non-empty Traversable. * * @return The first element of this Traversable. * @throws NoSuchElementException if this is empty */ T head(); /** * Returns the first element of a non-empty Traversable as {@code Option}. * * @return {@code Some(element)} or {@code None} if this is empty. */ default Option headOption() { return isEmpty() ? Option.none() : Option.some(head()); } /** * Returns the hash code of this collection. *
* We distinguish between two types of hashes, those for collections with predictable iteration order (like Seq) and those with arbitrary iteration order (like Set, Map and Multimap). *
* In all cases the hash of an empty collection is defined to be 1. *
* Collections with predictable iteration order are hashed as follows: * *

{@code
     * int hash = 1;
     * for (T t : this) { hash = hash * 31 + Objects.hashCode(t); }
     * }
* * Collections with arbitrary iteration order are hashed in a way such that the hash of a fixed number of elements is independent of their iteration order. * *
{@code
     * int hash = 1;
     * for (T t : this) { hash += Objects.hashCode(t); }
     * }
* * Please note that the particular hashing algorithms may change in a future version of Vavr. *
* Generally, hash codes of collections aren't cached in Vavr (opposed to the size/length). * Storing hash codes in order to reduce the time complexity would increase the memory footprint. * Persistent collections are built upon tree structures, it allows us to implement efficient memory sharing. * A drawback of tree structures is that they make it necessary to store collection attributes at each tree node (read: element). *
* The computation of the hash code is linear in time, i.e. O(n). If the hash code of a collection is re-calculated often, * e.g. when using a List as HashMap key, we might want to cache the hash code. * This can be achieved by simply using a wrapper class, which is not included in Vavr but could be implemented like this: * *
{@code public final class Hashed {
     *
     *     private final K key;
     *     private final Lazy hashCode;
     *
     *     public Hashed(K key) {
     *         this.key = key;
     *         this.hashCode = Lazy.of(() -> Objects.hashCode(key));
     *     }
     *
     *     public K key() {
     *         return key;
     *     }
     *
     *     @Override
     *     public boolean equals(Object o) {
     *         if (o == key) {
     *             return true;
     *         } else if (key != null && o instanceof Hashed) {
     *             final Hashed that = (Hashed) o;
     *             return key.equals(that.key);
     *         } else {
     *             return false;
     *         }
     *     }
     *
     *     @Override
     *     public int hashCode() {
     *         return hashCode.get();
     *     }
     *
     *     @Override
     *     public String toString() {
     *         return "Hashed(" + (key == null ? "null" : key.toString()) + ")";
     *     }
     * }}
* * @return The hash code of this collection */ int hashCode(); /** * Dual of {@linkplain #tail()}, returning all elements except the last. * * @return a new instance containing all elements except the last. * @throws UnsupportedOperationException if this is empty */ Traversable init(); /** * Dual of {@linkplain #tailOption()}, returning all elements except the last as {@code Option}. * * @return {@code Some(traversable)} or {@code None} if this is empty. */ default Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } /** * Checks if this Traversable may consist of distinct elements only. * * @return true if this Traversable may consist of distinct elements only, false otherwise. */ default boolean isDistinct() { return false; } /** * Checks if this Traversable is empty. * * @return true, if this Traversable contains no elements, false otherwise. */ @Override default boolean isEmpty() { return length() == 0; } /** * Checks if this Traversable is ordered * * @return true, if this Traversable is ordered, false otherwise. */ default boolean isOrdered() { return false; } /** * Checks if the elements of this Traversable appear in encounter order. * * @return true, if the insertion order of elements is preserved, false otherwise. */ default boolean isSequential() { return false; } /** * Each of Vavr's collections may contain more than one element. * * @return {@code false} */ @Override default boolean isSingleValued() { return false; } /** * Checks if this Traversable can be repeatedly traversed. *

* This method should be implemented by classes only, i.e. not by interfaces. * * @return true, if this Traversable is known to be traversable repeatedly, false otherwise. */ boolean isTraversableAgain(); /** * An iterator by means of head() and tail(). Subclasses may want to override this method. * * @return A new Iterator of this Traversable elements. */ @Override default Iterator iterator() { final Traversable that = this; return new AbstractIterator() { Traversable traversable = that; @Override public boolean hasNext() { return !traversable.isEmpty(); } @Override public T getNext() { final T result = traversable.head(); traversable = traversable.tail(); return result; } }; } /** * Dual of {@linkplain #head()}, returning the last element. * * @return the last element. * @throws NoSuchElementException is this is empty */ T last(); /** * Dual of {@linkplain #headOption()}, returning the last element as {@code Option}. * * @return {@code Some(element)} or {@code None} if this is empty. */ default Option lastOption() { return isEmpty() ? Option.none() : Option.some(last()); } /** * Computes the number of elements of this Traversable. *

* Same as {@link #size()}. * * @return the number of elements */ int length(); /** * Maps the elements of this {@code Traversable} to elements of a new type preserving their order, if any. * * @param mapper A mapper. * @param Component type of the target Traversable * @return a mapped Traversable * @throws NullPointerException if {@code mapper} is null */ @Override Traversable map(Function mapper); /** * Calculates the maximum of this elements according to their natural order. Especially the underlying * order of sorted collections is not taken into account. *

* Examples: *

     * 
     * List.empty().max()             // = None
     * List.of(1, 2, 3).max()         // = Some(3)
     * List.of("a", "b", "c").max()   // = Some("c")
     * List.of(1.0, Double.NaN).max() // = NaN
     * List.of(1, "a").max()          // throws
     * 
     * 
* * @return {@code Some(maximum)} of this elements or {@code None} if this is empty * @throws NullPointerException if an element is null * @throws ClassCastException if the elements do not have a natural order, i.e. they do not implement Comparable */ default Option max() { return maxBy(Comparators.naturalComparator()); } /** * Calculates the maximum of this elements using a specific comparator. * * @param comparator A non-null element comparator * @return {@code Some(maximum)} of this elements or {@code None} if this is empty * @throws NullPointerException if {@code comparator} is null */ default Option maxBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); if (isEmpty()) { return Option.none(); } else { final T value = reduce((t1, t2) -> comparator.compare(t1, t2) >= 0 ? t1 : t2); return Option.some(value); } } /** * Calculates the maximum of this elements within the co-domain of a specific function. * * @param f A function that maps this elements to comparable elements * @param The type where elements are compared * @return The element of type T which is the maximum within U * @throws NullPointerException if {@code f} is null. */ default > Option maxBy(Function f) { Objects.requireNonNull(f, "f is null"); if (isEmpty()) { return Option.none(); } else { final Iterator iter = iterator(); T tm = iter.next(); U um = f.apply(tm); while (iter.hasNext()) { final T t = iter.next(); final U u = f.apply(t); if (u.compareTo(um) > 0) { um = u; tm = t; } } return Option.some(tm); } } /** * Calculates the minimum of this elements according to their natural order in O(n). Especially the underlying * order of sorted collections is not taken into account. *

* Examples: *

     * 
     * List.empty().min()             // = None
     * List.of(1, 2, 3).min()         // = Some(1)
     * List.of("a", "b", "c").min()   // = Some("a")
     * List.of(1.0, Double.NaN).min() // = NaN
     * List.of(1, "a").min()          // throws
     * 
     * 
* * There is an exception for {@link Double} and {@link Float}: The minimum is defined to be {@code NaN} if * this contains {@code NaN}. According to the natural order {@code NaN} would be the maximum element * instead. * * @return {@code Some(minimum)} of this elements or {@code None} if this is empty * @throws NullPointerException if an element is null * @throws ClassCastException if the elements do not have a natural order, i.e. they do not implement Comparable */ @SuppressWarnings("unchecked") default Option min() { // DEV-NOTE: minBy(Comparators.naturalComparator()) does not handle (Double/Float) NaN correctly if (isEmpty()) { return Option.none(); } else { final T head = head(); final T min; if (head instanceof Double) { min = (T) ((Traversable) this).foldLeft((Double) head, Math::min); } else if (head instanceof Float) { min = (T) ((Traversable) this).foldLeft((Float) head, Math::min); } else { final Comparator comparator = Comparators.naturalComparator(); min = this.foldLeft(head, (t1, t2) -> comparator.compare(t1, t2) <= 0 ? t1 : t2); } return Option.some(min); } } /** * Calculates the minimum of this elements using a specific comparator. * * @param comparator A non-null element comparator * @return {@code Some(minimum)} of this elements or {@code None} if this is empty * @throws NullPointerException if {@code comparator} is null */ default Option minBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); if (isEmpty()) { return Option.none(); } else { final T value = reduce((t1, t2) -> comparator.compare(t1, t2) <= 0 ? t1 : t2); return Option.some(value); } } /** * Calculates the minimum of this elements within the co-domain of a specific function. * * @param f A function that maps this elements to comparable elements * @param The type where elements are compared * @return The element of type T which is the minimum within U * @throws NullPointerException if {@code f} is null. */ default > Option minBy(Function f) { Objects.requireNonNull(f, "f is null"); if (isEmpty()) { return Option.none(); } else { final Iterator iter = iterator(); T tm = iter.next(); U um = f.apply(tm); while (iter.hasNext()) { final T t = iter.next(); final U u = f.apply(t); if (u.compareTo(um) < 0) { um = u; tm = t; } } return Option.some(tm); } } /** * Joins the elements of this by concatenating their string representations. *

* This has the same effect as calling {@code mkCharSeq("", "", "")}. * * @return a new {@link CharSeq} */ default CharSeq mkCharSeq() { return mkCharSeq("", "", ""); } /** * Joins the string representations of this elements using a specific delimiter. *

* This has the same effect as calling {@code mkCharSeq("", delimiter, "")}. * * @param delimiter A delimiter string put between string representations of elements of this * @return A new {@link CharSeq} */ default CharSeq mkCharSeq(CharSequence delimiter) { return mkCharSeq("", delimiter, ""); } /** * Joins the string representations of this elements using a specific delimiter, prefix and suffix. *

* Example: {@code List.of("a", "b", "c").mkCharSeq("Chars(", ", ", ")") = CharSeq.of("Chars(a, b, c))"} * * @param prefix prefix of the resulting {@link CharSeq} * @param delimiter A delimiter string put between string representations of elements of this * @param suffix suffix of the resulting {@link CharSeq} * @return a new {@link CharSeq} */ default CharSeq mkCharSeq(CharSequence prefix, CharSequence delimiter, CharSequence suffix) { return CharSeq.of(mkString(prefix, delimiter, suffix)); } /** * Joins the elements of this by concatenating their string representations. *

* This has the same effect as calling {@code mkString("", "", "")}. * * @return a new String */ default String mkString() { return mkString("", "", ""); } /** * Joins the string representations of this elements using a specific delimiter. *

* This has the same effect as calling {@code mkString("", delimiter, "")}. * * @param delimiter A delimiter string put between string representations of elements of this * @return A new String */ default String mkString(CharSequence delimiter) { return mkString("", delimiter, ""); } /** * Joins the string representations of this elements using a specific delimiter, prefix and suffix. *

* Example: {@code List.of("a", "b", "c").mkString("Chars(", ", ", ")") = "Chars(a, b, c)"} * * @param prefix prefix of the resulting string * @param delimiter A delimiter string put between string representations of elements of this * @param suffix suffix of the resulting string * @return a new String */ default String mkString(CharSequence prefix, CharSequence delimiter, CharSequence suffix) { final StringBuilder builder = new StringBuilder(prefix); iterator().map(String::valueOf).intersperse(String.valueOf(delimiter)).forEach(builder::append); return builder.append(suffix).toString(); } /** * Checks, this {@code Traversable} is not empty. *

* The call is equivalent to {@code !isEmpty()}. * * @return true, if an underlying value is present, false otherwise. */ default boolean nonEmpty() { return !isEmpty(); } /** * Returns this {@code Traversable} if it is nonempty, otherwise return the alternative. * * @param other An alternative {@code Traversable} * @return this {@code Traversable} if it is nonempty, otherwise return the alternative. */ Traversable orElse(Iterable other); /** * Returns this {@code Traversable} if it is nonempty, otherwise return the result of evaluating supplier. * * @param supplier An alternative {@code Traversable} supplier * @return this {@code Traversable} if it is nonempty, otherwise return the result of evaluating supplier. */ Traversable orElse(Supplier> supplier); /** * Creates a partition of this {@code Traversable} by splitting this elements in two in distinct traversables * according to a predicate. * * @param predicate A predicate which classifies an element if it is in the first or the second traversable. * @return A disjoint union of two traversables. The first {@code Traversable} contains all elements that satisfy the given {@code predicate}, the second {@code Traversable} contains all elements that don't. The original order of elements is preserved. * @throws NullPointerException if predicate is null */ Tuple2, ? extends Traversable> partition(Predicate predicate); @Override Traversable peek(Consumer action); /** * Calculates the product of this elements. Supported component types are {@code Byte}, {@code Double}, {@code Float}, * {@code Integer}, {@code Long}, {@code Short}, {@code BigInteger} and {@code BigDecimal}. *

* Examples: *

     * 
     * List.empty().product()              // = 1
     * List.of(1, 2, 3).product()          // = 6L
     * List.of(0.1, 0.2, 0.3).product()    // = 0.006
     * List.of("apple", "pear").product()  // throws
     * 
     * 
* * Please also see {@link #fold(Object, BiFunction)}, a way to do a type-safe multiplication of elements. * * @return a {@code Number} representing the sum of this elements * @throws UnsupportedOperationException if this elements are not numeric */ @SuppressWarnings("unchecked") default Number product() { if (isEmpty()) { return 1; } else { try { final Iterator iter = iterator(); final Object o = iter.next(); if (o instanceof Integer || o instanceof Long || o instanceof Byte || o instanceof Short) { return ((Iterator) iter).foldLeft(((Number) o).longValue(), (product, number) -> product * number.longValue()); } else if (o instanceof BigInteger) { return ((Iterator) iter).foldLeft(((BigInteger) o), BigInteger::multiply); } else if (o instanceof BigDecimal) { return ((Iterator) iter).foldLeft(((BigDecimal) o), BigDecimal::multiply); } else { return ((Iterator) iter).toJavaStream().mapToDouble(Number::doubleValue).reduce(((Number) o).doubleValue(), (d1, d2) -> d1 * d2); } } catch(ClassCastException x) { throw new UnsupportedOperationException("not numeric", x); } } } /** * Accumulates the elements of this Traversable by successively calling the given operation {@code op} from the left. * * @param op A BiFunction of type T * @return the reduced value. * @throws NoSuchElementException if this is empty * @throws NullPointerException if {@code op} is null */ @Override default T reduceLeft(BiFunction op) { Objects.requireNonNull(op, "op is null"); return iterator().reduceLeft(op); } /** * Shortcut for {@code isEmpty() ? Option.none() : Option.some(reduceLeft(op))}. * * @param op A BiFunction of type T * @return a reduced value * @throws NullPointerException if {@code op} is null */ @Override default Option reduceLeftOption(BiFunction op) { Objects.requireNonNull(op, "op is null"); return isEmpty() ? Option.none() : Option.some(reduceLeft(op)); } /** * Accumulates the elements of this Traversable by successively calling the given operation {@code op} from the right. * * @param op An operation of type T * @return the reduced value. * @throws NoSuchElementException if this is empty * @throws NullPointerException if {@code op} is null */ @Override default T reduceRight(BiFunction op) { Objects.requireNonNull(op, "op is null"); if (isEmpty()) { throw new NoSuchElementException("reduceRight on empty"); } else { return iterator().reduceRight(op); } } /** * Shortcut for {@code isEmpty() ? Option.none() : Option.some(reduceRight(op))}. * * @param op An operation of type T * @return a reduced value * @throws NullPointerException if {@code op} is null */ @Override default Option reduceRightOption(BiFunction op) { Objects.requireNonNull(op, "op is null"); return isEmpty() ? Option.none() : Option.some(reduceRight(op)); } /** * Replaces the first occurrence (if exists) of the given currentElement with newElement. * * @param currentElement An element to be substituted. * @param newElement A replacement for currentElement. * @return a Traversable containing all elements of this where the first occurrence of currentElement is replaced with newElement. */ Traversable replace(T currentElement, T newElement); /** * Replaces all occurrences of the given currentElement with newElement. * * @param currentElement An element to be substituted. * @param newElement A replacement for currentElement. * @return a Traversable containing all elements of this where all occurrences of currentElement are replaced with newElement. */ Traversable replaceAll(T currentElement, T newElement); /** * Keeps all occurrences of the given elements from this. * * @param elements Elements to be kept. * @return a Traversable containing all occurrences of the given elements. * @throws NullPointerException if {@code elements} is null */ Traversable retainAll(Iterable elements); /** * Computes a prefix scan of the elements of the collection. * * Note: The neutral element z may be applied more than once. * * @param zero neutral element for the operator op * @param operation the associative operator for the scan * @return a new traversable collection containing the prefix scan of the elements in this traversable collection * @throws NullPointerException if {@code operation} is null. */ Traversable scan(T zero, BiFunction operation); /** * Produces a collection containing cumulative results of applying the * operator going left to right. * * Note: will not terminate for infinite-sized collections. * * Note: might return different results for different runs, unless the * underlying collection type is ordered. * * @param the type of the elements in the resulting collection * @param zero the initial value * @param operation the binary operator applied to the intermediate result and the element * @return collection with intermediate results * @throws NullPointerException if {@code operation} is null. */ Traversable scanLeft(U zero, BiFunction operation); /** * Produces a collection containing cumulative results of applying the * operator going right to left. The head of the collection is the last * cumulative result. * * Note: will not terminate for infinite-sized collections. * * Note: might return different results for different runs, unless the * underlying collection type is ordered. * * @param the type of the elements in the resulting collection * @param zero the initial value * @param operation the binary operator applied to the intermediate result and the element * @return collection with intermediate results * @throws NullPointerException if {@code operation} is null. */ Traversable scanRight(U zero, BiFunction operation); /** * Returns the single element of this Traversable or throws, if this is empty or contains more than one element. * * @return the single element from the Traversable * @throws NoSuchElementException if the Traversable does not contain a single element. */ default T single() { return singleOption().getOrElseThrow(() -> new NoSuchElementException("Does not contain a single value")); } /** * Returns the only element of a Traversable as {@code Option}. * * @return {@code Some(element)} or {@code None} if the Traversable does not contain a single element. */ default Option singleOption() { final Iterator it = iterator(); if (!it.hasNext()) { return Option.none(); } final T first = it.next(); if (it.hasNext()) { return Option.none(); } else { return Option.some(first); } } /** * Computes the number of elements of this Traversable. *

* Same as {@link #length()}. * * @return the number of elements */ default int size() { return length(); } /** * Slides a non-overlapping window of a variable size over this {@code Traversable}. *

* Each window contains elements with the same class, as determined by {@code classifier}. Two consecutive * values in this {@code Traversable} will be in the same window only if {@code classifier} returns equal * values for them. Otherwise, the values will constitute the last element of the previous window and the * first element of the next window. *

* Examples: *

{@code
     * [].slideBy(Function.identity()) = []
     * [1,2,3,4,4,5].slideBy(Function.identity()) = [[1],[2],[3],[4,4],[5]]
     * [1,2,3,10,12,5,7,20,29].slideBy(x -> x/10) = [[1,2,3],[10,12],[5,7],[20,29]]
     * }
* * @param classifier A function which classifies elements into classes * @return A new Iterator of windows of the grouped elements * @throws NullPointerException if {@code classifier} is null. */ Iterator> slideBy(Function classifier); /** * Slides a window of a specific {@code size} and step size 1 over this {@code Traversable} by calling * {@link #sliding(int, int)}. * * @param size a positive window size * @return a new Iterator of windows of a specific size using step size 1 * @throws IllegalArgumentException if {@code size} is negative or zero */ Iterator> sliding(int size); /** * Slides a window of a specific {@code size} and {@code step} size over this {@code Traversable}. *

* Examples: *

     * 
     * [].sliding(1,1) = []
     * [1,2,3,4,5].sliding(2,3) = [[1,2],[4,5]]
     * [1,2,3,4,5].sliding(2,4) = [[1,2],[5]]
     * [1,2,3,4,5].sliding(2,5) = [[1,2]]
     * [1,2,3,4].sliding(5,3) = [[1,2,3,4],[4]]
     * 
     * 
* * @param size a positive window size * @param step a positive step size * @return a new Iterator of windows of a specific size using a specific step size * @throws IllegalArgumentException if {@code size} or {@code step} are negative or zero */ Iterator> sliding(int size, int step); /** * Returns a tuple where the first element is the longest prefix of elements that satisfy the given * {@code predicate} and the second element is the remainder. * * @param predicate A predicate. * @return a {@code Tuple} containing the longest prefix of elements that satisfy p and the remainder. * @throws NullPointerException if {@code predicate} is null */ Tuple2, ? extends Traversable> span(Predicate predicate); @Override default Spliterator spliterator() { int characteristics = Spliterator.IMMUTABLE; if (isDistinct()) { characteristics |= Spliterator.DISTINCT; } if (isOrdered()) { characteristics |= (Spliterator.SORTED | Spliterator.ORDERED); } if (isSequential()) { characteristics |= Spliterator.ORDERED; } if (hasDefiniteSize()) { characteristics |= (Spliterator.SIZED | Spliterator.SUBSIZED); return Spliterators.spliterator(iterator(), length(), characteristics); } else { return Spliterators.spliteratorUnknownSize(iterator(), characteristics); } } /** * Calculates the sum of this elements. Supported component types are {@code Byte}, {@code Double}, {@code Float}, * {@code Integer}, {@code Long}, {@code Short}, {@code BigInteger} and {@code BigDecimal}. *

* Examples: *

     * 
     * List.empty().sum()              // = 0
     * List.of(1, 2, 3).sum()          // = 6L
     * List.of(0.1, 0.2, 0.3).sum()    // = 0.6
     * List.of("apple", "pear").sum()  // throws
     * 
     * 
* * Please also see {@link #fold(Object, BiFunction)}, a way to do a type-safe summation of elements. * * @return a {@code Number} representing the sum of this elements * @throws UnsupportedOperationException if this elements are not numeric */ @SuppressWarnings("unchecked") default Number sum() { if (isEmpty()) { return 0; } else { try { final Iterator iter = iterator(); final Object o = iter.next(); if (o instanceof Integer || o instanceof Long || o instanceof Byte || o instanceof Short) { return ((Iterator) iter).foldLeft(((Number) o).longValue(), (sum, number) -> sum + number.longValue()); } else if (o instanceof BigInteger) { return ((Iterator) iter).foldLeft(((BigInteger) o), BigInteger::add); } else if (o instanceof BigDecimal) { return ((Iterator) iter).foldLeft(((BigDecimal) o), BigDecimal::add); } else { return TraversableModule.neumaierSum(Iterator.of(o).concat(iter), t -> ((Number) t).doubleValue())[0]; } } catch(ClassCastException x) { throw new UnsupportedOperationException("not numeric", x); } } } /** * Drops the first element of a non-empty Traversable. * * @return A new instance of Traversable containing all elements except the first. * @throws UnsupportedOperationException if this is empty */ Traversable tail(); /** * Drops the first element of a non-empty Traversable and returns an {@code Option}. * * @return {@code Some(traversable)} or {@code None} if this is empty. */ Option> tailOption(); /** * Takes the first n elements of this or all elements, if this length < n. *

* The result is equivalent to {@code sublist(0, max(0, min(length(), n)))} but does not throw if {@code n < 0} or * {@code n > length()}. *

* In the case of {@code n < 0} the empty instance is returned, in the case of {@code n > length()} this is returned. * * @param n The number of elements to take. * @return A new instance consisting of the first n elements of this or all elements, if this has less than n elements. */ Traversable take(int n); /** * Takes the last n elements of this or all elements, if this length < n. *

* The result is equivalent to {@code sublist(max(0, min(length(), length() - n)), n)}, i.e. takeRight will not * throw if {@code n < 0} or {@code n > length()}. *

* In the case of {@code n < 0} the empty instance is returned, in the case of {@code n > length()} this is returned. * * @param n The number of elements to take. * @return A new instance consisting of the last n elements of this or all elements, if this has less than n elements. */ Traversable takeRight(int n); /** * Takes elements until the predicate holds for the current element. *

* Note: This is essentially the same as {@code takeWhile(predicate.negate())}. It is intended to be used with * method references, which cannot be negated directly. * * @param predicate A condition tested subsequently for this elements. * @return a new instance consisting of all elements before the first one which does satisfy the given * predicate. * @throws NullPointerException if {@code predicate} is null */ Traversable takeUntil(Predicate predicate); /** * Takes elements while the predicate holds for the current element. * * @param predicate A condition tested subsequently for the contained elements. * @return a new instance consisting of all elements before the first one which does not satisfy the * given predicate. * @throws NullPointerException if {@code predicate} is null */ Traversable takeWhile(Predicate predicate); /** * Unzips this elements by mapping this elements to pairs which are subsequently split into two distinct * sets. * * @param unzipper a function which converts elements of this to pairs * @param 1st element type of a pair returned by unzipper * @param 2nd element type of a pair returned by unzipper * @return A pair of set containing elements split by unzipper * @throws NullPointerException if {@code unzipper} is null */ Tuple2, ? extends Traversable> unzip( Function> unzipper); /** * Unzips this elements by mapping this elements to triples which are subsequently split into three distinct * sets. * * @param unzipper a function which converts elements of this to pairs * @param 1st element type of a triplet returned by unzipper * @param 2nd element type of a triplet returned by unzipper * @param 3rd element type of a triplet returned by unzipper * @return A triplet of set containing elements split by unzipper * @throws NullPointerException if {@code unzipper} is null */ Tuple3, ? extends Traversable, ? extends Traversable> unzip3( Function> unzipper); /** * Returns a traversable formed from this traversable and another Iterable collection by combining * corresponding elements in pairs. If one of the two iterables is longer than the other, its remaining elements * are ignored. *

* The length of the returned traversable is the minimum of the lengths of this traversable and {@code that} * iterable. * * @param The type of the second half of the returned pairs. * @param that The Iterable providing the second half of each result pair. * @return a new traversable containing pairs consisting of corresponding elements of this traversable and {@code that} iterable. * @throws NullPointerException if {@code that} is null */ Traversable> zip(Iterable that); /** * Returns a traversable formed from this traversable and another Iterable by combining corresponding elements in * pairs. If one of the two collections is shorter than the other, placeholder elements are used to extend the * shorter collection to the length of the longer. *

* The length of the returned traversable is the maximum of the lengths of this traversable and {@code that} * iterable. *

* Special case: if this traversable is shorter than that elements, and that elements contains duplicates, the * resulting traversable may be shorter than the maximum of the lengths of this and that because a traversable * contains an element at most once. *

* If this Traversable is shorter than that, thisElem values are used to fill the result. * If that is shorter than this Traversable, thatElem values are used to fill the result. * * @param The type of the second half of the returned pairs. * @param that The Iterable providing the second half of each result pair. * @param thisElem The element to be used to fill up the result if this traversable is shorter than that. * @param thatElem The element to be used to fill up the result if that is shorter than this traversable. * @return A new traversable containing pairs consisting of corresponding elements of this traversable and that. * @throws NullPointerException if {@code that} is null */ Traversable> zipAll(Iterable that, T thisElem, U thatElem); /** * Returns a traversable formed from this traversable and another Iterable collection by mapping elements. * If one of the two iterables is longer than the other, its remaining elements are ignored. *

* The length of the returned traversable is the minimum of the lengths of this traversable and {@code that} * iterable. * * @param The type of the second parameter of the mapper. * @param The type of the mapped elements. * @param that The Iterable providing the second parameter of the mapper. * @param mapper a mapper. * @return a new traversable containing mapped elements of this traversable and {@code that} iterable. * @throws NullPointerException if {@code that} or {@code mapper} is null */ Traversable zipWith(Iterable that, BiFunction mapper); /** * Zips this traversable with its indices. * * @return A new traversable containing all elements of this traversable paired with their index, starting with 0. */ Traversable> zipWithIndex(); /** * Returns a traversable formed from this traversable and another Iterable collection by mapping elements. * If one of the two iterables is longer than the other, its remaining elements are ignored. *

* The length of the returned traversable is the minimum of the lengths of this traversable and {@code that} * iterable. * * @param The type of the mapped elements. * @param mapper a mapper. * @return a new traversable containing mapped elements of this traversable and {@code that} iterable. * @throws NullPointerException if {@code mapper} is null */ Traversable zipWithIndex(BiFunction mapper); } interface TraversableModule { /** * Uses Neumaier's variant of the Kahan summation algorithm in order to sum double values. *

* See Kahan summation algorithm. * * @param element type * @param ts the elements * @param toDouble function which maps elements to {@code double} values * @return A pair {@code [sum, size]}, where {@code sum} is the compensated sum and {@code size} is the number of elements which were summed. */ static double[] neumaierSum(Iterable ts, ToDoubleFunction toDouble) { double simpleSum = 0.0; double sum = 0.0; double compensation = 0.0; int size = 0; for (T t : ts) { final double d = toDouble.applyAsDouble(t); final double tmp = sum + d; compensation += (Math.abs(sum) >= Math.abs(d)) ? (sum - tmp) + d : (d - tmp) + sum; sum = tmp; simpleSum += d; size++; } sum += compensation; if (size > 0 && Double.isNaN(sum) && Double.isInfinite(simpleSum)) { sum = simpleSum; } return new double[] { sum, size }; } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Tree.java000066400000000000000000001274501342074374400234630ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.collection.List.Nil; import io.vavr.collection.Tree.*; import io.vavr.control.Option; import java.io.*; import java.util.*; import java.util.function.*; import java.util.stream.Collector; import static io.vavr.collection.Tree.Order.PRE_ORDER; import static io.vavr.collection.Tree.*; /** * A general Tree interface. * * @param component type of this Tree * @author Daniel Dietrich, Grzegorz Piwowarek */ public interface Tree extends Traversable, Serializable { long serialVersionUID = 1L; /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link Tree}. * * @param Component type of the Tree. * @return A io.vavr.collection.Tree Collector. */ static Collector, Tree> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, Tree> finisher = Tree::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Returns the singleton empty tree. * * @param Type of tree values. * @return The empty tree. */ static Empty empty() { return Empty.instance(); } /** * Narrows a widened {@code Tree} to {@code Tree} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param tree An {@code Tree}. * @param Component type of the {@code Tree}. * @return the given {@code tree} instance as narrowed type {@code Tree}. */ @SuppressWarnings("unchecked") static Tree narrow(Tree tree) { return (Tree) tree; } /** * Returns a new Node containing the given value and having no children. * * @param value A value * @param Value type * @return A new Node instance. */ static Node of(T value) { return new Node<>(value, io.vavr.collection.List.empty()); } /** * Returns a new Node containing the given value and having the given children. * * @param value A value * @param children The child nodes, possibly empty * @param Value type * @return A new Node instance. */ @SuppressWarnings("varargs") @SafeVarargs static Node of(T value, Node... children) { Objects.requireNonNull(children, "children is null"); return new Node<>(value, io.vavr.collection.List.of(children)); } /** * Returns a new Node containing the given value and having the given children. * * @param value A value * @param children The child nodes, possibly empty * @param Value type * @return A new Node instance. */ static Node of(T value, Iterable> children) { Objects.requireNonNull(children, "children is null"); return new Node<>(value, io.vavr.collection.List.ofAll(children)); } /** * Creates a Tree of the given elements. * * @param Component type of the List. * @param values Zero or more values. * @return A Tree containing the given values. * @throws NullPointerException if {@code values} is null */ @SuppressWarnings("varargs") @SafeVarargs static Tree of(T... values) { Objects.requireNonNull(values, "values is null"); final io.vavr.collection.List list = io.vavr.collection.List.of(values); return list.isEmpty() ? Empty.instance() : new Node<>(list.head(), list.tail().map(Tree::of)); } /** * Creates a Tree of the given elements. *

* If the given iterable is a tree, it is returned as result. * if the iteration order of the elements is stable. * * @param Component type of the List. * @param iterable An Iterable of elements. * @return A list containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("unchecked") static Tree ofAll(Iterable iterable) { Objects.requireNonNull(iterable, "iterable is null"); if (iterable instanceof Tree) { return (Tree) iterable; } else { final io.vavr.collection.List list = io.vavr.collection.List.ofAll(iterable); return list.isEmpty() ? Empty.instance() : new Node<>(list.head(), list.tail().map(Tree::of)); } } /** * Creates a Tree that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return A Tree containing the given elements in the same order. */ static Tree ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return ofAll(io.vavr.collection.Iterator.ofAll(javaStream.iterator())); } /** * Returns a Tree containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the Tree * @param n The number of elements in the Tree * @param f The Function computing element values * @return A Tree consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ static Tree tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return io.vavr.collection.Collections.tabulate(n, f, empty(), Tree::of); } /** * Returns a Tree containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the Tree * @param n The number of elements in the Tree * @param s The Supplier computing element values * @return A Tree of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ static Tree fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return io.vavr.collection.Collections.fill(n, s, empty(), Tree::of); } /** * Returns a Tree containing {@code n} times the given {@code element} * * @param Component type of the Tree * @param n The number of elements in the Tree * @param element The element * @return A Tree of size {@code n}, where each element is the given {@code element}. */ static Tree fill(int n, T element) { return io.vavr.collection.Collections.fillObject(n, element, empty(), Tree::of); } /** * Recursively builds a non-empty {@code Tree}, starting with the given {@code seed} value and proceeding in depth-first order. *

* The children of a node are created by *

    *
  1. applying the {@code descend} function to the node value
  2. *
  3. calling this method recursively by using each derived child value as new seed (in iteration order).
  4. *
*

* Example: *

{@code
     * // = (1 (2 4 5) 3)
     * Tree.recurse(1, i ->
     *   (i == 1) ? List.of(2, 3) :
     *   (i == 2) ? List.(4, 5) :
     *   List.empty()
     * ).toLispString();
     * }
* * @param seed The start value for the Tree * @param descend A function to calculate the child values * @param Value type * @return a new, non-empty {@code Tree} instance * @throws NullPointerException if {@code descend} is null */ static Node recurse(T seed, Function> descend) { Objects.requireNonNull(descend, "descend is null"); return Tree.of(seed, Stream.of(seed).flatMap(descend).map(children -> recurse(children, descend))); } /** * Build a {@code List} with roots of {@code Tree} from flat source. *

* {@code parentMapper} must return {@code null} for root element. * *

{@code
     *  // = [(1, null, "I"), (2, 1, "II"), (3, 1, "III"), (4, 2, "IV"), (5, 2, "V")]
     *  List items = ...; // MenuItem(id, parentId, label)
     *
     *  //      I
     *  //     / \
     *  //   II  III
     *  //   /\
     *  //  IV V
     *  Tree menu = Tree.build(items, MenuItem::getId, MenuItem::getParentId);
     * }
* * @param source Flat source * @param idMapper A mapper from source item to unique identifier of that item * @param parentMapper A mapper from source item to unique identifier of parent item. Need return null for root items * @param Value type * @param Id type * @return a new, maybe empty {@code List} instance with non-empty {@code Tree} instances * @throws NullPointerException if {@code source}, {@code idMapper} or {@code parentMapper} is null */ static List> build(Iterable source, Function idMapper, Function parentMapper) { Objects.requireNonNull(source, "source is null"); Objects.requireNonNull(source, "idMapper is null"); Objects.requireNonNull(source, "parentMapper is null"); final List list = List.ofAll(source); final Map> byParent = list.groupBy(parentMapper); final Function> descend = idMapper .andThen(byParent::get) .andThen(o -> o.getOrElse(List::empty)); final List roots = byParent.get(null).getOrElse(List::empty); return roots.map(v -> recurse(v, descend)); } @Override default Tree collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } /** * Gets the value of this tree. * * @return The value of this tree. * @throws java.lang.UnsupportedOperationException if this tree is empty */ T getValue(); /** * Returns the children of this tree. * * @return the tree's children */ io.vavr.collection.List> getChildren(); /** * Checks if this Tree is a leaf. A tree is a leaf if it is a Node with no children. * Because the empty tree is no Node, it is not a leaf by definition. * * @return true if this tree is a leaf, false otherwise. */ boolean isLeaf(); /** * Checks if this Tree is a branch. A Tree is a branch if it is a Node which has children. * Because the empty tree is not a Node, it is not a branch by definition. * * @return true if this tree is a branch, false otherwise. */ default boolean isBranch() { return !(isEmpty() || isLeaf()); } /** * A {@code Tree} is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } @Override default boolean isDistinct() { return false; } /** * A {@code Tree} is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } @Override default boolean isSequential() { return true; } /** * Traverses this tree values in a specific {@link Order}. * * @param order A traversal order * @return A new Iterator */ default io.vavr.collection.Iterator iterator(Order order) { return values(order).iterator(); } /** * Creates a Lisp-like representation of this {@code Tree}. * * @return This {@code Tree} as Lisp-string, i.e. represented as list of lists. */ String toLispString(); /** * Transforms this {@code Tree}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } /** * Traverses this tree in {@link Order#PRE_ORDER}. * * @return A sequence of nodes. */ default Seq> traverse() { return traverse(PRE_ORDER); } /** * Traverses this tree in a specific order. * * @param order the tree traversal order * @return A sequence of nodes. * @throws java.lang.NullPointerException if order is null */ default Seq> traverse(Order order) { Objects.requireNonNull(order, "order is null"); if (isEmpty()) { return Stream.empty(); } else { final Node node = (Node) this; switch (order) { case PRE_ORDER: return TreeModule.traversePreOrder(node); case IN_ORDER: return TreeModule.traverseInOrder(node); case POST_ORDER: return TreeModule.traversePostOrder(node); case LEVEL_ORDER: return TreeModule.traverseLevelOrder(node); default: throw new IllegalStateException("Unknown order: " + order.name()); } } } /** * Traverses this tree values in {@link Order#PRE_ORDER}. * Syntactic sugar for {@code traverse().map(Node::getValue)}. * * @return A sequence of the tree values. */ default Seq values() { return traverse(PRE_ORDER).map(Node::getValue); } /** * Traverses this tree values in a specific order. * Syntactic sugar for {@code traverse(order).map(Node::getValue)}. * * @param order the tree traversal order * @return A sequence of the tree values. * @throws java.lang.NullPointerException if order is null */ default Seq values(Order order) { return traverse(order).map(Node::getValue); } /** * Counts the number of branches of this tree. The empty tree and a leaf have no branches. * * @return The number of branches of this tree. */ default int branchCount() { if (isEmpty() || isLeaf()) { return 0; } else { return getChildren().foldLeft(1, (count, child) -> count + child.branchCount()); } } /** * Counts the number of leaves of this tree. The empty tree has no leaves. * * @return The number of leaves of this tree. */ default int leafCount() { if (isEmpty()) { return 0; } else if (isLeaf()) { return 1; } else { return getChildren().foldLeft(0, (count, child) -> count + child.leafCount()); } } /** * Counts the number of nodes (i.e. branches and leaves) of this tree. The empty tree has no nodes. * * @return The number of nodes of this tree. */ default int nodeCount() { return length(); } // -- Methods inherited from Traversable @Override default Seq distinct() { return values().distinct(); } @Override default Seq distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); if (isEmpty()) { return Stream.empty(); } else { return values().distinctBy(comparator); } } @Override default Seq distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); if (isEmpty()) { return Stream.empty(); } else { return values().distinctBy(keyExtractor); } } @Override default Seq drop(int n) { if (n >= length()) { return Stream.empty(); } else { return values().drop(n); } } @Override default Seq dropRight(int n) { if (n >= length()) { return Stream.empty(); } else { return values().dropRight(n); } } @Override default Seq dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override default Seq dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Stream.empty(); } else { return values().dropWhile(predicate); } } @Override default Seq filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Stream.empty(); } else { return values().filter(predicate); } } @Override default Seq reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Stream.empty(); } else { return values().reject(predicate); } } @Override default Tree flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? Empty.instance() : TreeModule.flatMap((Node) this, mapper); } @Override default U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); if (isEmpty()) { return zero; } else { return iterator().foldRight(zero, f); } } @SuppressWarnings("unchecked") @Override default Map> groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(values(), classifier, Stream::ofAll); } @Override default io.vavr.collection.Iterator> grouped(int size) { return sliding(size, size); } @Override default boolean hasDefiniteSize() { return true; } @Override default T head() { if (isEmpty()) { throw new NoSuchElementException("head of empty tree"); } else { return iterator().next(); } } @Override default Seq init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty tree"); } else { return values().init(); } } @Override default Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override default boolean isTraversableAgain() { return true; } @Override default io.vavr.collection.Iterator iterator() { return values().iterator(); } @Override default Tree map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? Empty.instance() : TreeModule.map((Node) this, mapper); } @Override default Tree orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override default Tree orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @SuppressWarnings("unchecked") @Override default Tuple2, Seq> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Tuple.of(Stream.empty(), Stream.empty()); } else { return (Tuple2, Seq>) values().partition(predicate); } } @Override default Tree peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return this; } @Override default Tree replace(T currentElement, T newElement) { if (isEmpty()) { return Empty.instance(); } else { return TreeModule.replace((Node) this, currentElement, newElement); } } @Override default Tree replaceAll(T currentElement, T newElement) { return map(t -> Objects.equals(t, currentElement) ? newElement : t); } @Override default Seq retainAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); return values().retainAll(elements); } @Override default Seq scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override default Seq scanLeft(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, io.vavr.collection.Iterator::toStream); } @Override default Seq scanRight(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, io.vavr.collection.Iterator::toStream); } @Override default io.vavr.collection.Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier); } @Override default io.vavr.collection.Iterator> sliding(int size) { return sliding(size, 1); } @Override default io.vavr.collection.Iterator> sliding(int size, int step) { return iterator().sliding(size, step); } @SuppressWarnings("unchecked") @Override default Tuple2, Seq> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Tuple.of(Stream.empty(), Stream.empty()); } else { return (Tuple2, Seq>) values().span(predicate); } } @Override default String stringPrefix() { return "Tree"; } @Override default Seq tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty tree"); } else { return values().tail(); } } @Override default Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override default Seq take(int n) { if (isEmpty()) { return Stream.empty(); } else { return values().take(n); } } @Override default Seq takeRight(int n) { if (isEmpty()) { return Stream.empty(); } else { return values().takeRight(n); } } @Override default Seq takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return values().takeUntil(predicate); } @Override default Seq takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return values().takeWhile(predicate); } @SuppressWarnings("unchecked") @Override default Tuple2, Tree> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (isEmpty()) { return Tuple.of(Empty.instance(), Empty.instance()); } else { return (Tuple2, Tree>) (Object) TreeModule.unzip((Node) this, unzipper); } } @SuppressWarnings("unchecked") @Override default Tuple3, Tree, Tree> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); if (isEmpty()) { return Tuple.of(Empty.instance(), Empty.instance(), Empty.instance()); } else { return (Tuple3, Tree, Tree>) (Object) TreeModule.unzip3((Node) this, unzipper); } } @Override default Tree> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override default Tree zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return Empty.instance(); } else { return TreeModule.zip((Node) this, that.iterator(), mapper); } } @Override default Tree> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); if (isEmpty()) { return io.vavr.collection.Iterator. ofAll(that).map(elem -> Tuple.of(thisElem, elem)).toTree(); } else { final java.util.Iterator thatIter = that.iterator(); final Tree> tree = TreeModule.zipAll((Node) this, thatIter, thatElem); if (thatIter.hasNext()) { final Iterable>> remainder = io.vavr.collection.Iterator .ofAll(thatIter) .map(elem -> of(Tuple.of(thisElem, elem))); return new Node<>(tree.getValue(), tree.getChildren().appendAll(remainder)); } else { return tree; } } } @Override default Tree> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override default Tree zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return zipWith(io.vavr.collection.Iterator.from(0), mapper); } @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); /** * Creates a neat 2-dimensional drawing of a tree. Unicode characters are used to draw node junctions. * * @return A nice string representation of the tree. */ String draw(); /** * Represents a tree node. * * @param value type */ final class Node implements Tree, Serializable { private static final long serialVersionUID = 1L; private final T value; private final io.vavr.collection.List> children; private final int size; /** * Constructs a rose tree branch. * * @param value A value. * @param children A non-empty list of children. * @throws NullPointerException if children is null * @throws IllegalArgumentException if children is empty */ public Node(T value, io.vavr.collection.List> children) { Objects.requireNonNull(children, "children is null"); this.value = value; this.children = children; this.size = children.foldLeft(1, (acc, child) -> acc + child.size); } @Override public io.vavr.collection.List> getChildren() { return children; } @Override public T getValue() { return value; } @Override public boolean isEmpty() { return false; } @Override public int length() { return size; } @Override public boolean isLeaf() { return size == 1; } @Override public T last() { return children.isEmpty() ? value : children.last().last(); } @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof Node) { final Node that = (Node) o; return Objects.equals(this.getValue(), that.getValue()) && Objects.equals(this.getChildren(), that.getChildren()); } else { return false; } } @Override public int hashCode() { return Tuple.hash(value, children); } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } @Override public String toLispString() { return toLispString(this); } @Override public String draw() { final StringBuilder builder = new StringBuilder(); drawAux("", builder); return builder.toString(); } private void drawAux(String indent, StringBuilder builder) { builder.append(value); for (io.vavr.collection.List> it = children; !it.isEmpty(); it = it.tail()) { final boolean isLast = it.tail().isEmpty(); builder.append('\n') .append(indent) .append(isLast ? "└──" : "├──"); it.head().drawAux(indent + (isLast ? " " : "│ "), builder); } } private static String toLispString(Tree tree) { final String value = String.valueOf(tree.getValue()); if (tree.isLeaf()) { return value; } else { final String children = tree.getChildren().map(child -> toLispString(child)).mkString(" "); return "(" + value + " " + children + ")"; } } // -- Serializable implementation /** * {@code writeReplace} method for the serialization proxy pattern. *

* The presence of this method causes the serialization system to emit a SerializationProxy instance instead of * an instance of the enclosing class. * * @return A SerializationProxy for this enclosing class. */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private Object writeReplace() { return new SerializationProxy<>(this); } /** * {@code readObject} method for the serialization proxy pattern. *

* Guarantees that the serialization system will never generate a serialized instance of the enclosing class. * * @param stream An object serialization stream. * @throws java.io.InvalidObjectException This method will throw with the message "Proxy required". */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } /** * A serialization proxy which, in this context, is used to deserialize immutable nodes with final * instance fields. * * @param The component type of the underlying tree. */ // DEV NOTE: The serialization proxy pattern is not compatible with non-final, i.e. extendable, // classes. Also, it may not be compatible with circular object graphs. @GwtIncompatible("The Java serialization protocol is explicitly not supported") private static final class SerializationProxy implements Serializable { private static final long serialVersionUID = 1L; // the instance to be serialized/deserialized private transient Node node; /** * Constructor for the case of serialization, called by {@link Node#writeReplace()}. *

* The constructor of a SerializationProxy takes an argument that concisely represents the logical state of * an instance of the enclosing class. * * @param node a Branch */ SerializationProxy(Node node) { this.node = node; } /** * Write an object to a serialization stream. * * @param s An object serialization stream. * @throws java.io.IOException If an error occurs writing to the stream. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeObject(node.value); s.writeObject(node.children); } /** * Read an object from a deserialization stream. * * @param s An object deserialization stream. * @throws ClassNotFoundException If the object's class read from the stream cannot be found. * @throws IOException If an error occurs reading from the stream. */ @SuppressWarnings("unchecked") private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); final T value = (T) s.readObject(); final io.vavr.collection.List> children = (io.vavr.collection.List>) s.readObject(); node = new Node<>(value, children); } /** * {@code readResolve} method for the serialization proxy pattern. *

* Returns a logically equivalent instance of the enclosing class. The presence of this method causes the * serialization system to translate the serialization proxy back into an instance of the enclosing class * upon deserialization. * * @return A deserialized instance of the enclosing class. */ private Object readResolve() { return node; } } } /** * The empty tree. Use Tree.empty() to create an instance. * * @param type of the tree's values */ final class Empty implements Tree, Serializable { private static final long serialVersionUID = 1L; private static final Empty INSTANCE = new Empty<>(); // hidden private Empty() { } @SuppressWarnings("unchecked") public static Empty instance() { return (Empty) INSTANCE; } @Override public io.vavr.collection.List> getChildren() { return Nil.instance(); } @Override public T getValue() { throw new UnsupportedOperationException("getValue of empty Tree"); } @Override public boolean isEmpty() { return true; } @Override public int length() { return 0; } @Override public boolean isLeaf() { return false; } @Override public T last() { throw new NoSuchElementException("last of empty tree"); } @Override public boolean equals(Object o) { return o == this; } @Override public int hashCode() { return 1; } @Override public String toString() { return stringPrefix() + "()"; } @Override public String toLispString() { return "()"; } @Override public String draw() { return "▣"; } // -- Serializable implementation /** * Instance control for object serialization. * * @return The singleton instance of Nil. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } } /** * Tree traversal order. *

* Example tree: *

     * 
     *         1
     *        / \
     *       /   \
     *      /     \
     *     2       3
     *    / \     /
     *   4   5   6
     *  /       / \
     * 7       8   9
     * 
     * 
*

* See also *

*/ // see http://programmers.stackexchange.com/questions/138766/in-order-traversal-of-m-way-trees enum Order { /** * 1 2 4 7 5 3 6 8 9 (= depth-first) */ PRE_ORDER, /** * 7 4 2 5 1 8 6 9 3 */ IN_ORDER, /** * 7 4 5 2 8 9 6 3 1 */ POST_ORDER, /** * 1 2 3 4 5 6 7 8 9 (= breadth-first) */ LEVEL_ORDER } } /** * Because the empty tree {@code Empty} cannot be a child of an existing tree, method implementations distinguish between the * empty and non-empty case. Because the structure of trees is recursive, often we have commands in the form of module * classes with one static method. */ interface TreeModule { @SuppressWarnings("unchecked") static Tree flatMap(Node node, Function> mapper) { final Tree mapped = ofAll(mapper.apply(node.getValue())); if (mapped.isEmpty()) { return empty(); } else { final io.vavr.collection.List> children = (io.vavr.collection.List>) (Object) node .getChildren() .map(child -> flatMap(child, mapper)) .filter(Tree::nonEmpty); return of(mapped.get(), children.prependAll(mapped.getChildren())); } } static Node map(Node node, Function mapper) { final U value = mapper.apply(node.getValue()); final io.vavr.collection.List> children = node.getChildren().map(child -> map(child, mapper)); return new Node<>(value, children); } // Idea: // Traverse (depth-first) until a match is found, then stop and rebuild relevant parts of the tree. // If not found, return the same tree instance. static Node replace(Node node, T currentElement, T newElement) { if (Objects.equals(node.getValue(), currentElement)) { return new Node<>(newElement, node.getChildren()); } else { for (Node child : node.getChildren()) { final Node newChild = replace(child, currentElement, newElement); final boolean found = newChild != child; if (found) { final io.vavr.collection.List> newChildren = node.getChildren().replace(child, newChild); return new Node<>(node.getValue(), newChildren); } } return node; } } static Stream> traversePreOrder(Node node) { return node.getChildren().foldLeft(Stream.of(node), (acc, child) -> acc.appendAll(traversePreOrder(child))); } static Stream> traverseInOrder(Node node) { if (node.isLeaf()) { return Stream.of(node); } else { final io.vavr.collection.List> children = node.getChildren(); return children .tail() .foldLeft(Stream.> empty(), (acc, child) -> acc.appendAll(traverseInOrder(child))) .prepend(node) .prependAll(traverseInOrder(children.head())); } } static Stream> traversePostOrder(Node node) { return node .getChildren() .foldLeft(Stream.> empty(), (acc, child) -> acc.appendAll(traversePostOrder(child))) .append(node); } static Stream> traverseLevelOrder(Node node) { Stream> result = Stream.empty(); final java.util.Queue> queue = new java.util.LinkedList<>(); queue.add(node); while (!queue.isEmpty()) { final Node next = queue.remove(); result = result.prepend(next); queue.addAll(next.getChildren().toJavaList()); } return result.reverse(); } static Tuple2, Node> unzip(Node node, Function> unzipper) { final Tuple2 value = unzipper.apply(node.getValue()); final io.vavr.collection.List, Node>> children = node .getChildren() .map(child -> unzip(child, unzipper)); final Node node1 = new Node<>(value._1, children.map(t -> t._1)); final Node node2 = new Node<>(value._2, children.map(t -> t._2)); return Tuple.of(node1, node2); } static Tuple3, Node, Node> unzip3(Node node, Function> unzipper) { final Tuple3 value = unzipper.apply(node.getValue()); final io.vavr.collection.List, Node, Node>> children = node.getChildren() .map(child -> unzip3(child, unzipper)); final Node node1 = new Node<>(value._1, children.map(t -> t._1)); final Node node2 = new Node<>(value._2, children.map(t -> t._2)); final Node node3 = new Node<>(value._3, children.map(t -> t._3)); return Tuple.of(node1, node2, node3); } @SuppressWarnings("unchecked") static Tree zip(Node node, java.util.Iterator that, BiFunction mapper) { if (!that.hasNext()) { return Empty.instance(); } else { final R value = mapper.apply(node.getValue(), that.next()); final io.vavr.collection.List> children = (io.vavr.collection.List>) (Object) node .getChildren() .map(child -> zip(child, that, mapper)) .filter(Tree::nonEmpty); return new Node<>(value, children); } } @SuppressWarnings("unchecked") static Tree> zipAll(Node node, java.util.Iterator that, U thatElem) { if (!that.hasNext()) { return node.map(value -> Tuple.of(value, thatElem)); } else { final Tuple2 value = Tuple.of(node.getValue(), that.next()); final io.vavr.collection.List>> children = (io.vavr.collection.List>>) (Object) node .getChildren() .map(child -> zipAll(child, that, thatElem)) .filter(Tree::nonEmpty); return new Node<>(value, children); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/TreeMap.java000066400000000000000000001752041342074374400241210ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.*; import java.util.stream.Collector; /** * SortedMap implementation, backed by a Red/Black Tree. * * @param Key type * @param Value type * @author Daniel Dietrich */ // DEV-NOTE: use entries.min().get() in favor of iterator().next(), it is faster! public final class TreeMap implements SortedMap, Serializable { private static final long serialVersionUID = 1L; private final RedBlackTree> entries; private TreeMap(RedBlackTree> entries) { this.entries = entries; } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a * {@link TreeMap}. *

* The natural comparator is used to compare TreeMap keys. * * @param The key type * @param The value type * @return A {@link TreeMap} Collector. */ public static , V> Collector, ArrayList>, TreeMap> collector() { return createCollector(EntryComparator.natural()); } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a * {@link TreeMap}. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A {@link TreeMap} Collector. */ public static Collector, ArrayList>, TreeMap> collector(Comparator keyComparator) { return createCollector(EntryComparator.of(keyComparator)); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link TreeMap}. *

* The natural comparator is used to compare TreeMap keys. * * @param keyMapper The key mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @return A {@link TreeMap} Collector. */ public static , V, T extends V> Collector, TreeMap> collector( Function keyMapper) { Objects.requireNonNull(keyMapper, "key comparator is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); return createCollector(EntryComparator.natural(), keyMapper, v -> v); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link TreeMap}. *

* The natural comparator is used to compare TreeMap keys. * * @param keyMapper The key mapper * @param valueMapper The value mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @return A {@link TreeMap} Collector. */ public static , V, T> Collector, TreeMap> collector( Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "key comparator is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return createCollector(EntryComparator.natural(), keyMapper, valueMapper); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link TreeMap}. * * @param keyMapper The key mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @param keyComparator The comparator used to sort the entries by their key. * @return A {@link TreeMap} Collector. */ public static Collector, TreeMap> collector( Comparator keyComparator, Function keyMapper) { Objects.requireNonNull(keyMapper, "key comparator is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); return createCollector(EntryComparator.of(keyComparator), keyMapper, v -> v); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link TreeMap}. * * @param keyMapper The key mapper * @param valueMapper The value mapper * @param The key type * @param The value type * @param Initial {@link java.util.stream.Stream} elements type * @param keyComparator The comparator used to sort the entries by their key. * @return A {@link TreeMap} Collector. */ public static Collector, TreeMap> collector( Comparator keyComparator, Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "key comparator is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return createCollector(EntryComparator.of(keyComparator), keyMapper, valueMapper); } /** * Returns the empty TreeMap. The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @return A new empty TreeMap. */ public static , V> TreeMap empty() { return new TreeMap<>(RedBlackTree.empty(EntryComparator.natural())); } /** * Returns the empty TreeMap using the given key comparator. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new empty TreeMap. */ public static TreeMap empty(Comparator keyComparator) { return new TreeMap<>(RedBlackTree.empty(EntryComparator.of(keyComparator))); } /** * Narrows a widened {@code TreeMap} to {@code TreeMap} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. *

* CAUTION: If {@code K} is narrowed, the underlying {@code Comparator} might fail! * * @param treeMap A {@code TreeMap}. * @param Key type * @param Value type * @return the given {@code treeMap} instance as narrowed type {@code TreeMap}. */ @SuppressWarnings("unchecked") public static TreeMap narrow(TreeMap treeMap) { return (TreeMap) treeMap; } /** * Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one entry. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param entry A map entry. * @return A new TreeMap containing the given entry. */ public static , V> TreeMap of(Tuple2 entry) { Objects.requireNonNull(entry, "entry is null"); return createFromTuple(EntryComparator.natural(), entry); } /** * Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one entry using a specific key comparator. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entry A map entry. * @return A new TreeMap containing the given entry. */ public static TreeMap of(Comparator keyComparator, Tuple2 entry) { Objects.requireNonNull(entry, "entry is null"); return createFromTuple(EntryComparator.of(keyComparator), entry); } /** * Returns a {@code TreeMap}, from a source java.util.Map. * * @param map A map * @param The key type * @param The value type * @return A new Map containing the given map */ public static , V> TreeMap ofAll(java.util.Map map) { Objects.requireNonNull(map, "map is null"); return createFromMap(EntryComparator.natural(), map); } /** * Returns a {@code TreeMap}, from entries mapped from stream. * * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static , V> TreeMap ofAll(java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Maps.ofStream(TreeMap. empty(), stream, keyMapper, valueMapper); } /** * Returns a {@code TreeMap}, from entries mapped from stream. * * @param keyComparator The comparator used to sort the entries by their key. * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static TreeMap ofAll(Comparator keyComparator, java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Maps.ofStream(empty(keyComparator), stream, keyMapper, valueMapper); } /** * Returns a {@code TreeMap}, from entries mapped from stream. * * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static , V> TreeMap ofAll(java.util.stream.Stream stream, Function> entryMapper) { return Maps.ofStream(TreeMap. empty(), stream, entryMapper); } /** * Returns a {@code TreeMap}, from entries mapped from stream. * * @param keyComparator The comparator used to sort the entries by their key. * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new Map */ public static TreeMap ofAll(Comparator keyComparator, java.util.stream.Stream stream, Function> entryMapper) { return Maps.ofStream(empty(keyComparator), stream, entryMapper); } /** * Returns a {@code TreeMap}, from a source java.util.Map. * * @param keyComparator The comparator used to sort the entries by their key. * @param map A map * @param The key type * @param The value type * @return A new Map containing the given map */ public static TreeMap ofAll(Comparator keyComparator, java.util.Map map) { Objects.requireNonNull(map, "map is null"); return createFromMap(EntryComparator.of(keyComparator), map); } /** * Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one element. * * @param key A singleton map key. * @param value A singleton map value. * @param The key type * @param The value type * @return A new Map containing the given entry */ public static , V> TreeMap of(K key, V value) { return createFromPairs(EntryComparator.natural(), key, value); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3, k4, v4); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static , V> TreeMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { return createFromPairs(EntryComparator.natural(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } /** * Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one element. * * @param keyComparator The comparator used to sort the entries by their key. * @param key A singleton map key. * @param value A singleton map value. * @param The key type * @param The value type * @return A new Map containing the given entry */ public static TreeMap of(Comparator keyComparator, K key, V value) { return createFromPairs(EntryComparator.of(keyComparator), key, value); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3, k4, v4); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** * Creates a {@code TreeMap} of the given list of key-value pairs. * * @param keyComparator The comparator used to sort the entries by their key. * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @return A new Map containing the given entries */ public static TreeMap of(Comparator keyComparator, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { return createFromPairs(EntryComparator.of(keyComparator), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } /** * Returns a TreeMap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key * @param n The number of elements in the TreeMap * @param f The Function computing element values * @return A TreeMap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code keyComparator} or {@code f} are null */ public static TreeMap tabulate(Comparator keyComparator, int n, Function> f) { Objects.requireNonNull(f, "f is null"); return createTreeMap(EntryComparator.of(keyComparator), Collections.tabulate(n, f)); } /** * Returns a TreeMap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param n The number of elements in the TreeMap * @param f The Function computing element values * @return A TreeMap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static , V> TreeMap tabulate(int n, Function> f) { Objects.requireNonNull(f, "f is null"); return createTreeMap(EntryComparator.natural(), Collections.tabulate(n, f)); } /** * Returns a TreeMap containing tuples returned by {@code n} calls to a given Supplier {@code s}. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key * @param n The number of elements in the TreeMap * @param s The Supplier computing element values * @return A TreeMap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code keyComparator} or {@code s} are null */ @SuppressWarnings("unchecked") public static TreeMap fill(Comparator keyComparator, int n, Supplier> s) { Objects.requireNonNull(s, "s is null"); return createTreeMap(EntryComparator.of(keyComparator), Collections.fill(n, s)); } /** * Returns a TreeMap containing tuples returned by {@code n} calls to a given Supplier {@code s}. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param n The number of elements in the TreeMap * @param s The Supplier computing element values * @return A TreeMap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static , V> TreeMap fill(int n, Supplier> s) { Objects.requireNonNull(s, "s is null"); return createTreeMap(EntryComparator.natural(), Collections.fill(n, s)); } /** * Creates a {@code TreeMap} of the given entries using the natural key comparator. * * @param The key type * @param The value type * @param entries Map entries * @return A new TreeMap containing the given entries. */ @SuppressWarnings("varargs") @SafeVarargs public static , V> TreeMap ofEntries(Tuple2... entries) { return createFromTuples(EntryComparator.natural(), entries); } /** * Creates a {@code TreeMap} of the given entries using the given key comparator. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entries Map entries * @return A new TreeMap containing the given entries. */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public static TreeMap ofEntries(Comparator keyComparator, Tuple2... entries) { return createFromTuples(EntryComparator.of(keyComparator), entries); } /** * Creates a {@code TreeMap} of the given entries using the natural key comparator. * * @param The key type * @param The value type * @param entries Map entries * @return A new TreeMap containing the given entries. */ @SuppressWarnings("varargs") @SafeVarargs public static , V> TreeMap ofEntries(java.util.Map.Entry... entries) { return createFromMapEntries(EntryComparator.natural(), entries); } /** * Creates a {@code TreeMap} of the given entries using the given key comparator. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entries Map entries * @return A new TreeMap containing the given entries. */ @SuppressWarnings("varargs") @SafeVarargs public static TreeMap ofEntries(Comparator keyComparator, java.util.Map.Entry... entries) { return createFromMapEntries(EntryComparator.of(keyComparator), entries); } /** * Creates a {@code TreeMap} of the given entries. * * @param The key type * @param The value type * @param entries Map entries * @return A new TreeMap containing the given entries. */ public static , V> TreeMap ofEntries(Iterable> entries) { return createTreeMap(EntryComparator.natural(), entries); } /** * Creates a {@code TreeMap} of the given entries. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entries Map entries * @return A new TreeMap containing the given entries. */ @SuppressWarnings("unchecked") public static TreeMap ofEntries(Comparator keyComparator, Iterable> entries) { return createTreeMap(EntryComparator.of(keyComparator), entries); } // -- TreeMap API @Override public TreeMap bimap(Function keyMapper, Function valueMapper) { return bimap(this, EntryComparator.natural(), keyMapper, valueMapper); } @Override public TreeMap bimap(Comparator keyComparator, Function keyMapper, Function valueMapper) { return bimap(this, EntryComparator.of(keyComparator), keyMapper, valueMapper); } @Override public Tuple2> computeIfAbsent(K key, Function mappingFunction) { return Maps.computeIfAbsent(this, key, mappingFunction); } @Override public Tuple2, TreeMap> computeIfPresent(K key, BiFunction remappingFunction) { return Maps.computeIfPresent(this, key, remappingFunction); } @Override public boolean containsKey(K key) { return entries.contains(new Tuple2<>(key, /*ignored*/null)); } @Override public TreeMap distinct() { return Maps.distinct(this); } @Override public TreeMap distinctBy(Comparator> comparator) { return Maps.distinctBy(this, this::createFromEntries, comparator); } @Override public TreeMap distinctBy(Function, ? extends U> keyExtractor) { return Maps.distinctBy(this, this::createFromEntries, keyExtractor); } @Override public TreeMap drop(int n) { return Maps.drop(this, this::createFromEntries, this::emptyInstance, n); } @Override public TreeMap dropRight(int n) { return Maps.dropRight(this, this::createFromEntries, this::emptyInstance, n); } @Override public TreeMap dropUntil(Predicate> predicate) { return Maps.dropUntil(this, this::createFromEntries, predicate); } @Override public TreeMap dropWhile(Predicate> predicate) { return Maps.dropWhile(this, this::createFromEntries, predicate); } @Override public TreeMap filter(BiPredicate predicate) { return Maps.filter(this, this::createFromEntries, predicate); } @Override public TreeMap reject(BiPredicate predicate) { return Maps.reject(this, this::createFromEntries, predicate); } @Override public TreeMap filter(Predicate> predicate) { return Maps.filter(this, this::createFromEntries, predicate); } @Override public TreeMap reject(Predicate> predicate) { return Maps.reject(this, this::createFromEntries, predicate); } @Override public TreeMap filterKeys(Predicate predicate) { return Maps.filterKeys(this, this::createFromEntries, predicate); } @Override public TreeMap rejectKeys(Predicate predicate) { return Maps.rejectKeys(this, this::createFromEntries, predicate); } @Override public TreeMap filterValues(Predicate predicate) { return Maps.filterValues(this, this::createFromEntries, predicate); } @Override public TreeMap rejectValues(Predicate predicate) { return Maps.rejectValues(this, this::createFromEntries, predicate); } @Override public TreeMap flatMap(BiFunction>> mapper) { return flatMap(this, EntryComparator.natural(), mapper); } @Override public TreeMap flatMap(Comparator keyComparator, BiFunction>> mapper) { return flatMap(this, EntryComparator.of(keyComparator), mapper); } @Override public Option get(K key) { final V ignored = null; return entries.find(new Tuple2<>(key, ignored)).map(Tuple2::_2); } @Override public V getOrElse(K key, V defaultValue) { return get(key).getOrElse(defaultValue); } @Override public Map> groupBy(Function, ? extends C> classifier) { return Maps.groupBy(this, this::createFromEntries, classifier); } @Override public Iterator> grouped(int size) { return Maps.grouped(this, this::createFromEntries, size); } @Override public Tuple2 head() { if (isEmpty()) { throw new NoSuchElementException("head of empty TreeMap"); } else { return entries.min().get(); } } @Override public TreeMap init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty TreeMap"); } else { final Tuple2 max = entries.max().get(); return new TreeMap<>(entries.delete(max)); } } @Override public Option> initOption() { return Maps.initOption(this); } /** * An {@code TreeMap}'s value is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return entries.isEmpty(); } /** * An {@code TreeMap}'s value is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public Iterator> iterator() { return entries.iterator(); } @Override public SortedSet keySet() { return TreeSet.ofAll(comparator(), iterator().map(Tuple2::_1)); } @Override public TreeMap map(BiFunction> mapper) { return map(this, EntryComparator.natural(), mapper); } @Override public TreeMap map(Comparator keyComparator, BiFunction> mapper) { Objects.requireNonNull(keyComparator, "keyComparator is null"); return map(this, EntryComparator.of(keyComparator), mapper); } @Override public TreeMap mapKeys(Function keyMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); return map((k, v) -> Tuple.of(keyMapper.apply(k), v)); } @Override public TreeMap mapKeys(Function keyMapper, BiFunction valueMerge) { final Comparator comparator = Comparators.naturalComparator(); return Collections.mapKeys(this, TreeMap. empty(comparator), keyMapper, valueMerge); } @Override public TreeMap mapValues(Function valueMapper) { Objects.requireNonNull(valueMapper, "valueMapper is null"); return map(comparator(), (k, v) -> Tuple.of(k, valueMapper.apply(v))); } @Override public TreeMap merge(Map that) { return Maps.merge(this, this::createFromEntries, that); } @Override public TreeMap merge(Map that, BiFunction collisionResolution) { return Maps.merge(this, this::createFromEntries, that, collisionResolution); } /** * Returns this {@code TreeMap} if it is nonempty, * otherwise {@code TreeMap} created from iterable, using existing comparator. * * @param other An alternative {@code Traversable} * @return this {@code TreeMap} if it is nonempty, * otherwise {@code TreeMap} created from iterable, using existing comparator. */ @Override public TreeMap orElse(Iterable> other) { return isEmpty() ? ofEntries(comparator(), other) : this; } /** * Returns this {@code TreeMap} if it is nonempty, * otherwise {@code TreeMap} created from result of evaluating supplier, using existing comparator. * * @param supplier An alternative {@code Traversable} * @return this {@code TreeMap} if it is nonempty, * otherwise {@code TreeMap} created from result of evaluating supplier, using existing comparator. */ @Override public TreeMap orElse(Supplier>> supplier) { return isEmpty() ? ofEntries(comparator(), supplier.get()) : this; } @Override public Tuple2, TreeMap> partition(Predicate> predicate) { return Maps.partition(this, this::createFromEntries, predicate); } @Override public TreeMap peek(Consumer> action) { return Maps.peek(this, action); } @Override public TreeMap put(K key, U value, BiFunction merge) { return Maps.put(this, key, value, merge); } @Override public TreeMap put(K key, V value) { return new TreeMap<>(entries.insert(new Tuple2<>(key, value))); } @Override public TreeMap put(Tuple2 entry) { return Maps.put(this, entry); } @Override public TreeMap put(Tuple2 entry, BiFunction merge) { return Maps.put(this, entry, merge); } @Override public TreeMap remove(K key) { final V ignored = null; final Tuple2 entry = new Tuple2<>(key, ignored); if (entries.contains(entry)) { return new TreeMap<>(entries.delete(entry)); } else { return this; } } @Override @Deprecated public TreeMap removeAll(BiPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override public TreeMap removeAll(Iterable keys) { final V ignored = null; RedBlackTree> removed = entries; for (K key : keys) { final Tuple2 entry = new Tuple2<>(key, ignored); if (removed.contains(entry)) { removed = removed.delete(entry); } } if (removed.size() == entries.size()) { return this; } else { return new TreeMap<>(removed); } } @Override @Deprecated public TreeMap removeKeys(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectKeys(predicate); } @Override @Deprecated public TreeMap removeValues(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return rejectValues(predicate); } @Override public TreeMap replace(Tuple2 currentElement, Tuple2 newElement) { return Maps.replace(this, currentElement, newElement); } @Override public TreeMap replaceAll(Tuple2 currentElement, Tuple2 newElement) { return Maps.replaceAll(this, currentElement, newElement); } @Override public TreeMap replaceValue(K key, V value) { return Maps.replaceValue(this, key, value); } @Override public TreeMap replace(K key, V oldValue, V newValue) { return Maps.replace(this, key, oldValue, newValue); } @Override public TreeMap replaceAll(BiFunction function) { return Maps.replaceAll(this, function); } @Override public TreeMap retainAll(Iterable> elements) { Objects.requireNonNull(elements, "elements is null"); RedBlackTree> tree = RedBlackTree.empty(entries.comparator()); for (Tuple2 entry : elements) { if (contains(entry)) { tree = tree.insert(entry); } } return new TreeMap<>(tree); } @Override public TreeMap scan( Tuple2 zero, BiFunction, ? super Tuple2, ? extends Tuple2> operation) { return Maps.scan(this, zero, operation, this::createFromEntries); } @Override public int size() { return entries.size(); } @Override public Iterator> slideBy(Function, ?> classifier) { return Maps.slideBy(this, this::createFromEntries, classifier); } @Override public Iterator> sliding(int size) { return Maps.sliding(this, this::createFromEntries, size); } @Override public Iterator> sliding(int size, int step) { return Maps.sliding(this, this::createFromEntries, size, step); } @Override public Tuple2, TreeMap> span(Predicate> predicate) { return Maps.span(this, this::createFromEntries, predicate); } @Override public TreeMap tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty TreeMap"); } else { final Tuple2 min = entries.min().get(); return new TreeMap<>(entries.delete(min)); } } @Override public Option> tailOption() { return Maps.tailOption(this); } @Override public TreeMap take(int n) { return Maps.take(this, this::createFromEntries, n); } @Override public TreeMap takeRight(int n) { return Maps.takeRight(this, this::createFromEntries, n); } @Override public TreeMap takeUntil(Predicate> predicate) { return Maps.takeUntil(this, this::createFromEntries, predicate); } @Override public TreeMap takeWhile(Predicate> predicate) { return Maps.takeWhile(this, this::createFromEntries, predicate); } @Override public java.util.TreeMap toJavaMap() { return toJavaMap(() -> new java.util.TreeMap<>(comparator()), t -> t); } @Override public Seq values() { return map(Tuple2::_2); } // -- Object @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } @Override public String stringPrefix() { return "TreeMap"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } // -- private helpers private static TreeMap bimap(TreeMap map, EntryComparator entryComparator, Function keyMapper, Function valueMapper) { Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return createTreeMap(entryComparator, map.entries, entry -> entry.map(keyMapper, valueMapper)); } private static TreeMap flatMap(TreeMap map, EntryComparator entryComparator, BiFunction>> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return createTreeMap(entryComparator, map.entries.iterator().flatMap(entry -> mapper.apply(entry._1, entry._2))); } private static TreeMap map(TreeMap map, EntryComparator entryComparator, BiFunction> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return createTreeMap(entryComparator, map.entries, entry -> entry.map(mapper)); } // -- internal factory methods private static Collector, ArrayList>, TreeMap> createCollector(EntryComparator entryComparator) { final Supplier>> supplier = ArrayList::new; final BiConsumer>, Tuple2> accumulator = ArrayList::add; final BinaryOperator>> combiner = (left, right) -> { left.addAll(right); return left; }; final Function>, TreeMap> finisher = list -> createTreeMap(entryComparator, list); return Collector.of(supplier, accumulator, combiner, finisher); } private static Collector, TreeMap> createCollector( EntryComparator entryComparator, Function keyMapper, Function valueMapper) { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, TreeMap> finisher = arr -> createTreeMap(entryComparator, Iterator.ofAll(arr) .map(t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t)))); return Collector.of(supplier, accumulator, combiner, finisher); } @SuppressWarnings("unchecked") private static TreeMap createTreeMap(EntryComparator entryComparator, Iterable> entries) { Objects.requireNonNull(entries, "entries is null"); RedBlackTree> tree = RedBlackTree.empty(entryComparator); for (Tuple2 entry : (Iterable>) entries) { tree = tree.insert(entry); } return new TreeMap<>(tree); } private static TreeMap createTreeMap(EntryComparator entryComparator, Iterable> entries, Function, Tuple2> entryMapper) { RedBlackTree> tree = RedBlackTree.empty(entryComparator); for (Tuple2 entry : entries) { tree = tree.insert(entryMapper.apply(entry)); } return new TreeMap<>(tree); } @SuppressWarnings("unchecked") private static TreeMap createFromMap(EntryComparator entryComparator, java.util.Map map) { Objects.requireNonNull(map, "map is null"); RedBlackTree> tree = RedBlackTree.empty(entryComparator); for (java.util.Map.Entry entry : ((java.util.Map) map).entrySet()) { tree = tree.insert(Tuple.of(entry.getKey(), entry.getValue())); } return new TreeMap<>(tree); } @SuppressWarnings("unchecked") private static TreeMap createFromTuple(EntryComparator entryComparator, Tuple2 entry) { Objects.requireNonNull(entry, "entry is null"); return new TreeMap<>(RedBlackTree.of(entryComparator, (Tuple2) entry)); } @SuppressWarnings("unchecked") private static TreeMap createFromTuples(EntryComparator entryComparator, Tuple2... entries) { Objects.requireNonNull(entries, "entries is null"); RedBlackTree> tree = RedBlackTree.empty(entryComparator); for (Tuple2 entry : entries) { tree = tree.insert((Tuple2) entry); } return new TreeMap<>(tree); } @SafeVarargs private static TreeMap createFromMapEntries(EntryComparator entryComparator, java.util.Map.Entry... entries) { Objects.requireNonNull(entries, "entries is null"); RedBlackTree> tree = RedBlackTree.empty(entryComparator); for (java.util.Map.Entry entry : entries) { final K key = entry.getKey(); final V value = entry.getValue(); tree = tree.insert(Tuple.of(key, value)); } return new TreeMap<>(tree); } @SuppressWarnings("unchecked") private static TreeMap createFromPairs(EntryComparator entryComparator, Object... pairs) { RedBlackTree> tree = RedBlackTree.empty(entryComparator); for (int i = 0; i < pairs.length; i += 2) { final K key = (K) pairs[i]; final V value = (V) pairs[i + 1]; tree = tree.insert(Tuple.of(key, value)); } return new TreeMap<>(tree); } private TreeMap createFromEntries(Iterable> tuples) { return createTreeMap((EntryComparator) entries.comparator(), tuples); } private TreeMap emptyInstance() { return isEmpty() ? this : new TreeMap<>(entries.emptyInstance()); } @Override public Comparator comparator() { return ((EntryComparator) entries.comparator()).keyComparator(); } // -- internal types private interface EntryComparator extends Comparator>, Serializable { long serialVersionUID = 1L; static EntryComparator of(Comparator keyComparator) { Objects.requireNonNull(keyComparator, "keyComparator is null"); return new Specific<>(keyComparator); } static EntryComparator natural() { return Natural.instance(); } Comparator keyComparator(); // -- internal impls final class Specific implements EntryComparator { private static final long serialVersionUID = 1L; private final Comparator keyComparator; @SuppressWarnings("unchecked") Specific(Comparator keyComparator) { this.keyComparator = (Comparator) keyComparator; } @Override public int compare(Tuple2 e1, Tuple2 e2) { return keyComparator.compare(e1._1, e2._1); } @Override public Comparator keyComparator() { return keyComparator; } } final class Natural implements EntryComparator { private static final long serialVersionUID = 1L; private static final Natural INSTANCE = new Natural<>(); // hidden private Natural() { } @SuppressWarnings("unchecked") public static Natural instance() { return (Natural) INSTANCE; } @SuppressWarnings("unchecked") @Override public int compare(Tuple2 e1, Tuple2 e2) { final K key1 = e1._1; final K key2 = e2._1; return ((Comparable) key1).compareTo(key2); } @Override public Comparator keyComparator() { return Comparators.naturalComparator(); } @Override public boolean equals(Object obj) { return obj instanceof Natural; } @Override public int hashCode() { return 1; } /** * Instance control for object serialization. * * @return The singleton instance of NaturalEntryComparator. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/TreeMultimap.java000066400000000000000000001274021342074374400251710ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple2; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; /** * A {@link TreeMap}-based implementation of {@link Multimap} * * @param Key type * @param Value type * @author Ruslan Sennov */ public final class TreeMultimap extends AbstractMultimap> implements Serializable, SortedMultimap { private static final long serialVersionUID = 1L; public static Builder withSeq() { return new Builder<>(ContainerType.SEQ, List::empty); } public static Builder withSet() { return new Builder<>(ContainerType.SET, HashSet::empty); } public static > Builder withSortedSet() { return new Builder<>(ContainerType.SORTED_SET, TreeSet::empty); } public static Builder withSortedSet(Comparator comparator) { return new Builder<>(ContainerType.SORTED_SET, () -> TreeSet.empty(comparator)); } public static class Builder { private final ContainerType containerType; private final SerializableSupplier> emptyContainer; private Builder(ContainerType containerType, SerializableSupplier> emptyContainer) { this.containerType = containerType; this.emptyContainer = emptyContainer; } /** * Returns the empty TreeMultimap. The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @return A new empty TreeMultimap. */ public , V2 extends V> TreeMultimap empty() { return empty(Comparators.naturalComparator()); } /** * Returns the empty TreeMultimap using the given key comparator. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new empty TreeMultimap. */ public TreeMultimap empty(Comparator keyComparator) { Objects.requireNonNull(keyComparator, "keyComparator is null"); return new TreeMultimap<>(TreeMap.empty(keyComparator), containerType, emptyContainer); } /** * Creates a {@code TreeMultimap} of the given entries. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new TreeMultimap containing the given entries. */ public , V2 extends V> TreeMultimap ofEntries(Iterable> entries) { return ofEntries(Comparators.naturalComparator(), entries); } /** * Creates a {@code TreeMultimap} of the given entries. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entries Multimap entries * @return A new TreeMultimap containing the given entries. */ public TreeMultimap ofEntries(Comparator keyComparator, Iterable> entries) { Objects.requireNonNull(keyComparator, "keyComparator is null"); Objects.requireNonNull(entries, "entries is null"); TreeMultimap result = empty(keyComparator); for (Tuple2 entry : entries) { result = result.put(entry._1, entry._2); } return result; } /** * Creates a {@code TreeMultimap} of the given entries. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new TreeMultimap containing the given entries. */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final , V2 extends V> TreeMultimap ofEntries(Tuple2... entries) { return ofEntries(Comparators.naturalComparator(), entries); } /** * Creates a {@code TreeMultimap} of the given entries. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entries Multimap entries * @return A new TreeMultimap containing the given entries. */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final TreeMultimap ofEntries(Comparator keyComparator, Tuple2... entries) { Objects.requireNonNull(keyComparator, "keyComparator is null"); Objects.requireNonNull(entries, "entries is null"); TreeMultimap result = empty(keyComparator); for (Tuple2 entry : entries) { result = result.put(entry._1, entry._2); } return result; } /** * Creates a {@code TreeMultimap} of the given entries. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param entries Multimap entries * @return A new TreeMultimap containing the given entries. */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final , V2 extends V> TreeMultimap ofEntries(java.util.Map.Entry... entries) { return ofEntries(Comparators.naturalComparator(), entries); } /** * Creates a {@code TreeMultimap} of the given entries. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entries Multimap entries * @return A new TreeMultimap containing the given entries. */ @SuppressWarnings({ "unchecked", "varargs" }) @SafeVarargs public final TreeMultimap ofEntries(Comparator keyComparator, java.util.Map.Entry... entries) { Objects.requireNonNull(keyComparator, "keyComparator is null"); Objects.requireNonNull(entries, "entries is null"); TreeMultimap result = empty(keyComparator); for (java.util.Map.Entry entry : entries) { result = result.put(entry.getKey(), entry.getValue()); } return result; } /** * Returns a {@code TreeMultimap}, from a source java.util.Map. * * @param map A map * @param keyComparator The comparator used to sort the entries by their key. * @param The key type * @param The value type * @return A new Multimap containing the given map entries */ public TreeMultimap ofAll(Comparator keyComparator, java.util.Map map) { return Multimaps.ofJavaMap(empty(keyComparator), map); } /** * Returns a {@code TreeMultimap}, from a source java.util.Map. * * @param map A map * @param The key type * @param The value type * @return A new Multimap containing the given map entries */ public , V2 extends V> TreeMultimap ofAll(java.util.Map map) { return Multimaps.ofJavaMap(this.empty(), map); } /** * Returns a {@code TreeMultimap}, from entries mapped from stream. * * @param keyComparator The comparator used to sort the entries by their key. * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Multimap */ public TreeMultimap ofAll(Comparator keyComparator, java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Multimaps.ofStream(empty(keyComparator), stream, keyMapper, valueMapper); } /** * Returns a {@code TreeMultimap}, from entries mapped from stream. * * @param stream the source stream * @param keyMapper the key mapper * @param valueMapper the value mapper * @param The stream element type * @param The key type * @param The value type * @return A new Multimap */ public , V2 extends V> TreeMultimap ofAll(java.util.stream.Stream stream, Function keyMapper, Function valueMapper) { return Multimaps.ofStream(this.empty(), stream, keyMapper, valueMapper); } /** * Returns a {@code TreeMultimap}, from entries mapped from stream. * * @param keyComparator The comparator used to sort the entries by their key. * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new Multimap */ public TreeMultimap ofAll(Comparator keyComparator, java.util.stream.Stream stream, Function> entryMapper) { return Multimaps.ofStream(empty(keyComparator), stream, entryMapper); } /** * Returns a {@code TreeMultimap}, from entries mapped from stream. * * @param stream the source stream * @param entryMapper the entry mapper * @param The stream element type * @param The key type * @param The value type * @return A new Multimap */ public , V2 extends V> TreeMultimap ofAll(java.util.stream.Stream stream, Function> entryMapper) { return Multimaps.ofStream(empty(), stream, entryMapper); } /** * Returns a TreeMultimap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param n The number of elements in the TreeMultimap * @param f The Function computing element values * @return A TreeMultimap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ @SuppressWarnings("unchecked") public , V2 extends V> TreeMultimap tabulate(int n, Function> f) { return tabulate(Comparators.naturalComparator(), n, f); } /** * Returns a TreeMultimap containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key * @param n The number of elements in the TreeMultimap * @param f The Function computing element values * @return A TreeMultimap consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code keyComparator} or {@code f} are null */ @SuppressWarnings("unchecked") public TreeMultimap tabulate(Comparator keyComparator, int n, Function> f) { Objects.requireNonNull(keyComparator, "keyComparator is null"); Objects.requireNonNull(f, "f is null"); return ofEntries(keyComparator, Collections.tabulate(n, (Function>) f)); } /** * Returns a TreeMultimap containing {@code n} values supplied by a given Supplier {@code s}. * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param n The number of elements in the TreeMultimap * @param s The Supplier computing element values * @return A TreeMultimap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ @SuppressWarnings("unchecked") public , V2 extends V> TreeMultimap fill(int n, Supplier> s) { return fill(Comparators.naturalComparator(), n, s); } /** * Returns a TreeMultimap containing {@code n} values supplied by a given Supplier {@code s}. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key * @param n The number of elements in the TreeMultimap * @param s The Supplier computing element values * @return A TreeMultimap of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code keyComparator} or {@code s} are null */ @SuppressWarnings("unchecked") public TreeMultimap fill(Comparator keyComparator, int n, Supplier> s) { Objects.requireNonNull(keyComparator, "keyComparator is null"); Objects.requireNonNull(s, "s is null"); return ofEntries(keyComparator, Collections.fill(n, (Supplier>) s)); } /** * Returns a TreeMultimap containing {@code n} times the given {@code element} * The underlying key comparator is the natural comparator of K. * * @param The key type * @param The value type * @param n The number of elements in the TreeMultimap * @param element The element * @return A TreeMultimap of size {@code 1}, where each element contains {@code n} values of {@code element._2}. */ @SuppressWarnings("unchecked") public , V2 extends V> TreeMultimap fill(int n, Tuple2 element) { return fill(Comparators.naturalComparator(), n, element); } /** * Returns a TreeMultimap containing {@code n} times the given {@code element} * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key * @param n The number of elements in the TreeMultimap * @param element The element * @return A TreeMultimap of size {@code 1}, where each element contains {@code n} values of {@code element._2}. */ @SuppressWarnings("unchecked") public TreeMultimap fill(Comparator keyComparator, int n, Tuple2 element) { Objects.requireNonNull(keyComparator, "keyComparator is null"); return ofEntries(keyComparator, Collections.fillObject(n, element)); } /** * Creates a TreeMultimap of the given key-value pair. * * @param key A singleton map key. * @param value A singleton map value. * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K key, V2 value) { return of(Comparators.naturalComparator(), key, value); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2) { return of(Comparators.naturalComparator(), k1, v1, k2, v2); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3, k4, v4); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @return A new Multimap containing the given entries */ public , V2 extends V> TreeMultimap of(K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9, K k10, V2 v10) { return of(Comparators.naturalComparator(), k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param The key type * @param The value type * @param entry The key-value pair used to form a new TreeMultimap. * @return A new Multimap containing the given entry */ public , V2 extends V> TreeMultimap of(Tuple2 entry) { return of(Comparators.naturalComparator(), entry); } /** * Creates a TreeMultimap of the given key-value pair. * * @param keyComparator The comparator used to sort the entries by their key. * @param key A singleton map key. * @param value A singleton map value. * @param The key type * @param The value type * @return A new Multimap containing the given entry */ public TreeMultimap of(Comparator keyComparator, K key, V2 value) { final TreeMultimap e = empty(keyComparator); return e.put(key, value); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2) { return of(keyComparator, k1, v1).put(k2, v2); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3) { return of(keyComparator, k1, v1, k2, v2).put(k3, v3); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4) { return of(keyComparator, k1, v1, k2, v2, k3, v3).put(k4, v4); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5) { return of(keyComparator, k1, v1, k2, v2, k3, v3, k4, v4).put(k5, v5); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6) { return of(keyComparator, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5).put(k6, v6); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7) { return of(keyComparator, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6).put(k7, v7); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8) { return of(keyComparator, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7).put(k8, v8); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9) { return of(keyComparator, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8).put(k9, v9); } /** * Creates a TreeMultimap of the given list of key-value pairs. * * @param k1 a key for the map * @param v1 the value for k1 * @param k2 a key for the map * @param v2 the value for k2 * @param k3 a key for the map * @param v3 the value for k3 * @param k4 a key for the map * @param v4 the value for k4 * @param k5 a key for the map * @param v5 the value for k5 * @param k6 a key for the map * @param v6 the value for k6 * @param k7 a key for the map * @param v7 the value for k7 * @param k8 a key for the map * @param v8 the value for k8 * @param k9 a key for the map * @param v9 the value for k9 * @param k10 a key for the map * @param v10 the value for k10 * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A new Multimap containing the given entries */ public TreeMultimap of(Comparator keyComparator, K k1, V2 v1, K k2, V2 v2, K k3, V2 v3, K k4, V2 v4, K k5, V2 v5, K k6, V2 v6, K k7, V2 v7, K k8, V2 v8, K k9, V2 v9, K k10, V2 v10) { return of(keyComparator, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9).put(k10, v10); } /** * Returns a singleton {@code TreeMultimap}, i.e. a {@code TreeMultimap} of one entry using a specific key comparator. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @param entry A map entry. * @return A new TreeMultimap containing the given entry. */ public TreeMultimap of(Comparator keyComparator, Tuple2 entry) { final TreeMultimap e = empty(keyComparator); return e.put(entry._1, entry._2); } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a * {@link TreeMultimap}. *

* The natural comparator is used to compare TreeMultimap keys. * * @param The key type * @param The value type * @return A {@link TreeMultimap} Collector. */ public , V2 extends V> Collector, ArrayList>, TreeMultimap> collector() { return collector(Comparators.naturalComparator()); } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a * {@link TreeMultimap}. * * @param The key type * @param The value type * @param keyComparator The comparator used to sort the entries by their key. * @return A {@link TreeMultimap} Collector. */ public Collector, ArrayList>, TreeMultimap> collector(Comparator keyComparator) { Objects.requireNonNull(keyComparator, "keyComparator is null"); final Supplier>> supplier = ArrayList::new; final BiConsumer>, Tuple2> accumulator = ArrayList::add; final BinaryOperator>> combiner = (left, right) -> { left.addAll(right); return left; }; final Function>, TreeMultimap> finisher = list -> ofEntries(keyComparator, list); return Collector.of(supplier, accumulator, combiner, finisher); } } /** * Narrows a widened {@code HashMultimap} to {@code HashMultimap} * by performing a type safe-cast. This is eligible because immutable/read-only * collections are covariant. * * @param map A {@code Map}. * @param Key type * @param Value type * @return the given {@code multimap} instance as narrowed type {@code Multimap}. */ @SuppressWarnings("unchecked") public static TreeMultimap narrow(TreeMultimap map) { return (TreeMultimap) map; } private TreeMultimap(Map> back, ContainerType containerType, SerializableSupplier> emptyContainer) { super(back, containerType, emptyContainer); } @Override protected Map emptyMapSupplier() { return TreeMap.empty(Comparators.naturalComparator()); } @SuppressWarnings("unchecked") @Override protected TreeMultimap emptyInstance() { return new TreeMultimap<>(emptyMapSupplier(), getContainerType(), emptyContainer); } @Override protected TreeMultimap createFromMap(Map> back) { return new TreeMultimap<>(back, getContainerType(), emptyContainer); } @Override public Comparator comparator() { return ((SortedMap>) back).comparator(); } @Override public SortedSet keySet() { return ((SortedMap>) back).keySet(); } @Override public java.util.SortedMap> toJavaMap() { return toJavaMap(new java.util.TreeMap<>()); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/TreeSet.java000066400000000000000000001110761342074374400241340ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.*; import java.util.stream.Collector; /** * SortedSet implementation, backed by a Red/Black Tree. * * @param Component type * @author Daniel Dietrich */ // DEV-NOTE: it is not possible to create an EMPTY TreeSet without a Comparator type in scope public final class TreeSet implements SortedSet, Serializable { private static final long serialVersionUID = 1L; private final RedBlackTree tree; TreeSet(RedBlackTree tree) { this.tree = tree; } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link TreeSet}. *

* The natural comparator is used to compare TreeSet elements. * * @param Component type of the List. * @return A io.vavr.collection.List Collector. */ public static > Collector, TreeSet> collector() { return collector(Comparators.naturalComparator()); } /** * Returns a {@link java.util.stream.Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link TreeSet}. * * @param Component type of the List. * @param comparator An element comparator * @return A io.vavr.collection.List Collector. */ public static Collector, TreeSet> collector(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, TreeSet> finisher = list -> TreeSet.ofAll(comparator, list); return Collector.of(supplier, accumulator, combiner, finisher); } public static > TreeSet empty() { return empty(Comparators.naturalComparator()); } public static TreeSet empty(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return new TreeSet<>(RedBlackTree.empty(comparator)); } /** * Narrows a widened {@code TreeSet} to {@code TreeSet} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. *

* CAUTION: The underlying {@code Comparator} might fail! * * @param treeSet A {@code TreeSet}. * @param Component type of the {@code TreeSet}. * @return the given {@code treeSet} instance as narrowed type {@code TreeSet}. */ @SuppressWarnings("unchecked") public static TreeSet narrow(TreeSet treeSet) { return (TreeSet) treeSet; } public static > TreeSet of(T value) { return of(Comparators.naturalComparator(), value); } public static TreeSet of(Comparator comparator, T value) { Objects.requireNonNull(comparator, "comparator is null"); return new TreeSet<>(RedBlackTree.of(comparator, value)); } @SuppressWarnings("varargs") @SafeVarargs public static > TreeSet of(T... values) { return TreeSet. of(Comparators.naturalComparator(), values); } @SuppressWarnings("varargs") @SafeVarargs public static TreeSet of(Comparator comparator, T... values) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(values, "values is null"); return new TreeSet<>(RedBlackTree.of(comparator, values)); } /** * Returns a TreeSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the TreeSet * @param comparator The comparator used to sort the elements * @param n The number of elements in the TreeSet * @param f The Function computing element values * @return A TreeSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code comparator} or {@code f} are null */ public static TreeSet tabulate(Comparator comparator, int n, Function f) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f, TreeSet.empty(comparator), values -> of(comparator, values)); } /** * Returns a TreeSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * The underlying comparator is the natural comparator of T. * * @param Component type of the TreeSet * @param n The number of elements in the TreeSet * @param f The Function computing element values * @return A TreeSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static > TreeSet tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return tabulate(Comparators.naturalComparator(), n, f); } /** * Returns a TreeSet containing tuples returned by {@code n} calls to a given Supplier {@code s}. * * @param Component type of the TreeSet * @param comparator The comparator used to sort the elements * @param n The number of elements in the TreeSet * @param s The Supplier computing element values * @return A TreeSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code comparator} or {@code s} are null */ public static TreeSet fill(Comparator comparator, int n, Supplier s) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s, TreeSet.empty(comparator), values -> of(comparator, values)); } /** * Returns a TreeSet containing tuples returned by {@code n} calls to a given Supplier {@code s}. * The underlying comparator is the natural comparator of T. * * @param Component type of the TreeSet * @param n The number of elements in the TreeSet * @param s The Supplier computing element values * @return A TreeSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static > TreeSet fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return fill(Comparators.naturalComparator(), n, s); } public static > TreeSet ofAll(Iterable values) { return ofAll(Comparators.naturalComparator(), values); } @SuppressWarnings("unchecked") public static TreeSet ofAll(Comparator comparator, Iterable values) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(values, "values is null"); if (values instanceof TreeSet && ((TreeSet) values).comparator() == comparator) { return (TreeSet) values; } else { return values.iterator().hasNext() ? new TreeSet<>(RedBlackTree.ofAll(comparator, values)) : empty(comparator); } } public static > TreeSet ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return ofAll(Iterator.ofAll(javaStream.iterator())); } public static TreeSet ofAll(Comparator comparator, java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return ofAll(comparator, Iterator.ofAll(javaStream.iterator())); } /** * Creates a TreeSet from boolean values. * * @param elements boolean values * @return A new TreeSet of Boolean values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from byte values. * * @param elements byte values * @return A new TreeSet of Byte values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from char values. * * @param elements char values * @return A new TreeSet of Character values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from double values. * * @param elements double values * @return A new TreeSet of Double values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from float values. * * @param elements float values * @return A new TreeSet of Float values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from int values. * * @param elements int values * @return A new TreeSet of Integer values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from long values. * * @param elements long values * @return A new TreeSet of Long values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from short values. * * @param elements short values * @return A new TreeSet of Short values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * TreeSet.range(0, 0)  // = TreeSet()
     * TreeSet.range(2, 0)  // = TreeSet()
     * TreeSet.range(-2, 2) // = TreeSet(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ public static TreeSet range(int from, int toExclusive) { return TreeSet.ofAll(Iterator.range(from, toExclusive)); } public static TreeSet range(char from, char toExclusive) { return TreeSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeBy(1, 3, 1)  // = TreeSet(1, 2)
     * TreeSet.rangeBy(1, 4, 2)  // = TreeSet(1, 3)
     * TreeSet.rangeBy(4, 1, -2) // = TreeSet(4, 2)
     * TreeSet.rangeBy(4, 1, 2)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeBy(int from, int toExclusive, int step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static TreeSet rangeBy(char from, char toExclusive, int step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } @GwtIncompatible public static TreeSet rangeBy(double from, double toExclusive, double step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * TreeSet.range(0L, 0L)  // = TreeSet()
     * TreeSet.range(2L, 0L)  // = TreeSet()
     * TreeSet.range(-2L, 2L) // = TreeSet(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ public static TreeSet range(long from, long toExclusive) { return TreeSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeBy(1L, 3L, 1L)  // = TreeSet(1L, 2L)
     * TreeSet.rangeBy(1L, 4L, 2L)  // = TreeSet(1L, 3L)
     * TreeSet.rangeBy(4L, 1L, -2L) // = TreeSet(4L, 2L)
     * TreeSet.rangeBy(4L, 1L, 2L)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeBy(long from, long toExclusive, long step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * TreeSet.rangeClosed(0, 0)  // = TreeSet(0)
     * TreeSet.rangeClosed(2, 0)  // = TreeSet()
     * TreeSet.rangeClosed(-2, 2) // = TreeSet(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ public static TreeSet rangeClosed(int from, int toInclusive) { return TreeSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } public static TreeSet rangeClosed(char from, char toInclusive) { return TreeSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeClosedBy(1, 3, 1)  // = TreeSet(1, 2, 3)
     * TreeSet.rangeClosedBy(1, 4, 2)  // = TreeSet(1, 3)
     * TreeSet.rangeClosedBy(4, 1, -2) // = TreeSet(4, 2)
     * TreeSet.rangeClosedBy(4, 1, 2)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeClosedBy(int from, int toInclusive, int step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } public static TreeSet rangeClosedBy(char from, char toInclusive, int step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @GwtIncompatible public static TreeSet rangeClosedBy(double from, double toInclusive, double step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * TreeSet.rangeClosed(0L, 0L)  // = TreeSet(0L)
     * TreeSet.rangeClosed(2L, 0L)  // = TreeSet()
     * TreeSet.rangeClosed(-2L, 2L) // = TreeSet(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ public static TreeSet rangeClosed(long from, long toInclusive) { return TreeSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeClosedBy(1L, 3L, 1L)  // = TreeSet(1L, 2L, 3L)
     * TreeSet.rangeClosedBy(1L, 4L, 2L)  // = TreeSet(1L, 3L)
     * TreeSet.rangeClosedBy(4L, 1L, -2L) // = TreeSet(4L, 2L)
     * TreeSet.rangeClosedBy(4L, 1L, 2L)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeClosedBy(long from, long toInclusive, long step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @Override public TreeSet add(T element) { return contains(element) ? this : new TreeSet<>(tree.insert(element)); } @Override public TreeSet addAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); RedBlackTree that = tree; for (T element : elements) { if (!that.contains(element)) { that = that.insert(element); } } if (tree == that) { return this; } else { return new TreeSet<>(that); } } @Override public TreeSet collect(PartialFunction partialFunction) { return ofAll(Comparators.naturalComparator(), iterator(). collect(partialFunction)); } @Override public Comparator comparator() { return tree.comparator(); } @SuppressWarnings("unchecked") @Override public TreeSet diff(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { return this; } else if (elements instanceof TreeSet) { final TreeSet that = (TreeSet) elements; return that.isEmpty() ? this : new TreeSet<>(tree.difference(that.tree)); } else { return removeAll(elements); } } @Override public boolean contains(T element) { return tree.contains(element); } @Override public TreeSet distinct() { return this; } @Override public TreeSet distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return isEmpty() ? this : TreeSet.ofAll(tree.comparator(), iterator().distinctBy(comparator)); } @Override public TreeSet distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return isEmpty() ? this : TreeSet.ofAll(tree.comparator(), iterator().distinctBy(keyExtractor)); } @Override public TreeSet drop(int n) { if (n <= 0 || isEmpty()) { return this; } else if (n >= length()) { return empty(tree.comparator()); } else { return TreeSet.ofAll(tree.comparator(), iterator().drop(n)); } } @Override public TreeSet dropRight(int n) { if (n <= 0 || isEmpty()) { return this; } else if (n >= length()) { return empty(tree.comparator()); } else { return TreeSet.ofAll(tree.comparator(), iterator().dropRight(n)); } } @Override public TreeSet dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override public TreeSet dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = TreeSet.ofAll(tree.comparator(), iterator().dropWhile(predicate)); return (treeSet.length() == length()) ? this : treeSet; } @Override public TreeSet filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = TreeSet.ofAll(tree.comparator(), iterator().filter(predicate)); return (treeSet.length() == length()) ? this : treeSet; } @Override public TreeSet reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(predicate.negate()); } @Override public TreeSet flatMap(Comparator comparator, Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(comparator, iterator().flatMap(mapper)); } @Override public TreeSet flatMap(Function> mapper) { return flatMap(Comparators.naturalComparator(), mapper); } @Override public U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return iterator().foldRight(zero, f); } @Override public Map> groupBy(Function classifier) { return Collections.groupBy(this, classifier, elements -> ofAll(comparator(), elements)); } @Override public Iterator> grouped(int size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public T head() { if (isEmpty()) { throw new NoSuchElementException("head of empty TreeSet"); } else { return tree.min().get(); } } @Override public Option headOption() { return tree.min(); } @Override public TreeSet init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty TreeSet"); } else { return new TreeSet<>(tree.delete(tree.max().get())); } } @Override public Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @SuppressWarnings("unchecked") @Override public TreeSet intersect(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { return this; } else if (elements instanceof TreeSet) { final TreeSet that = (TreeSet) elements; return new TreeSet<>(tree.intersection(that.tree)); } else { return retainAll(elements); } } /** * A {@code TreeSet} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return tree.isEmpty(); } /** * A {@code TreeSet} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } @Override public Iterator iterator() { return tree.iterator(); } @Override public T last() { if (isEmpty()) { throw new NoSuchElementException("last of empty TreeSet"); } else { return tree.max().get(); } } @Override public int length() { return tree.size(); } @Override public TreeSet map(Comparator comparator, Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(comparator, iterator().map(mapper)); } @Override public TreeSet map(Function mapper) { return map(Comparators.naturalComparator(), mapper); } /** * Returns this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from iterable, using existing comparator. * * @param other An alternative {@code Traversable} * @return this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from iterable, using existing comparator. */ @Override public TreeSet orElse(Iterable other) { return isEmpty() ? ofAll(tree.comparator(), other) : this; } /** * Returns this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from result of evaluating supplier, using existing comparator. * * @param supplier An alternative {@code Traversable} * @return this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from result of evaluating supplier, using existing comparator. */ @Override public TreeSet orElse(Supplier> supplier) { return isEmpty() ? ofAll(tree.comparator(), supplier.get()) : this; } @Override public Tuple2, TreeSet> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterator().partition(predicate).map(i1 -> TreeSet.ofAll(tree.comparator(), i1), i2 -> TreeSet.ofAll(tree.comparator(), i2)); } @Override public TreeSet peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return this; } @Override public TreeSet remove(T element) { return new TreeSet<>(tree.delete(element)); } @Override public TreeSet removeAll(Iterable elements) { return Collections.removeAll(this, elements); } @Override public TreeSet replace(T currentElement, T newElement) { if (tree.contains(currentElement)) { return new TreeSet<>(tree.delete(currentElement).insert(newElement)); } else { return this; } } @Override public TreeSet replaceAll(T currentElement, T newElement) { // a set has only one occurrence return replace(currentElement, newElement); } @Override public TreeSet retainAll(Iterable elements) { return Collections.retainAll(this, elements); } @Override public TreeSet scan(T zero, BiFunction operation) { return Collections.scanLeft(this, zero, operation, iter -> TreeSet.ofAll(comparator(), iter)); } @Override public Set scanLeft(U zero, BiFunction operation) { if (zero instanceof Comparable) { final Comparator comparator = Comparators.naturalComparator(); return Collections.scanLeft(this, zero, operation, iter -> TreeSet.ofAll(comparator, iter)); } else { return Collections.scanLeft(this, zero, operation, HashSet::ofAll); } } @Override public Set scanRight(U zero, BiFunction operation) { if (zero instanceof Comparable) { final Comparator comparator = Comparators.naturalComparator(); return Collections.scanRight(this, zero, operation, iter -> TreeSet.ofAll(comparator, iter)); } else { return Collections.scanRight(this, zero, operation, HashSet::ofAll); } } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(seq -> TreeSet.ofAll(tree.comparator(), seq)); } @Override public Iterator> sliding(int size) { return sliding(size, 1); } @Override public Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(seq -> TreeSet.ofAll(tree.comparator(), seq)); } @Override public Tuple2, TreeSet> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterator().span(predicate).map(i1 -> TreeSet.ofAll(tree.comparator(), i1), i2 -> TreeSet.ofAll(tree.comparator(), i2)); } @Override public TreeSet tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty TreeSet"); } else { return new TreeSet<>(tree.delete(tree.min().get())); } } @Override public Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override public TreeSet take(int n) { if (n <= 0) { return empty(tree.comparator()); } else if (n >= length()) { return this; } else { return TreeSet.ofAll(tree.comparator(), iterator().take(n)); } } @Override public TreeSet takeRight(int n) { if (n <= 0) { return empty(tree.comparator()); } else if (n >= length()) { return this; } else { return TreeSet.ofAll(tree.comparator(), iterator().takeRight(n)); } } @Override public TreeSet takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = takeWhile(predicate.negate()); return (treeSet.length() == length()) ? this : treeSet; } @Override public TreeSet takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = TreeSet.ofAll(tree.comparator(), iterator().takeWhile(predicate)); return (treeSet.length() == length()) ? this : treeSet; } /** * Transforms this {@code TreeSet}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public java.util.TreeSet toJavaSet() { return toJavaSet(ignore -> new java.util.TreeSet<>(comparator())); } @SuppressWarnings("unchecked") @Override public TreeSet union(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof TreeSet) { final TreeSet that = (TreeSet) elements; return that.isEmpty() ? this : new TreeSet<>(tree.union(that.tree)); } else { return addAll(elements); } } @Override public Tuple2, TreeSet> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip(unzipper).map(i1 -> TreeSet.ofAll(Comparators.naturalComparator(), i1), i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2)); } @Override public Tuple3, TreeSet, TreeSet> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map( i1 -> TreeSet.ofAll(Comparators.naturalComparator(), i1), i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2), i3 -> TreeSet.ofAll(Comparators.naturalComparator(), i3)); } @Override public TreeSet> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public TreeSet zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWith(that, mapper)); } @Override public TreeSet> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); final Comparator> tuple2Comparator = Tuple2.comparator(tree.comparator(), Comparators.naturalComparator()); return TreeSet.ofAll(tuple2Comparator, iterator().zipAll(that, thisElem, thatElem)); } @Override public TreeSet> zipWithIndex() { final Comparator component1Comparator = tree.comparator(); final Comparator> tuple2Comparator = (t1, t2) -> component1Comparator.compare(t1._1, t2._1); return TreeSet.ofAll(tuple2Comparator, iterator().zipWithIndex()); } @Override public SortedSet zipWithIndex(BiFunction mapper) { return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWithIndex(mapper)); } // -- Object @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } @Override public String stringPrefix() { return "TreeSet"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/Vector.java000066400000000000000000001311571342074374400240250ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.collection.VectorModule.Combinations; import io.vavr.control.Option; import java.io.Serializable; import java.util.*; import java.util.function.*; import java.util.stream.Collector; import static io.vavr.collection.Collections.removeAll; import static io.vavr.collection.Collections.withSize; import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE; import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE; /** * Vector is the default Seq implementation that provides effectively constant time access to any element. * Many other operations (e.g. `tail`, `drop`, `slice`) are also effectively constant. * * The implementation is based on a `bit-mapped trie`, a very wide and shallow tree (i.e. depth ≤ 6). * * @param Component type of the Vector. * @author Ruslan Sennov, Pap Lőrinc */ public final class Vector implements IndexedSeq, Serializable { private static final long serialVersionUID = 1L; private static final Vector EMPTY = new Vector<>(BitMappedTrie.empty()); final BitMappedTrie trie; private Vector(BitMappedTrie trie) { this.trie = trie; } @SuppressWarnings("ObjectEquality") private Vector wrap(BitMappedTrie trie) { return (trie == this.trie) ? this : ofAll(trie); } private static Vector ofAll(BitMappedTrie trie) { return (trie.length() == 0) ? empty() : new Vector<>(trie); } /** * Returns the empty Vector. * * @param Component type. * @return The empty Vector. */ @SuppressWarnings("unchecked") public static Vector empty() { return (Vector) EMPTY; } /** * Returns a {@link Collector} which may be used in conjunction with * {@link java.util.stream.Stream#collect(Collector)} to obtain a {@link Vector}. * * @param Component type of the Vector. * @return A io.vavr.collection.List Collector. */ public static Collector, Vector> collector() { final Supplier> supplier = ArrayList::new; final BiConsumer, T> accumulator = ArrayList::add; final BinaryOperator> combiner = (left, right) -> { left.addAll(right); return left; }; final Function, Vector> finisher = Vector::ofAll; return Collector.of(supplier, accumulator, combiner, finisher); } /** * Narrows a widened {@code Vector} to {@code Vector} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param vector An {@code Vector}. * @param Component type of the {@code Vector}. * @return the given {@code vector} instance as narrowed type {@code Vector}. */ @SuppressWarnings("unchecked") public static Vector narrow(Vector vector) { return (Vector) vector; } /** * Returns a singleton {@code Vector}, i.e. a {@code Vector} of one element. * * @param element An element. * @param The component type * @return A new Vector instance containing the given element */ public static Vector of(T element) { return ofAll(Iterator.of(element)); } /** * Creates a Vector of the given elements. * * @param Component type of the Vector. * @param elements Zero or more elements. * @return A vector containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SafeVarargs @SuppressWarnings("varargs") public static Vector of(T... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Returns a Vector containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the Vector * @param n The number of elements in the Vector * @param f The Function computing element values * @return A Vector consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static Vector tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return io.vavr.collection.Collections.tabulate(n, f, empty(), Vector::of); } /** * Returns a Vector containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the Vector * @param n The number of elements in the Vector * @param s The Supplier computing element values * @return A Vector of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static Vector fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return io.vavr.collection.Collections.fill(n, s, empty(), Vector::of); } /** * Returns a Vector containing {@code n} times the given {@code element} * * @param Component type of the Vector * @param n The number of elements in the Vector * @param element The element * @return A Vector of size {@code n}, where each element is the given {@code element}. */ public static Vector fill(int n, T element) { return io.vavr.collection.Collections.fillObject(n, element, empty(), Vector::of); } /** * Creates a Vector of the given elements. *

* The resulting vector has the same iteration order as the given iterable of elements * if the iteration order of the elements is stable. * * @param Component type of the Vector. * @param iterable An Iterable of elements. * @return A vector containing the given elements in the same order. * @throws NullPointerException if {@code elements} is null */ @SuppressWarnings("unchecked") public static Vector ofAll(Iterable iterable) { Objects.requireNonNull(iterable, "iterable is null"); if (iterable instanceof Traversable && io.vavr.collection.Collections.isEmpty(iterable)){ return empty(); } if (iterable instanceof Vector) { return (Vector) iterable; } final Object[] values = withSize(iterable).toArray(); return ofAll(BitMappedTrie.ofAll(values)); } /** * Creates a Vector that contains the elements of the given {@link java.util.stream.Stream}. * * @param javaStream A {@link java.util.stream.Stream} * @param Component type of the Stream. * @return A Vector containing the given elements in the same order. */ public static Vector ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return ofAll(Iterator.ofAll(javaStream.iterator())); } /** * Creates a Vector from boolean values. * * @param elements boolean values * @return A new Vector of Boolean values * @throws NullPointerException if elements is null */ public static Vector ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Creates a Vector from byte values. * * @param elements byte values * @return A new Vector of Byte values * @throws NullPointerException if elements is null */ public static Vector ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Creates a Vector from char values. * * @param elements char values * @return A new Vector of Character values * @throws NullPointerException if elements is null */ public static Vector ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Creates a Vector from double values. * * @param elements double values * @return A new Vector of Double values * @throws NullPointerException if elements is null */ public static Vector ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Creates a Vector from float values. * * @param elements float values * @return A new Vector of Float values * @throws NullPointerException if elements is null */ public static Vector ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Creates a Vector from int values. * * @param elements int values * @return A new Vector of Integer values * @throws NullPointerException if elements is null */ public static Vector ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Creates a Vector from long values. * * @param elements long values * @return A new Vector of Long values * @throws NullPointerException if elements is null */ public static Vector ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } /** * Creates a Vector from short values. * * @param elements short values * @return A new Vector of Short values * @throws NullPointerException if elements is null */ public static Vector ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return ofAll(BitMappedTrie.ofAll(elements)); } public static Vector range(char from, char toExclusive) { return ofAll(ArrayType. asPrimitives(char.class, Iterator.range(from, toExclusive))); } public static Vector rangeBy(char from, char toExclusive, int step) { return ofAll(ArrayType. asPrimitives(char.class, Iterator.rangeBy(from, toExclusive, step))); } @GwtIncompatible public static Vector rangeBy(double from, double toExclusive, double step) { return ofAll(ArrayType. asPrimitives(double.class, Iterator.rangeBy(from, toExclusive, step))); } /** * Creates a Vector of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Vector.range(0, 0)  // = Vector()
     * Vector.range(2, 0)  // = Vector()
     * Vector.range(-2, 2) // = Vector(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ public static Vector range(int from, int toExclusive) { return ofAll(ArrayType. asPrimitives(int.class, Iterator.range(from, toExclusive))); } /** * Creates a Vector of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Vector.rangeBy(1, 3, 1)  // = Vector(1, 2)
     * Vector.rangeBy(1, 4, 2)  // = Vector(1, 3)
     * Vector.rangeBy(4, 1, -2) // = Vector(4, 2)
     * Vector.rangeBy(4, 1, 2)  // = Vector()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Vector rangeBy(int from, int toExclusive, int step) { return ofAll(ArrayType. asPrimitives(int.class, Iterator.rangeBy(from, toExclusive, step))); } /** * Creates a Vector of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * Vector.range(0L, 0L)  // = Vector()
     * Vector.range(2L, 0L)  // = Vector()
     * Vector.range(-2L, 2L) // = Vector(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ public static Vector range(long from, long toExclusive) { return ofAll(ArrayType. asPrimitives(long.class, Iterator.range(from, toExclusive))); } /** * Creates a Vector of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * Vector.rangeBy(1L, 3L, 1L)  // = Vector(1L, 2L)
     * Vector.rangeBy(1L, 4L, 2L)  // = Vector(1L, 3L)
     * Vector.rangeBy(4L, 1L, -2L) // = Vector(4L, 2L)
     * Vector.rangeBy(4L, 1L, 2L)  // = Vector()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Vector rangeBy(long from, long toExclusive, long step) { return ofAll(ArrayType. asPrimitives(long.class, Iterator.rangeBy(from, toExclusive, step))); } public static Vector rangeClosed(char from, char toInclusive) { return ofAll(ArrayType. asPrimitives(char.class, Iterator.rangeClosed(from, toInclusive))); } public static Vector rangeClosedBy(char from, char toInclusive, int step) { return ofAll(ArrayType. asPrimitives(char.class, Iterator.rangeClosedBy(from, toInclusive, step))); } @GwtIncompatible public static Vector rangeClosedBy(double from, double toInclusive, double step) { return ofAll(ArrayType. asPrimitives(double.class, Iterator.rangeClosedBy(from, toInclusive, step))); } /** * Creates a Vector of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Vector.rangeClosed(0, 0)  // = Vector(0)
     * Vector.rangeClosed(2, 0)  // = Vector()
     * Vector.rangeClosed(-2, 2) // = Vector(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ public static Vector rangeClosed(int from, int toInclusive) { return ofAll(ArrayType. asPrimitives(int.class, Iterator.rangeClosed(from, toInclusive))); } /** * Creates a Vector of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Vector.rangeClosedBy(1, 3, 1)  // = Vector(1, 2, 3)
     * Vector.rangeClosedBy(1, 4, 2)  // = Vector(1, 3)
     * Vector.rangeClosedBy(4, 1, -2) // = Vector(4, 2)
     * Vector.rangeClosedBy(4, 1, 2)  // = Vector()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Vector rangeClosedBy(int from, int toInclusive, int step) { return ofAll(ArrayType. asPrimitives(int.class, Iterator.rangeClosedBy(from, toInclusive, step))); } /** * Creates a Vector of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * Vector.rangeClosed(0L, 0L)  // = Vector(0L)
     * Vector.rangeClosed(2L, 0L)  // = Vector()
     * Vector.rangeClosed(-2L, 2L) // = Vector(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ public static Vector rangeClosed(long from, long toInclusive) { return ofAll(ArrayType. asPrimitives(long.class, Iterator.rangeClosed(from, toInclusive))); } /** * Creates a Vector of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * Vector.rangeClosedBy(1L, 3L, 1L)  // = Vector(1L, 2L, 3L)
     * Vector.rangeClosedBy(1L, 4L, 2L)  // = Vector(1L, 3L)
     * Vector.rangeClosedBy(4L, 1L, -2L) // = Vector(4L, 2L)
     * Vector.rangeClosedBy(4L, 1L, 2L)  // = Vector()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static Vector rangeClosedBy(long from, long toInclusive, long step) { return ofAll(ArrayType. asPrimitives(long.class, Iterator.rangeClosedBy(from, toInclusive, step))); } /** * Transposes the rows and columns of a {@link Vector} matrix. * * @param matrix element type * @param matrix to be transposed. * @return a transposed {@link Vector} matrix. * @throws IllegalArgumentException if the row lengths of {@code matrix} differ. *

* ex: {@code * Vector.transpose(Vector(Vector(1,2,3), Vector(4,5,6))) → Vector(Vector(1,4), Vector(2,5), Vector(3,6)) * } */ public static Vector> transpose(Vector> matrix) { return io.vavr.collection.Collections.transpose(matrix, Vector::ofAll, Vector::of); } /** * Creates a Vector from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Vector, otherwise {@code Some} {@code Tuple} * of the element for the next call and the value to add to the * resulting Vector. *

* Example: *

     * 
     * Vector.unfoldRight(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x, x-1)));
     * // Vector(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Vector with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Vector unfoldRight(T seed, Function>> f) { return Iterator.unfoldRight(seed, f).toVector(); } /** * Creates a Vector from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Vector, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting Vector and * the element for the next call. *

* Example: *

     * 
     * Vector.unfoldLeft(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds * @param type of unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Vector with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Vector unfoldLeft(T seed, Function>> f) { return Iterator.unfoldLeft(seed, f).toVector(); } /** * Creates a Vector from a seed value and a function. * The function takes the seed at first. * The function should return {@code None} when it's * done generating the Vector, otherwise {@code Some} {@code Tuple} * of the value to add to the resulting Vector and * the element for the next call. *

* Example: *

     * 
     * Vector.unfold(10, x -> x == 0
     *             ? Option.none()
     *             : Option.of(new Tuple2<>(x-1, x)));
     * // Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
     * 
     * 
* * @param type of seeds and unfolded values * @param seed the start value for the iteration * @param f the function to get the next step of the iteration * @return a Vector with the values built up by the iteration * @throws NullPointerException if {@code f} is null */ public static Vector unfold(T seed, Function>> f) { return Iterator.unfold(seed, f).toVector(); } @Override public Vector append(T element) { return appendAll(io.vavr.collection.List.of(element)); } @Override public Vector appendAll(Iterable iterable) { Objects.requireNonNull(iterable, "iterable is null"); if (isEmpty()) { return ofAll(iterable); } if (io.vavr.collection.Collections.isEmpty(iterable)){ return this; } return new Vector<>(trie.appendAll(iterable)); } @GwtIncompatible @Override public java.util.List asJava() { return JavaConverters.asJava(this, IMMUTABLE); } @GwtIncompatible @Override public Vector asJava(Consumer> action) { return Collections.asJava(this, action, IMMUTABLE); } @GwtIncompatible @Override public java.util.List asJavaMutable() { return JavaConverters.asJava(this, MUTABLE); } @GwtIncompatible @Override public Vector asJavaMutable(Consumer> action) { return Collections.asJava(this, action, MUTABLE); } @Override public Vector collect(PartialFunction partialFunction) { return ofAll(iterator(). collect(partialFunction)); } @Override public Vector> combinations() { return rangeClosed(0, length()).map(this::combinations).flatMap(Function.identity()); } @Override public Vector> combinations(int k) { return Combinations.apply(this, Math.max(k, 0)); } @Override public Iterator> crossProduct(int power) { return io.vavr.collection.Collections.crossProduct(empty(), this, power); } @Override public Vector distinct() { return distinctBy(Function.identity()); } @Override public Vector distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); final java.util.Set seen = new java.util.TreeSet<>(comparator); return filter(seen::add); } @Override public Vector distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); final java.util.Set seen = new java.util.HashSet<>(length()); return filter(t -> seen.add(keyExtractor.apply(t))); } @Override public Vector drop(int n) { return wrap(trie.drop(n)); } @Override public Vector dropUntil(Predicate predicate) { return io.vavr.collection.Collections.dropUntil(this, predicate); } @Override public Vector dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropUntil(predicate.negate()); } @Override public Vector dropRight(int n) { return take(length() - n); } @Override public Vector dropRightUntil(Predicate predicate) { return io.vavr.collection.Collections.dropRightUntil(this, predicate); } @Override public Vector dropRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropRightUntil(predicate.negate()); } @Override public Vector filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return wrap(trie.filter(predicate)); } @Override public Vector reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Collections.reject(this, predicate); } @Override public Vector flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); final Iterator results = iterator().flatMap(mapper); return ofAll(results); } @Override public T get(int index) { if (isValid(index)) { return trie.get(index); } else { throw new IndexOutOfBoundsException("get(" + index + ")"); } } private boolean isValid(int index) { return (index >= 0) && (index < length()); } @Override public T head() { if (nonEmpty()) { return get(0); } else { throw new NoSuchElementException("head of empty Vector"); } } @Override public Map> groupBy(Function classifier) { return io.vavr.collection.Collections.groupBy(this, classifier, Vector::ofAll); } @Override public Iterator> grouped(int size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public int indexOf(T element, int from) { for (int i = from; i < length(); i++) { if (Objects.equals(get(i), element)) { return i; } } return -1; } @Override public Vector init() { if (nonEmpty()) { return dropRight(1); } else { throw new UnsupportedOperationException("init of empty Vector"); } } @Override public Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override public Vector insert(int index, T element) { return insertAll(index, Iterator.of(element)); } @Override public Vector insertAll(int index, Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if ((index >= 0) && (index <= length())) { final Vector begin = take(index).appendAll(elements); final Vector end = drop(index); return (begin.size() > end.size()) ? begin.appendAll(end) : end.prependAll(begin); } else { throw new IndexOutOfBoundsException("insert(" + index + ", e) on Vector of length " + length()); } } @Override public Vector intersperse(T element) { return ofAll(iterator().intersperse(element)); } /** * A {@code Vector} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return length() == 0; } /** * A {@code Vector} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } @Override public Iterator iterator() { return isEmpty() ? Iterator.empty() : trie.iterator(); } @Override public int lastIndexOf(T element, int end) { for (int i = Math.min(end, length() - 1); i >= 0; i--) { if (Objects.equals(get(i), element)) { return i; } } return -1; } @Override public int length() { return trie.length(); } @Override public Vector map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return ofAll(trie.map(mapper)); } @Override public Vector orElse(Iterable other) { return isEmpty() ? ofAll(other) : this; } @Override public Vector orElse(Supplier> supplier) { return isEmpty() ? ofAll(supplier.get()) : this; } @Override public Vector padTo(int length, T element) { final int actualLength = length(); return (length <= actualLength) ? this : appendAll(Iterator.continually(element) .take(length - actualLength)); } @Override public Vector leftPadTo(int length, T element) { if (length <= length()) { return this; } else { final Iterator prefix = Iterator.continually(element).take(length - length()); return prependAll(prefix); } } @Override public Vector patch(int from, Iterable that, int replaced) { from = Math.max(from, 0); replaced = Math.max(replaced, 0); Vector result = take(from).appendAll(that); from += replaced; result = result.appendAll(drop(from)); return result; } @Override public Tuple2, Vector> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final ArrayList left = new ArrayList<>(), right = new ArrayList<>(); for (int i = 0; i < length(); i++) { final T t = get(i); (predicate.test(t) ? left : right).add(t); } return Tuple.of(ofAll(left), ofAll(right)); } @Override public Vector peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return this; } @Override public Vector> permutations() { if (isEmpty()) { return empty(); } else if (length() == 1) { return of(this); } else { Vector> results = empty(); for (T t : distinct()) { for (Vector ts : remove(t).permutations()) { results = results.append(of(t).appendAll(ts)); } } return results; } } @Override public Vector prepend(T element) { return prependAll(io.vavr.collection.List.of(element)); } @Override public Vector prependAll(Iterable iterable) { Objects.requireNonNull(iterable, "iterable is null"); if (isEmpty()) { return ofAll(iterable); } if (io.vavr.collection.Collections.isEmpty(iterable)){ return this; } return new Vector<>(trie.prependAll(iterable)); } @Override public Vector remove(T element) { for (int i = 0; i < length(); i++) { if (Objects.equals(get(i), element)) { return removeAt(i); } } return this; } @Override public Vector removeFirst(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = 0; i < length(); i++) { if (predicate.test(get(i))) { return removeAt(i); } } return this; } @Override public Vector removeLast(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = length() - 1; i >= 0; i--) { if (predicate.test(get(i))) { return removeAt(i); } } return this; } @Override public Vector removeAt(int index) { if (isValid(index)) { final Vector begin = take(index); final Vector end = drop(index + 1); return (begin.size() > end.size()) ? begin.appendAll(end) : end.prependAll(begin); } else { throw new IndexOutOfBoundsException("removeAt(" + index + ")"); } } @Override public Vector removeAll(T element) { return io.vavr.collection.Collections.removeAll(this, element); } @Override public Vector removeAll(Iterable elements) { return io.vavr.collection.Collections.removeAll(this, elements); } @Override @Deprecated public Vector removeAll(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return reject(predicate); } @Override public Vector replace(T currentElement, T newElement) { return indexOfOption(currentElement) .map(i -> update(i, newElement)) .getOrElse(this); } @Override public Vector replaceAll(T currentElement, T newElement) { Vector result = this; int index = 0; for (T value : iterator()) { if (Objects.equals(value, currentElement)) { result = result.update(index, newElement); } index++; } return result; } @Override public Vector retainAll(Iterable elements) { return io.vavr.collection.Collections.retainAll(this, elements); } @Override public Vector reverse() { return (length() <= 1) ? this : ofAll(reverseIterator()); } @Override public Vector rotateLeft(int n) { return Collections.rotateLeft(this, n); } @Override public Vector rotateRight(int n) { return Collections.rotateRight(this, n); } @Override public Vector scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override public Vector scanLeft(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanLeft(this, zero, operation, Iterator::toVector); } @Override public Vector scanRight(U zero, BiFunction operation) { return io.vavr.collection.Collections.scanRight(this, zero, operation, Iterator::toVector); } @Override public Vector shuffle() { return io.vavr.collection.Collections.shuffle(this, Vector::ofAll); } @Override public Vector slice(int beginIndex, int endIndex) { if ((beginIndex >= endIndex) || (beginIndex >= size()) || isEmpty()) { return empty(); } else if ((beginIndex <= 0) && (endIndex >= length())) { return this; } else { return take(endIndex).drop(beginIndex); } } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(Vector::ofAll); } @Override public Iterator> sliding(int size) { return sliding(size, 1); } @Override public Iterator> sliding(int size, int step) { return iterator().sliding(size, step).map(Vector::ofAll); } @Override public Vector sorted() { if (isEmpty()) { return this; } else { @SuppressWarnings("unchecked") final T[] list = (T[]) toJavaArray(); Arrays.sort(list); return Vector.of(list); } } @Override public Vector sorted(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return isEmpty() ? this : toJavaStream().sorted(comparator).collect(collector()); } @Override public > Vector sortBy(Function mapper) { return sortBy(U::compareTo, mapper); } @Override public Vector sortBy(Comparator comparator, Function mapper) { return Collections.sortBy(this, comparator, mapper, collector()); } @Override public Tuple2, Vector> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return Tuple.of(takeWhile(predicate), dropWhile(predicate)); } @Override public Tuple2, Vector> splitAt(int n) { return Tuple.of(take(n), drop(n)); } @Override public Tuple2, Vector> splitAt(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Vector init = takeWhile(predicate.negate()); return Tuple.of(init, drop(init.size())); } @Override public Tuple2, Vector> splitAtInclusive(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); for (int i = 0; i < length(); i++) { final T value = get(i); if (predicate.test(value)) { return (i == (length() - 1)) ? Tuple.of(this, empty()) : Tuple.of(take(i + 1), drop(i + 1)); } } return Tuple.of(this, empty()); } @Override public Vector subSequence(int beginIndex) { if ((beginIndex >= 0) && (beginIndex <= length())) { return drop(beginIndex); } else { throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ")"); } } @Override public Vector subSequence(int beginIndex, int endIndex) { Collections.subSequenceRangeCheck(beginIndex, endIndex, length()); return slice(beginIndex, endIndex); } @Override public Vector tail() { if (nonEmpty()) { return drop(1); } else { throw new UnsupportedOperationException("tail of empty Vector"); } } @Override public Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override public Vector take(int n) { return wrap(trie.take(n)); } @Override public Vector takeUntil(Predicate predicate) { return io.vavr.collection.Collections.takeUntil(this, predicate); } @Override public Vector takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeUntil(predicate.negate()); } @Override public Vector takeRight(int n) { return drop(length() - n); } @Override public Vector takeRightUntil(Predicate predicate) { return io.vavr.collection.Collections.takeRightUntil(this, predicate); } @Override public Vector takeRightWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeRightUntil(predicate.negate()); } /** * Transforms this {@code Vector}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public Tuple2, Vector> unzip(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); Vector xs = empty(); Vector ys = empty(); for (int i = 0; i < length(); i++) { final Tuple2 t = unzipper.apply(get(i)); xs = xs.append(t._1); ys = ys.append(t._2); } return Tuple.of(xs, ys); } @Override public Tuple3, Vector, Vector> unzip3(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); Vector xs = empty(); Vector ys = empty(); Vector zs = empty(); for (int i = 0; i < length(); i++) { final Tuple3 t = unzipper.apply(get(i)); xs = xs.append(t._1); ys = ys.append(t._2); zs = zs.append(t._3); } return Tuple.of(xs, ys, zs); } @Override public Vector update(int index, T element) { if (isValid(index)) { return wrap(trie.update(index, element)); } else { throw new IndexOutOfBoundsException("update(" + index + ")"); } } @Override public Vector update(int index, Function updater) { Objects.requireNonNull(updater, "updater is null"); return update(index, updater.apply(get(index))); } @Override public Vector> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public Vector zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return ofAll(iterator().zipWith(that, mapper)); } @Override public Vector> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public Vector> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public Vector zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return ofAll(iterator().zipWithIndex(mapper)); } private Object readResolve() { return isEmpty() ? EMPTY : this; } @Override public boolean equals(Object o) { return io.vavr.collection.Collections.equals(this, o); } @Override public int hashCode() { return io.vavr.collection.Collections.hashOrdered(this); } @Override public String stringPrefix() { return "Vector"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } } interface VectorModule { final class Combinations { static Vector> apply(Vector elements, int k) { return (k == 0) ? Vector.of(Vector.empty()) : elements.zipWithIndex().flatMap( t -> apply(elements.drop(t._2 + 1), (k - 1)).map((Vector c) -> c.prepend(t._1))); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/collection/package-info.java000066400000000000000000000113251342074374400251010ustar00rootroot00000000000000/** * Purely functional collections based on {@linkplain io.vavr.collection.Traversable}. * *

Performance Characteristics of Vavr Collections

* * * * * * * * * * * * * * * * * * * * * * * *
Time Complexity of Sequential Operations
 head()tail()get(int)update(int, T)prepend(T)append(T)
{@linkplain io.vavr.collection.Array}constlinearconstconstlinearlinear
{@linkplain io.vavr.collection.CharSeq}constlinearconstlinearlinearlinear
{@linkplain io.vavr.collection.Iterator}constconst
{@linkplain io.vavr.collection.List}constconstlinearlinearconstlinear
{@linkplain io.vavr.collection.Queue}constconstalinearlinearconstconst
{@linkplain io.vavr.collection.PriorityQueue}loglogloglog
{@linkplain io.vavr.collection.Stream}constconstlinearlinearconstlazyconstlazy
{@linkplain io.vavr.collection.Vector}consteffconsteffconsteffconsteffconsteffconsteff
*
* * * * * * * * * * * * * * * * * * * * *
Time Complexity of Map/Set Operations
 contains/Keyadd/putremovemin
{@linkplain io.vavr.collection.HashMap}consteffconsteffconstefflinear
{@linkplain io.vavr.collection.HashSet}consteffconsteffconstefflinear
{@linkplain io.vavr.collection.LinkedHashMap}constefflinearlinearlinear
{@linkplain io.vavr.collection.LinkedHashSet}constefflinearlinearlinear
{@linkplain io.vavr.collection.Tree}loglogloglog
{@linkplain io.vavr.collection.TreeMap}loglogloglog
{@linkplain io.vavr.collection.TreeSet}loglogloglog
*
*
    *
  • const · constant time
  • *
  • consta · amortized constant time, few operations may take longer
  • *
  • consteff · effectively constant time, depending on assumptions like distribution of hash keys
  • *
  • constlazy · lazy constant time, the operation is deferred
  • *
  • log · logarithmic time
  • *
  • linear · linear time
  • *
*/ package io.vavr.collection; vavr-0.10.0/vavr/src/main/java/io/vavr/collection/readme-contributing.md000066400000000000000000000024231342074374400261750ustar00rootroot00000000000000We need to follow some conventions to keep the collections consistent. There are two kinds of methods - **Accessors** access some of the elements of a collection, but return a result which is unrelated to the collection. Example of accessors are: head, foldLeft, toList. - **Transformers** access elements of a collection and produce a new collection of same type as a result. Example of transformers are: filter, map, groupBy, zip. Given this, our _transformers_ should return the most specific type, e.g. `HashMap.map(...)` should return `HashMap`. E.g. `zipWithIndex` is also a transformer. Our _accessors_ should return an interface instead to keep our library extensible for future enhancements. E.g. `HashMap.groupBy` should return `Map` because we may decide in future that returning another Map implementation than HashMap is more efficient. Returning now HashMap would break API on future changes. The only disadvantage is that Map's methods have generic parameters with wildcards, which reduces usability slightly. More specific, methods like `Seq.combinations()` or `Seq.crossProduct()` should return `Seq`. This applies also to subclasses of `Seq`. E.g. `CharSeq.combinations()` should also return `Seq`. Of course the concrete object returned remains `Vector` (for CharSeq). vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/000077500000000000000000000000001342074374400217375ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/Future.java000066400000000000000000001533601342074374400240640ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.concurrent; import io.vavr.*; import io.vavr.collection.Iterator; import io.vavr.collection.Seq; import io.vavr.collection.Stream; import io.vavr.control.Option; import io.vavr.control.Try; import io.vavr.collection.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.*; /** * A Future is a computation result that becomes available at some point. All operations provided are non-blocking. *

* The underlying {@code Executor} is used to execute asynchronous handlers, e.g. via * {@code onComplete(...)}. *

* A Future has two states: pending and completed. *

    *
  • Pending: The computation is ongoing. Only a pending future may be completed or cancelled.
  • *
  • Completed: The computation finished successfully with a result, failed with an exception or was cancelled.
  • *
* Callbacks may be registered on a Future at each point of time. These actions are performed as soon as the Future * is completed. An action which is registered on a completed Future is immediately performed. The action may run on * a separate Thread, depending on the underlying Executor. Actions which are registered on a cancelled * Future are performed with the failed result. * * @param Type of the computation result. * @author Daniel Dietrich */ @SuppressWarnings("deprecation") public interface Future extends Value { /** * The default executor service is {@link ForkJoinPool#commonPool()}. *

* Facts about ForkJoinPool: * *

    *
  • It is work-stealing, i.e. all threads in the pool attempt to find work submitted to the pool. * Especially this is efficient under heavy load (many small tasks), e.g. when tasks create subtasks * (recursive threads).
  • *
  • The ForkJoinPool is dynamic, it has a maximum of 32767 running threads. Compared to fixed-size pools, * this reduces the risk of dead-locks.
  • *
  • The commonPool() is shared across the entire VM. Keep this in mind when also using * {@link java.util.stream.Stream#parallel()} and {@link java.util.concurrent.CompletableFuture}}
  • *
* * The ForkJoinPool creates daemon threads but its run state is unaffected by attempts to shutdown() or shutdownNow(). * However, all running tasks are immediately terminated upon program System.exit(int). *

* IMPORTANT: Invoke {@code ForkJoinPool.commonPool().awaitQuiescence(long, TimeUnit)} before exit in order to * ensure that all running async tasks complete before program termination. * * @see ForkJoinPool#awaitQuiescence(long, TimeUnit) * @deprecated Will be removed in Vavr 1.0. Use {@link #DEFAULT_EXECUTOR instead}. */ @Deprecated // See https://zeroturnaround.com/rebellabs/fixedthreadpool-cachedthreadpool-or-forkjoinpool-picking-correct-java-executors-for-background-tasks ExecutorService DEFAULT_EXECUTOR_SERVICE = ForkJoinPool.commonPool(); /** * The default executor is {@link ForkJoinPool#commonPool()}. *

* Facts about ForkJoinPool: * *

    *
  • It is work-stealing, i.e. all threads in the pool attempt to find work submitted to the pool. * Especially this is efficient under heavy load (many small tasks), e.g. when tasks create subtasks * (recursive threads).
  • *
  • The ForkJoinPool is dynamic, it has a maximum of 32767 running threads. Compared to fixed-size pools, * this reduces the risk of dead-locks.
  • *
  • The commonPool() is shared across the entire VM. Keep this in mind when also using * {@link java.util.stream.Stream#parallel()} and {@link java.util.concurrent.CompletableFuture}}
  • *
* * The ForkJoinPool creates daemon threads but its run state is unaffected by attempts to shutdown() or shutdownNow(). * However, all running tasks are immediately terminated upon program System.exit(int). *

* IMPORTANT: Invoke {@code ForkJoinPool.commonPool().awaitQuiescence(long, TimeUnit)} before exit in order to * ensure that all running async tasks complete before program termination. * * @see ForkJoinPool#awaitQuiescence(long, TimeUnit) */ // See https://zeroturnaround.com/rebellabs/fixedthreadpool-cachedthreadpool-or-forkjoinpool-picking-correct-java-executors-for-background-tasks Executor DEFAULT_EXECUTOR = DEFAULT_EXECUTOR_SERVICE; /** * Creates a failed {@code Future} with the given {@code exception}, backed by the {@link #DEFAULT_EXECUTOR}. * * @param exception The reason why it failed. * @param The value type of a successful result. * @return A failed {@code Future}. * @throws NullPointerException if exception is null */ static Future failed(Throwable exception) { Objects.requireNonNull(exception, "exception is null"); return failed(DEFAULT_EXECUTOR, exception); } /** * Creates a failed {@code Future} with the given {@code exception}, backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param exception The reason why it failed. * @param The value type of a successful result. * @return A failed {@code Future}. * @throws NullPointerException if executor or exception is null */ static Future failed(Executor executor, Throwable exception) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(exception, "exception is null"); return FutureImpl.of(executor, Try.failure(exception)); } /** * Returns a {@code Future} that eventually succeeds with the first result of the given {@code Future}s which * matches the given {@code predicate}. If no result matches, the {@code Future} will contain {@link Option.None}. *

* The returned {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. * * @param futures An iterable of futures. * @param predicate A predicate that tests successful future results. * @param Result type of the futures. * @return A Future of an {@link Option} of the first result of the given {@code futures} that satisfies the given {@code predicate}. * @throws NullPointerException if one of the arguments is null */ static Future> find(Iterable> futures, Predicate predicate) { return find(DEFAULT_EXECUTOR, futures, predicate); } /** * Returns a {@code Future} that eventually succeeds with the first result of the given {@code Future}s which * matches the given {@code predicate}. If no result matches, the {@code Future} will contain {@link Option.None}. *

* The returned {@code Future} is backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param futures An iterable of futures. * @param predicate A predicate that tests successful future results. * @param Result type of the futures. * @return A Future of an {@link Option} of the first result of the given {@code futures} that satisfies the given {@code predicate}. * @throws NullPointerException if one of the arguments is null */ static Future> find(Executor executor, Iterable> futures, Predicate predicate) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(futures, "futures is null"); Objects.requireNonNull(predicate, "predicate is null"); final List> list = List.ofAll(futures); if (list.isEmpty()) { return successful(executor, Option.none()); } else { return run(executor, complete -> { final AtomicBoolean completed = new AtomicBoolean(false); final AtomicInteger count = new AtomicInteger(list.length()); list.forEach(future -> future.onComplete(result -> { synchronized (count) { // if the future is already completed we already found our result and there is nothing more to do. if (!completed.get()) { // when there are no more results we return a None final boolean wasLast = count.decrementAndGet() == 0; // when result is a Failure or predicate is false then we check in onFailure for finish result.filter(predicate) .onSuccess(value -> completed.set(complete.with(Try.success(Option.some(value))))) .onFailure(ignored -> { if (wasLast) { completed.set(complete.with(Try.success(Option.none()))); } }); } } })); }); } } /** * Returns a new {@code Future} that will contain the result of the first of the given futures that is completed, * backed by the {@link #DEFAULT_EXECUTOR}. * * @param futures An iterable of futures. * @param The result type. * @return A new {@code Future}. * @throws NullPointerException if futures is null */ static Future firstCompletedOf(Iterable> futures) { return firstCompletedOf(DEFAULT_EXECUTOR, futures); } /** * Returns a new {@code Future} that will contain the result of the first of the given futures that is completed, * backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param futures An iterable of futures. * @param The result type. * @return A new {@code Future}. * @throws NullPointerException if executor or futures is null */ static Future firstCompletedOf(Executor executor, Iterable> futures) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(futures, "futures is null"); return run(executor, complete -> futures.forEach(future -> future.onComplete(complete::with))); } /** * Returns a Future which contains the result of the fold of the given future values. If any future or the fold * fail, the result is a failure. *

* The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. * * @param futures An iterable of futures. * @param zero The zero element of the fold. * @param f The fold operation. * @param The result type of the given {@code Futures}. * @param The fold result type. * @return A new {@code Future} that will contain the fold result. * @throws NullPointerException if futures or f is null. */ static Future fold(Iterable> futures, U zero, BiFunction f) { return fold(DEFAULT_EXECUTOR, futures, zero, f); } /** * Returns a Future which contains the result of the fold of the given future values. If any future or the fold * fail, the result is a failure. *

* The resulting {@code Future} is backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param futures An iterable of futures. * @param zero The zero element of the fold. * @param f The fold operation. * @param The result type of the given {@code Futures}. * @param The fold result type. * @return A new {@code Future} that will contain the fold result. * @throws NullPointerException if executor, futures or f is null. */ static Future fold(Executor executor, Iterable> futures, U zero, BiFunction f) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(futures, "futures is null"); Objects.requireNonNull(f, "f is null"); if (!futures.iterator().hasNext()) { return successful(executor, zero); } else { return sequence(executor, futures).map(seq -> seq.foldLeft(zero, f)); } } /** * Creates a {@code Future} with the given java.util.concurrent.Future, backed by the {@link #DEFAULT_EXECUTOR} * * @param future A {@link java.util.concurrent.Future} * @param Result type of the Future * @return A new {@code Future} wrapping the result of the Java future * @throws NullPointerException if future is null */ static Future fromJavaFuture(java.util.concurrent.Future future) { Objects.requireNonNull(future, "future is null"); return of(DEFAULT_EXECUTOR, future::get); } /** * Creates a {@code Future} with the given java.util.concurrent.Future, backed by given {@link Executor} * * @param executor An {@link Executor}. * @param future A {@link java.util.concurrent.Future}. * @param Result type of the Future * @return A new {@code Future} wrapping the result of the Java future * @throws NullPointerException if executor or future is null */ static Future fromJavaFuture(Executor executor, java.util.concurrent.Future future) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(future, "future is null"); return of(executor, future::get); } /** * Creates a {@code Future} with the given {@link java.util.concurrent.CompletableFuture}, backed by the {@link #DEFAULT_EXECUTOR} * * @param future A {@link java.util.concurrent.CompletableFuture} * @param Result type of the Future * @return A new {@code Future} wrapping the result of the {@link java.util.concurrent.CompletableFuture} * @throws NullPointerException if future is null */ @GwtIncompatible static Future fromCompletableFuture(CompletableFuture future) { return fromCompletableFuture(DEFAULT_EXECUTOR, future); } /** * Creates a {@code Future} with the given {@link java.util.concurrent.CompletableFuture}, backed by given {@link Executor} * * @param executor An {@link Executor}. * @param future A {@link java.util.concurrent.CompletableFuture}. * @param Result type of the Future * @return A new {@code Future} wrapping the result of the {@link java.util.concurrent.CompletableFuture} * @throws NullPointerException if executor or future is null */ @GwtIncompatible static Future fromCompletableFuture(Executor executor, CompletableFuture future) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(future, "future is null"); if (future.isDone() || future.isCompletedExceptionally() || future.isCancelled()) { return fromTry(Try.of(future::get).recoverWith(error -> Try.failure(error.getCause()))); } else { return run(executor, complete -> future.handle((t, err) -> complete.with((err == null) ? Try.success(t) : Try.failure(err))) ); } } /** * Creates a {@code Future} from a {@link Try}, backed by the {@link #DEFAULT_EXECUTOR}. * * @param result The result. * @param The value type of a successful result. * @return A completed {@code Future} which contains either a {@code Success} or a {@code Failure}. * @throws NullPointerException if result is null */ static Future fromTry(Try result) { return fromTry(DEFAULT_EXECUTOR, result); } /** * Creates a {@code Future} from a {@link Try}, backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param result The result. * @param The value type of a successful result. * @return A completed {@code Future} which contains either a {@code Success} or a {@code Failure}. * @throws NullPointerException if executor or result is null */ static Future fromTry(Executor executor, Try result) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(result, "result is null"); return FutureImpl.of(executor, result); } /** * Narrows a widened {@code Future} to {@code Future} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param future A {@code Future}. * @param Component type of the {@code Future}. * @return the given {@code future} instance as narrowed type {@code Future}. */ @SuppressWarnings("unchecked") static Future narrow(Future future) { return (Future) future; } /** * Starts an asynchronous computation, backed by the {@link #DEFAULT_EXECUTOR}. * * @param computation A computation. * @param Type of the computation result. * @return A new Future instance * @throws NullPointerException if computation is null. * @deprecated Will be removed. Use {@code Future.of(supplier::get)} instead of {@code Future.ofSupplier(supplier)}. */ @Deprecated static Future ofSupplier(Supplier computation) { Objects.requireNonNull(computation, "computation is null"); return of(DEFAULT_EXECUTOR, computation::get); } /** * Starts an asynchronous computation, backed by the given {@link Executor}. * * @param executor An executor service. * @param computation A computation. * @param Type of the computation result. * @return A new Future instance * @throws NullPointerException if one of executor or computation is null. * @deprecated Will be removed. Use {@code Future.of(executor, supplier::get)} instead of {@code Future.ofSupplier(executor, supplier)}. */ @Deprecated static Future ofSupplier(Executor executor, Supplier computation) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(computation, "computation is null"); return of(executor, computation::get); } /** * Starts an asynchronous computation, backed by the {@link #DEFAULT_EXECUTOR}. * * @param computation A computation * @param Type of the computation result. * @return A new Future instance * @throws NullPointerException if computation is null. * @deprecated Will be removed. Use {@code Future.of(callable::call)} instead of {@code Future.ofCallable(callable)}. */ @Deprecated static Future ofCallable(Callable computation) { Objects.requireNonNull(computation, "computation is null"); return of(DEFAULT_EXECUTOR, computation::call); } /** * Starts an asynchronous computation, backed by the given {@link Executor}. * * @param executor An executor service. * @param computation A computation. * @param Type of the computation result. * @return A new Future instance * @throws NullPointerException if one of executor or computation is null. * @deprecated Will be removed. Use {@code Future.of(executor, callable::call)} instead of {@code Future.ofCallable(executor, callable)}. */ @Deprecated static Future ofCallable(Executor executor, Callable computation) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(computation, "computation is null"); return of(executor, computation::call); } /** * Starts an asynchronous computation, backed by the {@link #DEFAULT_EXECUTOR}. * * @param computation A computation * @return A new Future instance * @throws NullPointerException if computation is null. * @deprecated Will be removed. Use {@code Future.of(runnable::run)} instead of {@code Future.runRunnable(runnable)}. */ @Deprecated static Future runRunnable(Runnable computation) { Objects.requireNonNull(computation, "computation is null"); return run(DEFAULT_EXECUTOR, computation::run); } /** * Starts an asynchronous computation, backed by the given {@link Executor}. * * @param executor An executor service. * @param computation A computation. * @return A new Future instance * @throws NullPointerException if one of executor or computation is null. * @deprecated Will be removed. Use {@code Future.of(executor, runnable::run)} instead of {@code Future.runRunnable(executor, runnable)}. */ @Deprecated static Future runRunnable(Executor executor, Runnable computation) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(computation, "computation is null"); return run(executor, computation::run); } /** * Starts an asynchronous computation, backed by the {@link #DEFAULT_EXECUTOR}. * * @param computation A computation. * @param Type of the computation result. * @return A new Future instance. * @throws NullPointerException if computation is null. */ static Future of(CheckedFunction0 computation) { return of(DEFAULT_EXECUTOR, computation); } /** * Starts an asynchronous computation, backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param computation A computation. * @param Type of the computation result. * @return A new Future instance. * @throws NullPointerException if one of executor or computation is null. */ static Future of(Executor executor, CheckedFunction0 computation) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(computation, "computation is null"); return FutureImpl.async(executor, complete -> complete.with(Try.of(computation))); } /** * Creates a (possibly blocking) Future that runs the results of the given {@code computation} * using a completion handler: * *

{@code
     * CheckedConsumer>> computation = complete -> {
     *     // computation
     * };
     * }
* * The {@code computation} is executed synchronously. It requires to complete the returned Future. * A common use-case is to hand over the {@code complete} predicate to another {@code Future} * in order to prevent blocking: * *
{@code
     * Future greeting(Future nameFuture) {
     *     return Future.run(complete -> {
     *         nameFuture.onComplete(name -> complete.test("Hi " + name));
     *     });
     * }}
* * The computation receives a {@link Predicate}, named {@code complete} by convention, * that takes a result of type {@code Try} and returns a boolean that states whether the * Future was completed. *

* Future completion is an idempotent operation in the way that the first call of {@code complete} * will return true, successive calls will return false. * * @param task A computational task * @param Type of the result * @return a new {@code Future} instance * @deprecated Experimental API */ @Deprecated static Future run(Task task) { return run(DEFAULT_EXECUTOR, task); } /** * Creates a (possibly blocking) Future that runs the results of the given {@code computation} * using a completion handler: * *

{@code
     * CheckedConsumer>> computation = complete -> {
     *     // computation
     * };
     * }
* * The {@code computation} is executed synchronously. It requires to complete the returned Future. * A common use-case is to hand over the {@code complete} predicate to another {@code Future} * in order to prevent blocking: * *
{@code
     * Future greeting(Future nameFuture) {
     *     return Future.run(complete -> {
     *         nameFuture.onComplete(name -> complete.with("Hi " + name));
     *     });
     * }}
* * The computation receives a {@link Predicate}, named {@code complete} by convention, * that takes a result of type {@code Try} and returns a boolean that states whether the * Future was completed. *

* Future completion is an idempotent operation in the way that the first call of {@code complete} * will return true, successive calls will return false. * * @param executor An {@link Executor} that runs the given {@code computation} * @param task A computational task * @param Type of the result * @return a new {@code Future} instance * @deprecated Experimental API */ @Deprecated static Future run(Executor executor, Task task) { return FutureImpl.sync(executor, task); } /** * Returns a Future which contains the reduce result of the given future values. The zero is the result of the * first future that completes. If any future or the reduce operation fail, the result is a failure. *

* The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. * * @param futures An iterable of futures. * @param f The reduce operation. * @param The result type of the given {@code Futures}. * @return A new {@code Future} that will contain the reduce result. * @throws NullPointerException if executor, futures or f is null. */ static Future reduce(Iterable> futures, BiFunction f) { return reduce(DEFAULT_EXECUTOR, futures, f); } /** * Returns a Future which contains the reduce result of the given future values. The zero is the result of the * first future that completes. If any future or the reduce operation fail, the result is a failure. *

* The resulting {@code Future} is backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param futures An iterable of futures. * @param f The reduce operation. * @param The result type of the given {@code Futures}. * @return A new {@code Future} that will contain the reduce result. * @throws NullPointerException if executor, futures or f is null. */ static Future reduce(Executor executor, Iterable> futures, BiFunction f) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(futures, "futures is null"); Objects.requireNonNull(f, "f is null"); if (!futures.iterator().hasNext()) { throw new NoSuchElementException("Future.reduce on empty futures"); } else { return Future. sequence(futures).map(seq -> seq.reduceLeft(f)); } } /** * Runs an asynchronous computation, backed by the {@link #DEFAULT_EXECUTOR}. * * @param unit A unit of work. * @return A new Future instance which results in nothing. * @throws NullPointerException if unit is null. */ static Future run(CheckedRunnable unit) { return run(DEFAULT_EXECUTOR, unit); } /** * Starts an asynchronous computation, backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param unit A unit of work. * @return A new Future instance which results in nothing. * @throws NullPointerException if one of executor or unit is null. */ static Future run(Executor executor, CheckedRunnable unit) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(unit, "unit is null"); return of(executor, () -> { unit.run(); return null; }); } /** * Reduces many {@code Future}s into a single {@code Future} by transforming an * {@code Iterable>} into a {@code Future>}. *

* The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. * *

    *
  • * If all of the given Futures succeed, sequence() succeeds too: *
    // = Future(Success(Seq(1, 2)))
         * sequence(
         *     List.of(
         *         Future.of(() -> 1),
         *         Future.of(() -> 2)
         *     )
         * );
    *
  • *
  • * If a given Future fails, sequence() fails too: *
    // = Future(Failure(Error)))
         * sequence(
         *     List.of(
         *         Future.of(() -> 1),
         *         Future.of(() -> { throw new Error(); }
         *     )
         * );
    *
  • *
* * @param futures An {@code Iterable} of {@code Future}s. * @param Result type of the futures. * @return A {@code Future} of a {@link Seq} of results. * @throws NullPointerException if futures is null. */ static Future> sequence(Iterable> futures) { return sequence(DEFAULT_EXECUTOR, futures); } /** * Reduces many {@code Future}s into a single {@code Future} by transforming an * {@code Iterable>} into a {@code Future>}. *

* The resulting {@code Future} is backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param futures An {@code Iterable} of {@code Future}s. * @param Result type of the futures. * @return A {@code Future} of a {@link Seq} of results. * @throws NullPointerException if executor or futures is null. */ static Future> sequence(Executor executor, Iterable> futures) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(futures, "futures is null"); final Future> zero = successful(executor, Stream.empty()); final BiFunction>, Future, Future>> f = (result, future) -> result.flatMap(seq -> future.map(seq::append)); return Iterator.ofAll(futures).foldLeft(zero, f); } /** * Creates a succeeded {@code Future}, backed by the {@link #DEFAULT_EXECUTOR}. * * @param result The result. * @param The value type of a successful result. * @return A succeeded {@code Future}. */ static Future successful(T result) { return successful(DEFAULT_EXECUTOR, result); } /** * Creates a succeeded {@code Future}, backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param result The result. * @param The value type of a successful result. * @return A succeeded {@code Future}. * @throws NullPointerException if executor is null */ static Future successful(Executor executor, T result) { Objects.requireNonNull(executor, "executor is null"); return FutureImpl.of(executor, Try.success(result)); } @Override @GwtIncompatible default CompletableFuture toCompletableFuture() { final CompletableFuture future = new CompletableFuture<>(); onSuccess(future::complete); onFailure(future::completeExceptionally); return future; } /** * Maps the values of an iterable in parallel to a sequence of mapped values into a single {@code Future} by * transforming an {@code Iterable} into a {@code Future>}. *

* The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. * * @param values An {@code Iterable} of {@code Future}s. * @param mapper A mapper of values to Futures * @param The type of the given values. * @param The mapped value type. * @return A {@code Future} of a {@link Seq} of results. * @throws NullPointerException if values or f is null. */ static Future> traverse(Iterable values, Function> mapper) { return traverse(DEFAULT_EXECUTOR, values, mapper); } /** * Maps the values of an iterable in parallel to a sequence of mapped values into a single {@code Future} by * transforming an {@code Iterable} into a {@code Future>}. *

* The resulting {@code Future} is backed by the given {@link Executor}. * * @param executor An {@link Executor}. * @param values An {@code Iterable} of values. * @param mapper A mapper of values to Futures * @param The type of the given values. * @param The mapped value type. * @return A {@code Future} of a {@link Seq} of results. * @throws NullPointerException if executor, values or f is null. */ static Future> traverse(Executor executor, Iterable values, Function> mapper) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(values, "values is null"); Objects.requireNonNull(mapper, "mapper is null"); return sequence(executor, Iterator.ofAll(values).map(mapper)); } // -- non-static Future API /** * Support for chaining of callbacks that are guaranteed to be executed in a specific order. *

* An exception, which occurs when performing the given {@code action}, is not propagated to the outside. * In other words, subsequent actions are performed based on the value of the original Future. *

* Example: *


     * // prints Success(1)
     * Future.of(() -> 1)
     *       .andThen(t -> { throw new Error(""); })
     *       .andThen(System.out::println);
     * 
* * @param action A side-effecting action. * @return A new Future that contains this result and which is completed after the given action was performed. * @throws NullPointerException if action is null */ default Future andThen(Consumer> action) { Objects.requireNonNull(action, "action is null"); return run(executor(), complete -> onComplete(t -> { Try.run(() -> action.accept(t)); complete.with(t); }) ); } /** * Blocks the current Thread until this Future completed or returns immediately if this Future is already completed. *

* In the case the current thread was interrupted while waiting, a failed {@code Future} is returned containing * the corresponding {@link InterruptedException}. * * @return this {@code Future} instance */ Future await(); /** * Blocks the current Thread until this Future completed or returns immediately if this Future is already completed. *

* In the case the current thread was interrupted while waiting, a failed {@code Future} is returned containing * the corresponding {@link InterruptedException}. *

* If the deadline wasn't met, a failed {@code Future} is returned containing a {@link TimeoutException}. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return this {@code Future} instance * @throws IllegalArgumentException if {@code timeout} is negative * @throws NullPointerException if {@code unit} is null */ Future await(long timeout, TimeUnit unit); /** * Cancels the Future. A running thread is interrupted. *

* If the Future was successfully cancelled, the result is a {@code Failure(CancellationException)}. * * @return {@code false}, if this {@code Future} is already completed or could not be cancelled, otherwise {@code true}. * @throws SecurityException if the current thread cannot modify the Future's thread * @see Future#isCancelled() */ default boolean cancel() { return cancel(true); } /** * Cancels the Future. A pending Future may be interrupted, depending on the underlying {@code Executor}. *

* If the Future was successfully cancelled, the result is a {@code Failure(CancellationException)}. * * @param mayInterruptIfRunning {@code true} if a running thread should be interrupted, otherwise a running thread * is allowed to complete its computation. * @return {@code false}, if this {@code Future} is already completed or could not be cancelled, otherwise {@code true}. * @throws SecurityException if the current thread cannot modify the Future's thread * @see Future#isCancelled() * @see java.util.concurrent.Future#cancel(boolean) */ boolean cancel(boolean mayInterruptIfRunning); /** * Collects value that is in the domain of the given {@code partialFunction} by mapping the value to type {@code R}. * *

{@code
     * partialFunction.isDefinedAt(value)
     * }
* * If the element makes it through that filter, the mapped instance is wrapped in {@code Future} * *
{@code
     * R newValue = partialFunction.apply(value)
     * }
* * @param partialFunction A function that is not necessarily defined on value of this future. * @param The new value type * @return A new {@code Future} instance containing value of type {@code R} * @throws NullPointerException if {@code partialFunction} is null */ default Future collect(PartialFunction partialFunction) { Objects.requireNonNull(partialFunction, "partialFunction is null"); return run(executor(), complete -> onComplete(result -> complete.with(result.collect(partialFunction))) ); } /** * Returns the {@link Executor} used by this {@code Future}. * * @return The underlying {@code Executor}. */ default Executor executor() { return executorService(); } /** * This method is deprecated. *

* THE DEFAULT IMPLEMENTATION (obtained by one of the {@link Future} factory methods) MIGHT THROW AN * {@link UnsupportedOperationException} AT RUNTIME. * * @return (never) * @throws UnsupportedOperationException if the underlying {@link Executor} isn't an {@link ExecutorService}. * @deprecated Removed starting with Vavr 0.10.0, use {@link #executor()} instead. */ @Deprecated ExecutorService executorService() throws UnsupportedOperationException; /** * A projection that inverses the result of this Future. *

* If this Future succeeds, the failed projection returns a failure containing a {@code NoSuchElementException}. *

* If this Future fails, the failed projection returns a success containing the exception. * * @return A new Future which contains an exception at a point of time. */ default Future failed() { return run(executor(), complete -> onComplete(result -> { if (result.isFailure()) { complete.with(Try.success(result.getCause())); } else { complete.with(Try.failure(new NoSuchElementException("Future.failed completed without a throwable"))); } }) ); } /** * Returns a Future that returns the result of this Future, if it is a success. If the value of this Future is a * failure, the result of {@code that} Future is returned, if that is a success. If both Futures fail, the failure * of this Future is returned. *

* Example: *


     * Future<Integer> future = Future.of(() -> { throw new Error(); });
     * Future<Integer> that = Future.of(() -> 1);
     * Future<Integer> result = future.fallbackTo(that);
     *
     * // prints Some(1)
     * result.onComplete(System.out::println);
     * 
* * @param that A fallback future computation * @return A new Future * @throws NullPointerException if that is null */ default Future fallbackTo(Future that) { Objects.requireNonNull(that, "that is null"); return run(executor(), complete -> onComplete(t -> { if (t.isSuccess()) { complete.with(t); } else { that.onComplete(alt -> complete.with(alt.isSuccess() ? alt : t)); } }) ); } /** * Shortcut for {@code filterTry(predicate::test}. * * @param predicate A predicate * @return A new {@code Future} * @throws NullPointerException if {@code predicate} is null */ default Future filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filterTry(predicate::test); } /** * Filters the result of this {@code Future} by calling {@link Try#filterTry(CheckedPredicate)}. * * @param predicate A checked predicate * @return A new {@code Future} * @throws NullPointerException if {@code predicate} is null */ default Future filterTry(CheckedPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return run(executor(), complete -> onComplete(result -> complete.with(result.filterTry(predicate)))); } /** * Returns the underlying exception of this Future, syntactic sugar for {@code future.getValue().map(Try::getCause)}. * * @return None if the Future is not completed yet. Returns Some(Throwable) if the Future was completed with a failure. * @throws UnsupportedOperationException if the Future was successfully completed with a value */ default Option getCause() { return getValue().map(Try::getCause); } /** * Returns the value of the Future. * * @return {@code None}, if the Future is not yet completed or was cancelled, otherwise {@code Some(Try)}. */ Option> getValue(); /** * Checks if this Future is cancelled, i.e. the thread was forced to stop before completion. * * @return true, if the computation was cancelled, false otherwise */ boolean isCancelled(); /** * Checks if this Future is completed, i.e. has a value. * * @return true, if the computation successfully finished, failed or was cancelled, false otherwise. */ boolean isCompleted(); /** * Checks if this Future completed with a success. * * @return true, if this Future completed and is a Success, false otherwise. */ default boolean isSuccess() { return isCompleted() && getValue().get().isSuccess(); } /** * Checks if this Future completed with a failure. * * @return true, if this Future completed and is a Failure, false otherwise. */ default boolean isFailure() { return isCompleted() && getValue().get().isFailure(); } /** * Performs the action once the Future is complete. * * @param action An action to be performed when this future is complete. * @return this Future * @throws NullPointerException if {@code action} is null. */ Future onComplete(Consumer> action); /** * Performs the action once the Future is complete and the result is a {@link Try.Failure}. Please note that the * future is also a failure when it was cancelled. * * @param action An action to be performed when this future failed. * @return this Future * @throws NullPointerException if {@code action} is null. */ default Future onFailure(Consumer action) { Objects.requireNonNull(action, "action is null"); return onComplete(result -> result.onFailure(action)); } /** * Performs the action once the Future is complete and the result is a {@link Try.Success}. * * @param action An action to be performed when this future succeeded. * @return this Future * @throws NullPointerException if {@code action} is null. */ default Future onSuccess(Consumer action) { Objects.requireNonNull(action, "action is null"); return onComplete(result -> result.onSuccess(action)); } /** * Handles a failure of this Future by returning another result. *

* Example: *


     * // = "oh!"
     * Future.of(() -> new Error("oh!")).recover(Throwable::getMessage);
     * 
* * @param f A function which takes the exception of a failure and returns a new value. * @return A new Future. * @throws NullPointerException if {@code f} is null */ default Future recover(Function f) { Objects.requireNonNull(f, "f is null"); return transformValue(t -> t.recover(f)); } /** * Handles a failure of this Future by returning the result of another Future. *

* Example: *


     * // = "oh!"
     * Future.of(() -> { throw new Error("oh!"); }).recoverWith(x -> Future.of(x::getMessage));
     * 
* * @param f A function which takes the exception of a failure and returns a new future. * @return A new Future. * @throws NullPointerException if {@code f} is null */ default Future recoverWith(Function> f) { Objects.requireNonNull(f, "f is null"); return run(executor(), complete -> onComplete(t -> { if (t.isFailure()) { Try.run(() -> f.apply(t.getCause()).onComplete(complete::with)) .onFailure(x -> complete.with(Try.failure(x))); } else { complete.with(t); } }) ); } /** * Transforms this {@code Future}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } /** * Transforms the value of this {@code Future}, whether it is a success or a failure. * * @param f A transformation * @param Generic type of transformation {@code Try} result * @return A {@code Future} of type {@code U} * @throws NullPointerException if {@code f} is null */ default Future transformValue(Function, ? extends Try> f) { Objects.requireNonNull(f, "f is null"); return run(executor(), complete -> onComplete(t -> Try.run(() -> complete.with(f.apply(t))) .onFailure(x -> complete.with(Try.failure(x))) ) ); } /** * Returns a tuple of this and that Future result. *

* If this Future failed the result contains this failure. Otherwise the result contains that failure or * a tuple of both successful Future results. * * @param that Another Future * @param Result type of {@code that} * @return A new Future that returns both Future results. * @throws NullPointerException if {@code that} is null */ default Future> zip(Future that) { Objects.requireNonNull(that, "that is null"); return zipWith(that, Tuple::of); } /** * Returns a this and that Future result combined using a given combinator function. *

* If this Future failed the result contains this failure. Otherwise the result contains that failure or * a combination of both successful Future results. * * @param that Another Future * @param combinator The combinator function * @param Result type of {@code that} * @param Result type of {@code f} * @return A new Future that returns both Future results. * @throws NullPointerException if {@code that} is null */ @SuppressWarnings({"deprecation", "unchecked"}) default Future zipWith(Future that, BiFunction combinator) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(combinator, "combinator is null"); return run(executor(), complete -> onComplete(res1 -> { if (res1.isFailure()) { complete.with((Try.Failure) res1); } else { that.onComplete(res2 -> { final Try result = res1.flatMap(t -> res2.map(u -> combinator.apply(t, u))); complete.with(result); }); } }) ); } // -- Value & Monad implementation default Future flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return flatMapTry(mapper::apply); } default Future flatMapTry(CheckedFunction1> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return run(executor(), complete -> onComplete(result -> result.mapTry(mapper) .onSuccess(future -> future.onComplete(complete::with)) .onFailure(x -> complete.with(Try.failure(x))) ) ); } /** * Performs the given {@code action} asynchronously hence this Future result becomes available. * The {@code action} is not performed, if the result is a failure. * * @param action A {@code Consumer} */ @Override default void forEach(Consumer action) { Objects.requireNonNull(action, "action is null"); onComplete(result -> result.forEach(action)); } /** * Gets the value if the computation result is a {@code Success} or throws if it was a {@code Failure}. * Waits for the result if necessary by blocking the current thread. *

* IMPORTANT! If the computation result is a {@link Try.Failure}, the underlying {@code cause} of type {@link Throwable} is thrown. * * @return The value of this {@code Future}. */ @Override default T get() { return await().getValue().get().get(); } /** * A {@code Futures}'s value is computed asynchronously. * * @return true */ @Override default boolean isAsync() { return true; } /** * Checks, if this future has a value. * * @return true, if this future succeeded with a value, false otherwise. */ @Override default boolean isEmpty() { return await().getValue().get().isEmpty(); } /** * A {@code Future}'s value is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } /** * A {@code Future} is single-valued. * * @return {@code true} */ @Override default boolean isSingleValued() { return true; } @Override default Iterator iterator() { return isEmpty() ? Iterator.empty() : Iterator.of(get()); } @Override default Future map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return transformValue(t -> t.map(mapper)); } default Future mapTry(CheckedFunction1 mapper) { Objects.requireNonNull(mapper, "mapper is null"); return transformValue(t -> t.mapTry(mapper)); } default Future orElse(Future other) { Objects.requireNonNull(other, "other is null"); return run(executor(), complete -> onComplete(result -> { if (result.isSuccess()) { complete.with(result); } else { other.onComplete(complete::with); } }) ); } default Future orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return run(executor(), complete -> onComplete(result -> { if (result.isSuccess()) { complete.with(result); } else { supplier.get().onComplete(complete::with); } }) ); } @Override default Future peek(Consumer action) { Objects.requireNonNull(action, "action is null"); onSuccess(action); return this; } @Override default String stringPrefix() { return "Future"; } } vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/FutureImpl.java000066400000000000000000000343021342074374400247000ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.concurrent; import io.vavr.collection.Queue; import io.vavr.control.Option; import io.vavr.control.Try; import java.util.Objects; import java.util.concurrent.*; import java.util.concurrent.locks.LockSupport; import java.util.function.Consumer; /** * INTERNAL API - This class is subject to change. * * @param Result of the computation. * @author Daniel Dietrich */ @SuppressWarnings("deprecation") final class FutureImpl implements Future { /** * Used to start new threads. */ private final Executor executor; /** * Used to synchronize state changes. */ private final Object lock = new Object(); /** * Indicates if this Future is cancelled * * GuardedBy("lock") */ private volatile boolean cancelled; /** * Once the Future is completed, the value is defined. * * GuardedBy("lock") */ private volatile Option> value; /** * The queue of actions is filled when calling onComplete() before the Future is completed or cancelled. * Otherwise actions = null. * * GuardedBy("lock") */ private Queue>> actions; /** * The queue of waiters is filled when calling await() before the Future is completed or cancelled. * Otherwise waiters = null. * * GuardedBy("lock") */ private Queue waiters; /** * The Thread which runs the computation. * * GuardedBy("lock") */ private Thread thread; // single constructor private FutureImpl(Executor executor, Option> value, Queue>> actions, Queue waiters, Computation computation) { this.executor = executor; synchronized (lock) { this.cancelled = false; this.value = value; this.actions = actions; this.waiters = waiters; try { computation.execute(this::tryComplete, this::updateThread); } catch (Throwable x) { tryComplete(Try.failure(x)); } } } /** * Creates a {@code FutureImpl} that needs to be automatically completed by calling {@link #tryComplete(Try)}. * * @param executor An {@link Executor} to run and control the computation and to perform the actions. * @param value type of the Future * @return a new {@code FutureImpl} instance */ static FutureImpl of(Executor executor) { return new FutureImpl<>(executor, Option.none(), Queue.empty(), Queue.empty(), (complete, updateThread) -> {}); } /** * Creates a {@code FutureImpl} that is immediately completed with the given value. No task will be started. * * @param executor An {@link Executor} to run and control the computation and to perform the actions. * @param value the result of this Future * @param value type of the Future * @return a new {@code FutureImpl} instance */ static FutureImpl of(Executor executor, Try value) { return new FutureImpl<>(executor, Option.some(Try.narrow(value)), null, null, (complete, updateThread) -> {}); } /** * Creates a {@code FutureImpl} that is eventually completed. * The given {@code computation} is synchronously executed, no thread is started. * * @param executor An {@link Executor} to run and control the computation and to perform the actions. * @param task A non-blocking computation * @param value type of the Future * @return a new {@code FutureImpl} instance */ static FutureImpl sync(Executor executor, Task task) { return new FutureImpl<>(executor, Option.none(), Queue.empty(), Queue.empty(), (complete, updateThread) -> task.run(complete::with) ); } /** * Creates a {@code FutureImpl} that is eventually completed. * The given {@code computation} is asynchronously executed, a new thread is started. * * @param executor An {@link Executor} to run and control the computation and to perform the actions. * @param task A (possibly blocking) computation * @param value type of the Future * @return a new {@code FutureImpl} instance */ static FutureImpl async(Executor executor, Task task) { // In a single-threaded context this Future may already have been completed during initialization. return new FutureImpl<>(executor, Option.none(), Queue.empty(), Queue.empty(), (complete, updateThread) -> executor.execute(() -> { updateThread.run(); try { task.run(complete::with); } catch (Throwable x) { complete.with(Try.failure(x)); } }) ); } @Override public Future await() { if (!isCompleted()) { _await(-1L, -1L, null); } return this; } @Override public Future await(long timeout, TimeUnit unit) { final long now = System.nanoTime(); Objects.requireNonNull(unit, "unit is null"); if (timeout < 0) { throw new IllegalArgumentException("negative timeout"); } if (!isCompleted()) { _await(now, timeout, unit); } return this; } /** * Blocks the current thread. *

* If timeout = 0 then {@code LockSupport.park()} is called (start, timeout and unit are not used), * otherwise {@code LockSupport.park(timeout, unit}} is called. *

* If a timeout > -1 is specified and the deadline is not met, this Future fails with a {@link TimeoutException}. *

* If this Thread was interrupted, this Future fails with a {@link InterruptedException}. * * @param start the start time in nanos, based on {@linkplain System#nanoTime()} * @param timeout a timeout in the given {@code unit} of time * @param unit a time unit */ private void _await(long start, long timeout, TimeUnit unit) { try { ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() { final long duration = (unit == null) ? -1 : unit.toNanos(timeout); final Thread waitingThread = Thread.currentThread(); boolean threadEnqueued = false; /** * Parks the Future's thread. *

* LockSupport.park() / parkNanos() may return when the Thread is permitted to be scheduled again. * If so, the Future's tryComplete() method wasn't called yet. In that case the block() method is * called again. The remaining timeout is recalculated accordingly. * * @return true, if this Future is completed, false otherwise */ @Override public boolean block() { try { if (!threadEnqueued) { synchronized (lock) { waiters = waiters.enqueue(waitingThread); } threadEnqueued = true; } if (timeout > -1) { final long delta = System.nanoTime() - start; final long remainder = duration - delta; LockSupport.parkNanos(remainder); // returns immediately if remainder <= 0 if (System.nanoTime() - start > duration) { tryComplete(Try.failure(new TimeoutException("timeout after " + timeout + " " + unit.name().toLowerCase()))); } } else { LockSupport.park(); } if (waitingThread.isInterrupted()) { tryComplete(Try.failure(new ExecutionException(new InterruptedException()))); } } catch (Throwable x) { tryComplete(Try.failure(x)); } return isCompleted(); } @Override public boolean isReleasable() { return isCompleted(); } }); } catch (Throwable x) { tryComplete(Try.failure(x)); } } @Override public boolean cancel(boolean mayInterruptIfRunning) { if (!isCompleted()) { synchronized (lock) { if (!isCompleted()) { if (mayInterruptIfRunning && this.thread != null) { this.thread.interrupt(); } this.cancelled = tryComplete(Try.failure(new CancellationException())); return this.cancelled; } } } return false; } private void updateThread() { // cancellation may have been initiated by a different thread before this.thread is set by the worker thread if (!isCompleted()) { synchronized (lock) { if (!isCompleted()) { this.thread = Thread.currentThread(); try { this.thread.setUncaughtExceptionHandler((thread, x) -> handleUncaughtException(x)); } catch (SecurityException x) { // we are not allowed to set the uncaught exception handler of the worker thread ¯\_(ツ)_/¯ } } } } } @Override public Executor executor() { return executor; } @Deprecated @Override public ExecutorService executorService() { if (executor instanceof ExecutorService) { return (ExecutorService) executor; } else { throw new UnsupportedOperationException("Removed starting with Vavr 0.10.0, use executor() instead."); } } @Override public Option> getValue() { return value; } @Override public boolean isCancelled() { return cancelled; } @Override public boolean isCompleted() { return value.isDefined(); } @SuppressWarnings("unchecked") @Override public Future onComplete(Consumer> action) { Objects.requireNonNull(action, "action is null"); if (isCompleted()) { perform(action); } else { synchronized (lock) { if (isCompleted()) { perform(action); } else { actions = actions.enqueue((Consumer>) action); } } } return this; } // This class is MUTABLE and therefore CANNOT CHANGE DEFAULT equals() and hashCode() behavior. // See http://stackoverflow.com/questions/4718009/mutable-objects-and-hashcode @Override public String toString() { final Option> value = this.value; final String s = (value == null || value.isEmpty()) ? "?" : value.get().toString(); return stringPrefix() + "(" + s + ")"; } /** * INTERNAL METHOD, SHOULD BE USED BY THE CONSTRUCTOR, ONLY. *

* Completes this Future with a value and performs all actions. *

* This method is idempotent. I.e. it does nothing, if this Future is already completed. * * @param value A Success containing a result or a Failure containing an Exception. * @throws IllegalStateException if the Future is already completed or cancelled. * @throws NullPointerException if the given {@code value} is null. */ boolean tryComplete(Try value) { Objects.requireNonNull(value, "value is null"); if (isCompleted()) { return false; } else { final Queue>> actions; final Queue waiters; // it is essential to make the completed state public *before* performing the actions synchronized (lock) { if (isCompleted()) { actions = null; waiters = null; } else { actions = this.actions; waiters = this.waiters; this.value = Option.some(Try.narrow(value)); this.actions = null; this.waiters = null; this.thread = null; } } if (waiters != null) { waiters.forEach(this::unlock); } if (actions != null) { actions.forEach(this::perform); return true; } else { return false; } } } private void perform(Consumer> action) { try { executor.execute(() -> action.accept(value.get())); } catch (Throwable x) { handleUncaughtException(x); } } private void unlock(Thread waiter) { try { LockSupport.unpark(waiter); } catch (Throwable x) { handleUncaughtException(x); } } private void handleUncaughtException(Throwable x) { tryComplete(Try.failure(x)); } private interface Computation { void execute(Task.Complete complete, Runnable updateThread) throws Throwable; } } vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/GwtIncompatible.java000066400000000000000000000017441342074374400257000ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2018 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.concurrent; import java.lang.annotation.*; @Retention(RetentionPolicy.CLASS) @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD }) @Documented @interface GwtIncompatible { String value() default ""; } vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/Promise.java000066400000000000000000000314751342074374400242320ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2017 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.concurrent; import io.vavr.control.Try; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import static io.vavr.concurrent.Future.DEFAULT_EXECUTOR; /** * A Promise is a write-once wrapper around a read-only Future which can complete the underlying Future with a value * or an exception. *

* The underlying {@code Executor} is used to execute asynchronous handlers, e.g. via * {@code promise.future().onComplete(...)}. * *

Creation

*

* Promise offers static factory methods to create new promises which hasn't been fulfilled yet: *

    *
  • create new promises: {@link Promise#make()}
  • *
* And we may create new promises that are already finished: *
    *
  • {@link #failed(Throwable)}
  • *
  • {@link #fromTry(Try)}
  • *
  • {@link #successful(Object)}
  • *
* All the static factory methods mentioned above have additional versions which take an {@link Executor} as * argument. This gives us more control over thread creation and thread pool sizes. * *

One-shot API

*

* The main purpose of a {@code Promise} is to complete its underlying {@code Future}. When only a single {@code Thread} * will eventually complete the {@code Promise}, we use one of these methods. Calls will throw if the {@code Promise} is already * completed. *

    *
  • {@link #complete(Try)}
  • *
  • {@link #completeWith(Future)}
  • *
  • {@link #failure(Throwable)}
  • *
  • {@link #success(Object)}
  • *
* *

API for competing threads

*

* When multiple {@code Thread}s may complete our {@code Promise}, we typically use one of these methods. Calls will * gracefully return {@code false} if the {@code Promise} is already completed. *

    *
  • {@link #tryComplete(Try)}
  • *
  • {@link #tryCompleteWith(Future)}
  • *
  • {@link #tryFailure(Throwable)}
  • *
  • {@link #trySuccess(Object)}
  • *
* * @param The result type of the underlying {@code Future}. * @author Daniel Dietrich */ public interface Promise { /** * Creates a failed {@code Promise}, backed by the {@link Future#DEFAULT_EXECUTOR}. * * @param exception The reason why it failed. * @param The value type of a successful result. * @return A failed {@code Promise}. * @throws NullPointerException if exception is null */ static Promise failed(Throwable exception) { Objects.requireNonNull(exception, "exception is null"); return failed(DEFAULT_EXECUTOR, exception); } /** * Creates a failed {@code Promise}, backed by the given {@link Executor}. * * @param executor An {@code Executor} passed to the underlying {@link Future}. * @param exception The reason why it failed. * @param The value type of a successful result. * @return A failed {@code Promise}. * @throws NullPointerException if executor or exception is null */ static Promise failed(Executor executor, Throwable exception) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(exception, "exception is null"); return Promise. make(executor).failure(exception); } /** * Creates a {@code Promise} from a {@link Try}, backed by the {@link Future#DEFAULT_EXECUTOR}. * * @param result The result. * @param The value type of a successful result. * @return A completed {@code Promise} which contains either a {@code Success} or a {@code Failure}. * @throws NullPointerException if result is null */ static Promise fromTry(Try result) { return fromTry(DEFAULT_EXECUTOR, result); } /** * Creates a {@code Promise} from a {@link Try}, backed by the given {@link Executor}. * * @param executor An {@code Executor} passed to the underlying {@link Future}. * @param result The result. * @param The value type of a successful result. * @return A completed {@code Promise} which contains either a {@code Success} or a {@code Failure}. * @throws NullPointerException if executor or result is null */ static Promise fromTry(Executor executor, Try result) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(result, "result is null"); return Promise. make(executor).complete(result); } /** * Makes a {@code Promise} that isn't fulfilled yet, backed by the {@link Future#DEFAULT_EXECUTOR}. * {@link ForkJoinPool#commonPool()}. * * @param Result type of the {@code Promise}. * @return A new {@code Promise}. */ static Promise make() { return make(DEFAULT_EXECUTOR); } /** * Makes a {@code Promise} that isn't fulfilled yet, backed by the given {@link Executor}. * * @param executor An {@code Executor} passed to the underlying {@link Future}. * @param Result type of the {@code Promise}. * @return A new {@code Promise}. * @throws NullPointerException if executor is null */ static Promise make(Executor executor) { Objects.requireNonNull(executor, "executor is null"); return new PromiseImpl<>(FutureImpl.of(executor)); } /** * Narrows a widened {@code Promise} to {@code Promise} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param promise A {@code Promise}. * @param Component type of the {@code Promise}. * @return the given {@code promise} instance as narrowed type {@code Promise}. */ @SuppressWarnings("unchecked") static Promise narrow(Promise promise) { return (Promise) promise; } /** * Creates a succeeded {@code Promise}, backed by the {@link Future#DEFAULT_EXECUTOR}. * * @param result The result. * @param The value type of a successful result. * @return A succeeded {@code Promise}. */ static Promise successful(T result) { return successful(DEFAULT_EXECUTOR, result); } /** * Creates a succeeded {@code Promise}, backed by the given {@link Executor}. * * @param executor An {@code Executor} passed to the underlying {@link Future}. * @param result The result. * @param The value type of a successful result. * @return A succeeded {@code Promise}. * @throws NullPointerException if executor is null */ static Promise successful(Executor executor, T result) { Objects.requireNonNull(executor, "executor is null"); return Promise. make(executor).success(result); } /** * Returns the {@link Executor} used by the underlying {@link Future} of this {@code Promise}. * * @return The underlying {@code Executor}. */ default Executor executor() { return executorService(); } /** * This method is deprecated. *

* THE DEFAULT IMPLEMENTATION (obtained by one of the {@link Promise} factory methods) MIGHT THROW AN * {@link UnsupportedOperationException} AT RUNTIME, DEPENDING ON WHAT {@link Future#executorService()} * returns. * * @return (never) * @throws UnsupportedOperationException if the underlying {@link Executor} isn't an {@link ExecutorService}. * @deprecated Removed starting with Vavr 0.10.0, use {@link #executor()} instead. */ @Deprecated ExecutorService executorService(); /** * Returns the underlying {@link Future} of this {@code Promise}. * * @return The {@code Future}. */ Future future(); /** * Checks if this {@code Promise} is completed, i.e. has a value. * * @return true, if the computation successfully finished or failed, false otherwise. */ default boolean isCompleted() { return future().isCompleted(); } /** * Completes this {@code Promise} with the given {@code value}. * * @param value Either a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception. * @return This {@code Promise}. * @throws IllegalStateException if this {@code Promise} has already been completed. */ default Promise complete(Try value) { if (tryComplete(value)) { return this; } else { throw new IllegalStateException("Promise already completed."); } } /** * Attempts to completes this {@code Promise} with the given {@code value}. * * @param value Either a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception. * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. * @throws IllegalStateException if this {@code Promise} has already been completed. */ boolean tryComplete(Try value); /** * Completes this {@code Promise} with the given {@code Future}, once that {@code Future} is completed. * * @param other Another {@code Future} to react on. * @return This {@code Promise}. */ default Promise completeWith(Future other) { return tryCompleteWith(other); } /** * Attempts to complete this {@code Promise} with the specified {@code Future}, once that {@code Future} is completed. * * @param other Another {@code Future} to react on. * @return This {@code Promise}. */ default Promise tryCompleteWith(Future other) { other.onComplete(this::tryComplete); return this; } /** * Completes this {@code Promise} with the given {@code value}. * * @param value A value. * @return This {@code Promise}. * @throws IllegalStateException if this {@code Promise} has already been completed. */ default Promise success(T value) { return complete(Try.success(value)); } /** * Completes this {@code Promise} with the given {@code value}. * * @param value A value. * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. */ default boolean trySuccess(T value) { return tryComplete(Try.success(value)); } /** * Completes this {@code Promise} with the given {@code exception}. * * @param exception An exception. * @return This {@code Promise}. * @throws IllegalStateException if this {@code Promise} has already been completed. */ default Promise failure(Throwable exception) { return complete(Try.failure(exception)); } /** * Completes this {@code Promise} with the given {@code exception}. * * @param exception An exception. * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. */ default boolean tryFailure(Throwable exception) { return tryComplete(Try.failure(exception)); } } /** * Internal {@code Promise} implementation. * * @param result type * @author Daniel Dietrich */ final class PromiseImpl implements Promise { private final FutureImpl future; PromiseImpl(FutureImpl future) { this.future = future; } @Override public Executor executor() { return future.executor(); } @Deprecated @Override public ExecutorService executorService() { return future.executorService(); } @Override public Future future() { return future; } @Override public boolean tryComplete(Try value) { return future.tryComplete(value); } // The underlying FutureImpl is MUTABLE and therefore we CANNOT CHANGE DEFAULT equals() and hashCode() behavior. // See http://stackoverflow.com/questions/4718009/mutable-objects-and-hashcode @Override public String toString() { return "Promise(" + future.getValue().map(String::valueOf).getOrElse("?") + ")"; } } vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/Task.java000066400000000000000000000025531342074374400235110ustar00rootroot00000000000000package io.vavr.concurrent; import io.vavr.control.Try; /** * Represents a possibly asynchronous unit of work, called "Task". *

* A {@code Task} is a function that takes an instance of {@link Complete} and returns nothing. *

* {@code Complete} is a handler that needs to be actively called to complete the {@code Task}. * *

{@code
 * Callable worker = ...;
 * Future result = Future.run(complete -> complete.with(Try.of(worker::call)));
 * }
* * @param result type * @deprecated Experimental API */ @Deprecated @FunctionalInterface public interface Task { /** * Runs the task. Non-fatal errors are catched by a {@link Future}. * * @param complete a function that completes this task * @throws Throwable if an error occurs */ void run(Complete complete) throws Throwable; /** * Completes a task. *

* @param result type */ @FunctionalInterface interface Complete { /** * A function that takes a {@link Try} (success or failure) and returns the state of completion. * * @param value the computation result * @return {@code true}, if the task could be completed, otherwise {@code false}. * Successive calls will result in {@code false}. */ boolean with(Try value); } } vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/package-info.java000066400000000000000000000010661342074374400251310ustar00rootroot00000000000000/** * This package contains basic building blocks for creating fast, asynchronous, non-blocking parallel code. *

* A {@linkplain io.vavr.concurrent.Future} represents an asynchronous task. It is a placeholder for a * value that becomes available at some point. With the help of {@code Future} we efficiently perform many non-blocking * operations in parallel. The value of a Future is supplied concurrently and can subsequently be used. Multiple * concurrent tasks represented by Futures can be composed to a single Future. */ package io.vavr.concurrent; vavr-0.10.0/vavr/src/main/java/io/vavr/concurrent/readme-contributing.md000066400000000000000000000031741342074374400262300ustar00rootroot00000000000000These are the ideas behind the implementation of Future/Promise: The design follows separation of concerns in two manners: - public interfaces vs. internal implementations (Promise/PromiseImpl, Future/FutureImpl) - Future = read-only, Promise = write-once ### Interfaces vs. internal classes Concurrent programming is all about synchronized state. To keep this as simple as possible, it is a good idea to separate readable and writable state. The internal implementations encapsulate the state. Their number of methods drill down to those which access instance variables. These classes are typically very short. They represent a clean and easy to maintain, thread-safe core. The interfaces define, beside abstract methods, static factory methods, static extension methods and default methods. The default implementations are built on top of the tread-safe core mentioned above. Typically, no additional synchronization takes place here. ### Read-only vs. write-once Separating the end-user API into the Future interface, providing the read-only API, and the Promise interface, providing the write-once API, solves a different concurrency problem than state synchronization. By separating these concerns, we define a specific _programming model_ that allows us to easily deal with common tasks in concurrent programming. ```java final Promise promise = Promise.make(); final Future future = promise.future(); // producer Future.run(() -> { promise.success(produceSomething()); continueDoingSomethingUnrelated(); }); // consumer Future.run(() -> { startDoingSomething(); future.onSuccess(doSomethingWithResult); }); ``` vavr-0.10.0/vavr/src/main/java/io/vavr/control/000077500000000000000000000000001342074374400212355ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/java/io/vavr/control/Either.java000066400000000000000000001204201342074374400233170ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.control; import io.vavr.Value; import io.vavr.collection.Iterator; import io.vavr.collection.Seq; import io.vavr.collection.Vector; import java.io.Serializable; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * Either represents a value of two possible types. An Either is either a {@link Left} or a * {@link Right}. *

* If the given Either is a Right and projected to a Left, the Left operations have no effect on the Right value.
* If the given Either is a Left and projected to a Right, the Right operations have no effect on the Left value.
* If a Left is projected to a Left or a Right is projected to a Right, the operations have an effect. *

* Example: A compute() function, which results either in an Integer value (in the case of success) or * in an error message of type String (in the case of failure). By convention the success case is Right and the failure * is Left. * *

 * 
 * Either<String,Integer> value = compute().right().map(i -> i * 2).toEither();
 * 
 * 
* * If the result of compute() is Right(1), the value is Right(2).
* If the result of compute() is Left("error"), the value is Left("error"). * * @param The type of the Left value of an Either. * @param The type of the Right value of an Either. * @author Daniel Dietrich */ public interface Either extends Value, Serializable { long serialVersionUID = 1L; /** * Constructs a {@link Right} * * @param right The value. * @param Type of left value. * @param Type of right value. * @return A new {@code Right} instance. */ static Either right(R right) { return new Right<>(right); } /** * Constructs a {@link Left} * * @param left The value. * @param Type of left value. * @param Type of right value. * @return A new {@code Left} instance. */ static Either left(L left) { return new Left<>(left); } /** * Narrows a widened {@code Either} to {@code Either} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param either A {@code Either}. * @param Type of left value. * @param Type of right value. * @return the given {@code either} instance as narrowed type {@code Either}. */ @SuppressWarnings("unchecked") static Either narrow(Either either) { return (Either) either; } /** * Returns the left value. * * @return The left value. * @throws NoSuchElementException if this is a {@code Right}. */ L getLeft(); /** * Returns whether this Either is a Left. * * @return true, if this is a Left, false otherwise */ boolean isLeft(); /** * Returns whether this Either is a Right. * * @return true, if this is a Right, false otherwise */ boolean isRight(); /** * Returns a LeftProjection of this Either. * * @return a new LeftProjection of this * @deprecated Either is right-biased. Use {@link #swap()} instead of projections. */ @Deprecated default LeftProjection left() { return new LeftProjection<>(this); } /** * Returns a RightProjection of this Either. * * @return a new RightProjection of this * @deprecated Either is right-biased. Use {@link #swap()} instead of projections. */ @Deprecated default RightProjection right() { return new RightProjection<>(this); } /** * Maps either the left or the right side of this disjunction. * * @param leftMapper maps the left value if this is a Left * @param rightMapper maps the right value if this is a Right * @param The new left type of the resulting Either * @param The new right type of the resulting Either * @return A new Either instance */ default Either bimap(Function leftMapper, Function rightMapper) { Objects.requireNonNull(leftMapper, "leftMapper is null"); Objects.requireNonNull(rightMapper, "rightMapper is null"); if (isRight()) { return new Right<>(rightMapper.apply(get())); } else { return new Left<>(leftMapper.apply(getLeft())); } } /** * Folds either the left or the right side of this disjunction. * * @param leftMapper maps the left value if this is a Left * @param rightMapper maps the right value if this is a Right * @param type of the folded value * @return A value of type U */ default U fold(Function leftMapper, Function rightMapper) { Objects.requireNonNull(leftMapper, "leftMapper is null"); Objects.requireNonNull(rightMapper, "rightMapper is null"); if (isRight()) { return rightMapper.apply(get()); } else { return leftMapper.apply(getLeft()); } } /** * Reduces many {@code Either}s into a single {@code Either} by transforming an * {@code Iterable>} into a {@code Either, Seq>}. *

* If any of the given {@code Either}s is a {@link Either.Left} then {@code sequence} returns a * {@link Either.Left} containing a non-empty {@link Seq} of all left values. *

* If none of the given {@code Either}s is a {@link Either.Left} then {@code sequence} returns a * {@link Either.Right} containing a (possibly empty) {@link Seq} of all right values. * *

{@code
     * // = Right(Seq())
     * Either.sequence(List.empty())
     *
     * // = Right(Seq(1, 2))
     * Either.sequence(List.of(Either.right(1), Either.right(2)))
     *
     * // = Left(Seq("x"))
     * Either.sequence(List.of(Either.right(1), Either.left("x")))
     * }
* * @param eithers An {@link Iterable} of {@code Either}s * @param closure of all left types of the given {@code Either}s * @param closure of all right types of the given {@code Either}s * @return An {@code Either} of a {@link Seq} of left or right values * @throws NullPointerException if {@code eithers} is null */ @SuppressWarnings("unchecked") static Either, Seq> sequence(Iterable> eithers) { Objects.requireNonNull(eithers, "eithers is null"); return Iterator.ofAll((Iterable>) eithers) .partition(Either::isLeft) .apply((leftPartition, rightPartition) -> leftPartition.hasNext() ? Either.left(leftPartition.map(Either::getLeft).toVector()) : Either.right(rightPartition.map(Either::get).toVector()) ); } /** * Maps the values of an iterable to a sequence of mapped values into a single {@code Either} by * transforming an {@code Iterable} into a {@code Either>}. *

* * @param values An {@code Iterable} of values. * @param mapper A mapper of values to Eithers * @param The mapped left value type. * @param The mapped right value type. * @param The type of the given values. * @return A {@code Either} of a {@link Seq} of results. * @throws NullPointerException if values or f is null. */ static Either, Seq> traverse(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); Objects.requireNonNull(mapper, "mapper is null"); return sequence(Iterator.ofAll(values).map(mapper)); } /** * Reduces many {@code Either}s into a single {@code Either} by transforming an * {@code Iterable>} into a {@code Either>}. *

* If any of the given {@code Either}s is a {@link Either.Left} then {@code sequenceRight} returns a * {@link Either.Left} containing the first left value (in iteration order). *

* If none of the given {@code Either}s is a {@link Either.Left} then {@code sequenceRight} returns a * {@link Either.Right} containing a (possibly empty) {@link Seq} of all right values. * *

{@code
     * // = Right(Seq())
     * Either.sequenceRight(List.empty())
     *
     * // = Right(Seq(1, 2))
     * Either.sequenceRight(List.of(Either.right(1), Either.right(2)))
     *
     * // = Left("x1")
     * Either.sequenceRight(List.of(Either.right(1), Either.left("x1"), Either.left("x2")))
     * }
* * @param eithers An {@link Iterable} of {@code Either}s * @param closure of all left types of the given {@code Either}s * @param closure of all right types of the given {@code Either}s * @return An {@code Either} of either a {@link Seq} of right values or the first left value, if present. * @throws NullPointerException if {@code eithers} is null */ static Either> sequenceRight(Iterable> eithers) { Objects.requireNonNull(eithers, "eithers is null"); Vector rightValues = Vector.empty(); for (Either either : eithers) { if (either.isRight()) { rightValues = rightValues.append(either.get()); } else { return Either.left(either.getLeft()); } } return Either.right(rightValues); } /** * Maps the values of an iterable to a sequence of mapped values into a single {@code Either} by * transforming an {@code Iterable} into a {@code Either>}. *

* * @param values An {@code Iterable} of values. * @param mapper A mapper of values to Eithers * @param The mapped left value type. * @param The mapped right value type. * @param The type of the given values. * @return A {@code Either} of a {@link Seq} of results. * @throws NullPointerException if values or f is null. */ static Either> traverseRight(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); Objects.requireNonNull(mapper, "mapper is null"); return sequenceRight(Iterator.ofAll(values).map(mapper)); } /** * Gets the Right value or an alternate value, if the projected Either is a Left. * * @param other a function which converts a Left value to an alternative Right value * @return the right value, if the underlying Either is a Right or else the alternative Right value provided by * {@code other} by applying the Left value. */ default R getOrElseGet(Function other) { Objects.requireNonNull(other, "other is null"); if (isRight()) { return get(); } else { return other.apply(getLeft()); } } /** * Runs an action in the case this is a projection on a Left value. * * @param action an action which consumes a Left value */ default void orElseRun(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isLeft()) { action.accept(getLeft()); } } /** * Gets the Right value or throws, if the projected Either is a Left. * * @param a throwable type * @param exceptionFunction a function which creates an exception based on a Left value * @return the right value, if the underlying Either is a Right or else throws the exception provided by * {@code exceptionFunction} by applying the Left value. * @throws X if the projected Either is a Left */ default R getOrElseThrow(Function exceptionFunction) throws X { Objects.requireNonNull(exceptionFunction, "exceptionFunction is null"); if (isRight()) { return get(); } else { throw exceptionFunction.apply(getLeft()); } } /** * Converts a {@code Left} to a {@code Right} vice versa by wrapping the value in a new type. * * @return a new {@code Either} */ default Either swap() { if (isRight()) { return new Left<>(get()); } else { return new Right<>(getLeft()); } } // -- Adjusted return types of Monad methods /** * FlatMaps this right-biased Either. * * @param mapper A mapper * @param Component type of the mapped right value * @return this as {@code Either} if this is a Left, otherwise the right mapping result * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") default Either flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isRight()) { return (Either) mapper.apply(get()); } else { return (Either) this; } } /** * Maps the value of this Either if it is a Right, performs no operation if this is a Left. * *


     * import static io.vavr.API.*;
     *
     * // = Right("A")
     * Right("a").map(String::toUpperCase);
     *
     * // = Left(1)
     * Left(1).map(String::toUpperCase);
     * 
* * @param mapper A mapper * @param Component type of the mapped right value * @return a mapped {@code Monad} * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") @Override default Either map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isRight()) { return Either.right(mapper.apply(get())); } else { return (Either) this; } } /** * Maps the value of this Either if it is a Left, performs no operation if this is a Right. * *
{@code
     * import static io.vavr.API.*;
     *
     * // = Left(2)
     * Left(1).mapLeft(i -> i + 1);
     *
     * // = Right("a")
     * Right("a").mapLeft(i -> i + 1);
     * }
* * @param leftMapper A mapper * @param Component type of the mapped right value * @return a mapped {@code Monad} * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") default Either mapLeft(Function leftMapper) { Objects.requireNonNull(leftMapper, "leftMapper is null"); if (isLeft()) { return Either.left(leftMapper.apply(getLeft())); } else { return (Either) this; } } // -- Adjusted return types of Value methods /** * Filters this right-biased {@code Either} by testing a predicate. *

* * @param predicate A predicate * @return a new {@code Option} instance * @throws NullPointerException if {@code predicate} is null */ default Option> filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return isLeft() || predicate.test(get()) ? Option.some(this) : Option.none(); } /** * Filters this right-biased {@code Either} by testing a predicate. * If the {@code Either} is a {@code Right} and the predicate doesn't match, the * {@code Either} will be turned into a {@code Left} with contents computed by applying * the filterVal function to the {@code Either} value. * *

{@code
     * import static io.vavr.API.*;
     *
     * // = Left("bad: a")
     * Right("a").filterOrElse(i -> false, val -> "bad: " + val);
     *
     * // = Right("a")
     * Right("a").filterOrElse(i -> true, val -> "bad: " + val);
     * }
* * @param predicate A predicate * @param zero A function that turns a right value into a left value if the right value does not make it through the filter. * @return an {@code Either} instance * @throws NullPointerException if {@code predicate} is null */ default Either filterOrElse(Predicate predicate, Function zero) { Objects.requireNonNull(predicate, "predicate is null"); Objects.requireNonNull(zero, "zero is null"); if (isLeft() || predicate.test(get())) { return this; } else { return Either.left(zero.apply(get())); } } /** * Gets the right value if this is a {@code Right} or throws if this is a {@code Left}. * * @return the right value * @throws NoSuchElementException if this is a {@code Left}. */ @Override R get(); @Override default boolean isEmpty() { return isLeft(); } @SuppressWarnings("unchecked") default Either orElse(Either other) { Objects.requireNonNull(other, "other is null"); return isRight() ? this : (Either) other; } @SuppressWarnings("unchecked") default Either orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isRight() ? this : (Either) supplier.get(); } /** * A right-biased {@code Either}'s value is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } /** * A right-biased {@code Either}'s value is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } /** * A right-biased {@code Either} is single-valued. * * @return {@code true} */ @Override default boolean isSingleValued() { return true; } @Override default Iterator iterator() { if (isRight()) { return Iterator.of(get()); } else { return Iterator.empty(); } } @Override default Either peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isRight()) { action.accept(get()); } return this; } default Either peekLeft(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isLeft()) { action.accept(getLeft()); } return this; } /** * Returns this as {@code Validation}. * * @return {@code Validation.valid(get())} if this is right, otherwise {@code Validation.invalid(getLeft())}. */ default Validation toValidation() { return isRight() ? Validation.valid(get()) : Validation.invalid(getLeft()); } // -- Object.* @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); // -- Left/Right projections /** * A left projection of an Either. * * @param The type of the Left value of an Either. * @param The type of the Right value of an Either. * @deprecated Either is right-biased. Use {@link #swap()} instead of projections. */ @Deprecated final class LeftProjection implements Value { private final Either either; private LeftProjection(Either either) { this.either = either; } public LeftProjection bimap(Function leftMapper, Function rightMapper) { return either. bimap(leftMapper, rightMapper).left(); } /** * A {@code LeftProjection}'s value is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return either.isRight(); } /** * A {@code LeftProjection}'s value is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } /** * A {@code LeftProjection} is single-valued. * * @return {@code true} */ @Override public boolean isSingleValued() { return true; } /** * Gets the {@code Left} value or throws. * * @return the left value, if the underlying {@code Either} is a {@code Left} * @throws NoSuchElementException if the underlying {@code Either} of this {@code LeftProjection} is a {@code Right} */ @Override public L get() { if (either.isLeft()) { return either.getLeft(); } else { throw new NoSuchElementException("LeftProjection.get() on Right"); } } @SuppressWarnings("unchecked") public LeftProjection orElse(LeftProjection other) { Objects.requireNonNull(other, "other is null"); return either.isLeft() ? this : (LeftProjection) other; } @SuppressWarnings("unchecked") public LeftProjection orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return either.isLeft() ? this : (LeftProjection) supplier.get(); } /** * Gets the Left value or an alternate value, if the projected Either is a Right. * * @param other an alternative value * @return the left value, if the underlying Either is a Left or else {@code other} * @throws NoSuchElementException if the underlying either of this LeftProjection is a Right */ @Override public L getOrElse(L other) { return either.isLeft() ? either.getLeft() : other; } /** * Gets the Left value or an alternate value, if the projected Either is a Right. * * @param other a function which converts a Right value to an alternative Left value * @return the left value, if the underlying Either is a Left or else the alternative Left value provided by * {@code other} by applying the Right value. */ public L getOrElseGet(Function other) { Objects.requireNonNull(other, "other is null"); if (either.isLeft()) { return either.getLeft(); } else { return other.apply(either.get()); } } /** * Runs an action in the case this is a projection on a Right value. * * @param action an action which consumes a Right value */ public void orElseRun(Consumer action) { Objects.requireNonNull(action, "action is null"); if (either.isRight()) { action.accept(either.get()); } } /** * Gets the Left value or throws, if the projected Either is a Right. * * @param a throwable type * @param exceptionFunction a function which creates an exception based on a Right value * @return the left value, if the underlying Either is a Left or else throws the exception provided by * {@code exceptionFunction} by applying the Right value. * @throws X if the projected Either is a Right */ public L getOrElseThrow(Function exceptionFunction) throws X { Objects.requireNonNull(exceptionFunction, "exceptionFunction is null"); if (either.isLeft()) { return either.getLeft(); } else { throw exceptionFunction.apply(either.get()); } } /** * Returns the underlying either of this projection. * * @return the underlying either */ public Either toEither() { return either; } /** * Returns {@code Some} value of type L if this is a left projection of a Left value and the predicate * applies to the underlying value. * * @param predicate A predicate * @return A new Option */ public Option> filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return either.isRight() || predicate.test(either.getLeft()) ? Option.some(this) : Option.none(); } /** * FlatMaps this LeftProjection. * * @param mapper A mapper * @param Component type of the mapped left value * @return this as {@code LeftProjection} if a Right is underlying, otherwise a the mapping result of the left value. * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") public LeftProjection flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (either.isLeft()) { return (LeftProjection) mapper.apply(either.getLeft()); } else { return (LeftProjection) this; } } /** * Maps the left value if the projected Either is a Left. * * @param mapper A mapper which takes a left value and returns a value of type U * @param The new type of a Left value * @return A new LeftProjection */ @SuppressWarnings("unchecked") @Override public LeftProjection map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (either.isLeft()) { return either.mapLeft((Function) mapper).left(); } else { return (LeftProjection) this; } } /** * Applies the given action to the value if the projected either is a Left. Otherwise nothing happens. * * @param action An action which takes a left value * @return this LeftProjection */ @Override public LeftProjection peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (either.isLeft()) { action.accept(either.getLeft()); } return this; } /** * Transforms this {@code LeftProjection}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public Iterator iterator() { if (either.isLeft()) { return Iterator.of(either.getLeft()); } else { return Iterator.empty(); } } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof LeftProjection && Objects.equals(either, ((LeftProjection) obj).either)); } @Override public int hashCode() { return either.hashCode(); } @Override public String stringPrefix() { return "LeftProjection"; } @Override public String toString() { return stringPrefix() + "(" + either + ")"; } } /** * A right projection of an Either. * * @param The type of the Left value of an Either. * @param The type of the Right value of an Either. * @deprecated Either is right-biased. Use {@link #swap()} instead of projections. */ @Deprecated final class RightProjection implements Value { private final Either either; private RightProjection(Either either) { this.either = either; } public RightProjection bimap(Function leftMapper, Function rightMapper) { return either. bimap(leftMapper, rightMapper).right(); } /** * A {@code RightProjection}'s value is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return either.isLeft(); } /** * A {@code RightProjection}'s value is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } /** * A {@code RightProjection} is single-valued. * * @return {@code true} */ @Override public boolean isSingleValued() { return true; } /** * Gets the {@code Right} value or throws. * * @return the right value, if the underlying {@code Either} is a {@code Right} * @throws NoSuchElementException if the underlying {@code Either} of this {@code RightProjection} is a {@code Left} */ @Override public R get() { if (either.isRight()) { return either.get(); } else { throw new NoSuchElementException("RightProjection.get() on Left"); } } @SuppressWarnings("unchecked") public RightProjection orElse(RightProjection other) { Objects.requireNonNull(other, "other is null"); return either.isRight() ? this : (RightProjection) other; } @SuppressWarnings("unchecked") public RightProjection orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return either.isRight() ? this : (RightProjection) supplier.get(); } /** * Gets the Right value or an alternate value, if the projected Either is a Left. * * @param other an alternative value * @return the right value, if the underlying Either is a Right or else {@code other} * @throws NoSuchElementException if the underlying either of this RightProjection is a Left */ @Override public R getOrElse(R other) { return either.getOrElse(other); } /** * Gets the Right value or an alternate value, if the projected Either is a Left. * * @param other a function which converts a Left value to an alternative Right value * @return the right value, if the underlying Either is a Right or else the alternative Right value provided by * {@code other} by applying the Left value. */ public R getOrElseGet(Function other) { Objects.requireNonNull(other, "other is null"); return either.getOrElseGet(other); } /** * Runs an action in the case this is a projection on a Left value. * * @param action an action which consumes a Left value */ public void orElseRun(Consumer action) { Objects.requireNonNull(action, "action is null"); either.orElseRun(action); } /** * Gets the Right value or throws, if the projected Either is a Left. * * @param a throwable type * @param exceptionFunction a function which creates an exception based on a Left value * @return the right value, if the underlying Either is a Right or else throws the exception provided by * {@code exceptionFunction} by applying the Left value. * @throws X if the projected Either is a Left */ public R getOrElseThrow(Function exceptionFunction) throws X { Objects.requireNonNull(exceptionFunction, "exceptionFunction is null"); return either.getOrElseThrow(exceptionFunction); } /** * Returns the underlying either of this projection. * * @return the underlying either */ public Either toEither() { return either; } /** * Returns {@code Some} value of type R if this is a right projection of a Right value and the predicate * applies to the underlying value. * * @param predicate A predicate * @return A new Option */ public Option> filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return either.isLeft() || predicate.test(either.get()) ? Option.some(this) : Option.none(); } /** * FlatMaps this RightProjection. * * @param mapper A mapper * @param Component type of the mapped right value * @return this as {@code RightProjection} if a Left is underlying, otherwise a the mapping result of the right value. * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") public RightProjection flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (either.isRight()) { return (RightProjection) mapper.apply(either.get()); } else { return (RightProjection) this; } } /** * Maps the right value if the projected Either is a Right. * * @param mapper A mapper which takes a right value and returns a value of type U * @param The new type of a Right value * @return A new RightProjection */ @SuppressWarnings("unchecked") @Override public RightProjection map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (either.isRight()) { return either.map((Function) mapper).right(); } else { return (RightProjection) this; } } /** * Applies the given action to the value if the projected either is a Right. Otherwise nothing happens. * * @param action An action which takes a right value * @return this {@code Either} instance */ @Override public RightProjection peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (either.isRight()) { action.accept(either.get()); } return this; } /** * Transforms this {@code RightProjection}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public Iterator iterator() { return either.iterator(); } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof RightProjection && Objects.equals(either, ((RightProjection) obj).either)); } @Override public int hashCode() { return either.hashCode(); } @Override public String stringPrefix() { return "RightProjection"; } @Override public String toString() { return stringPrefix() + "(" + either + ")"; } } /** * The {@code Left} version of an {@code Either}. * * @param left component type * @param right component type * @author Daniel Dietrich */ final class Left implements Either, Serializable { private static final long serialVersionUID = 1L; private final L value; /** * Constructs a {@code Left}. * * @param value a left value */ private Left(L value) { this.value = value; } @Override public R get() { throw new NoSuchElementException("get() on Left"); } @Override public L getLeft() { return value; } @Override public boolean isLeft() { return true; } @Override public boolean isRight() { return false; } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Left && Objects.equals(value, ((Left) obj).value)); } @Override public int hashCode() { return Objects.hashCode(value); } @Override public String stringPrefix() { return "Left"; } @Override public String toString() { return stringPrefix() + "(" + value + ")"; } } /** * The {@code Right} version of an {@code Either}. * * @param left component type * @param right component type * @author Daniel Dietrich */ final class Right implements Either, Serializable { private static final long serialVersionUID = 1L; private final R value; /** * Constructs a {@code Right}. * * @param value a right value */ private Right(R value) { this.value = value; } @Override public R get() { return value; } @Override public L getLeft() { throw new NoSuchElementException("getLeft() on Right"); } @Override public boolean isLeft() { return false; } @Override public boolean isRight() { return true; } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Right && Objects.equals(value, ((Right) obj).value)); } @Override public int hashCode() { return Objects.hashCode(value); } @Override public String stringPrefix() { return "Right"; } @Override public String toString() { return stringPrefix() + "(" + value + ")"; } } } vavr-0.10.0/vavr/src/main/java/io/vavr/control/GwtIncompatible.java000066400000000000000000000017411342074374400251730ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2018 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.control; import java.lang.annotation.*; @Retention(RetentionPolicy.CLASS) @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD }) @Documented @interface GwtIncompatible { String value() default ""; } vavr-0.10.0/vavr/src/main/java/io/vavr/control/HashCodes.java000066400000000000000000000346071342074374400237530ustar00rootroot00000000000000package io.vavr.control; import java.util.List; import java.util.Objects; // TODO should we generate this file and add more permutations of parameter types? /** * Utility that allows to compute hashcodes without var-arg conversion into arrays for common * types of vavr. * * @author Sebastian Zarnekow * @deprecated Will be removed from public API */ @Deprecated public interface HashCodes { /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Integer#hashCode() */ static int hash(int value) { return Integer.hashCode(value); } /** * Return the order-dependent hash of the two given integers. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(int v1, int v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Long#hashCode() */ static int hash(long value) { return Long.hashCode(value); } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Byte#hashCode() */ static int hash(byte value) { return Byte.hashCode(value); } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Short#hashCode() */ static int hash(short value) { return Short.hashCode(value); } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Character#hashCode() */ static int hash(char value) { return Character.hashCode(value); } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Boolean#hashCode() */ static int hash(boolean value) { return Boolean.hashCode(value); } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Float#hashCode() */ static int hash(float value) { return Float.hashCode(value); } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Double#hashCode() */ static int hash(double value) { return Double.hashCode(value); } /** * Returns the hashcode of the given value. * * @param value the value to hash * @return the hashcode * @see Objects#hashCode() */ static int hash(Object value) { return Objects.hashCode(value); } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(int v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(long v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(byte v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(short v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(char v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(boolean v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(float v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(double v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the two given values. *

* More formally, it returns the value {@code 31 * (31 + hash(v1)) + hash(v2)}. * * @param v1 the first value to hash * @param v2 the second value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(Object v1, Object v2) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); return result; } /** * Return the order-dependent hash of the three given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the given values. * * @param v1 the first value to hash * @param v2 the second value to hash * @param v3 the third value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(Object v1, Object v2, Object v3) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); result = 31 * result + hash(v3); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the given values. * * @param v1 the first value to hash * @param v2 the second value to hash * @param v3 the third value to hash * @param v4 the fourth value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(Object v1, Object v2, Object v3, Object v4) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); result = 31 * result + hash(v3); result = 31 * result + hash(v4); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the given values. * * @param v1 the first value to hash * @param v2 the second value to hash * @param v3 the third value to hash * @param v4 the fourth value to hash * @param v5 the fifth value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(Object v1, Object v2, Object v3, Object v4, Object v5) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); result = 31 * result + hash(v3); result = 31 * result + hash(v4); result = 31 * result + hash(v5); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the given values. * * @param v1 the first value to hash * @param v2 the second value to hash * @param v3 the third value to hash * @param v4 the fourth value to hash * @param v5 the fifth value to hash * @param v6 the sixth value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(Object v1, Object v2, Object v3, Object v4, Object v5, Object v6) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); result = 31 * result + hash(v3); result = 31 * result + hash(v4); result = 31 * result + hash(v5); result = 31 * result + hash(v6); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the given values. * * @param v1 the first value to hash * @param v2 the second value to hash * @param v3 the third value to hash * @param v4 the fourth value to hash * @param v5 the fifth value to hash * @param v6 the sixth value to hash * @param v7 the seventh value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(Object v1, Object v2, Object v3, Object v4, Object v5, Object v6, Object v7) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); result = 31 * result + hash(v3); result = 31 * result + hash(v4); result = 31 * result + hash(v5); result = 31 * result + hash(v6); result = 31 * result + hash(v7); return result; } /** * Return the order-dependent hash of the two given values. *

* The hashcode is equivalent to the hashcode of a {@link java.util.List} containing the given values. * * @param v1 the first value to hash * @param v2 the second value to hash * @param v3 the third value to hash * @param v4 the fourth value to hash * @param v5 the fifth value to hash * @param v6 the sixth value to hash * @param v7 the seventh value to hash * @param v8 the eighth value to hash * @return the hashcode * @see List#hashCode() * @see java.util.Arrays#hashCode(Object[]) */ static int hash(Object v1, Object v2, Object v3, Object v4, Object v5, Object v6, Object v7, Object v8) { int result = 1; result = 31 * result + hash(v1); result = 31 * result + hash(v2); result = 31 * result + hash(v3); result = 31 * result + hash(v4); result = 31 * result + hash(v5); result = 31 * result + hash(v6); result = 31 * result + hash(v7); result = 31 * result + hash(v8); return result; } }vavr-0.10.0/vavr/src/main/java/io/vavr/control/Option.java000066400000000000000000000437341342074374400233630ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.control; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.Value; import io.vavr.collection.Iterator; import io.vavr.collection.Seq; import io.vavr.collection.Vector; import java.io.Serializable; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * Replacement for {@link java.util.Optional}. *

* Option is a monadic container type which * represents an optional value. Instances of Option are either an instance of {@link Some} or the * singleton {@link None}. *

* Most of the API is taken from {@link java.util.Optional}. A similar type can be found in Haskell and Scala. * * @param The type of the optional value. * @author Daniel Dietrich */ public interface Option extends Value, Serializable { long serialVersionUID = 1L; /** * Creates a new {@code Option} of a given value. * * @param value A value * @param type of the value * @return {@code Some(value)} if value is not {@code null}, {@code None} otherwise */ static Option of(T value) { return (value == null) ? none() : some(value); } /** * Reduces many {@code Option}s into a single {@code Option} by transforming an * {@code Iterable>} into a {@code Option>}. If any of * the Options are {@link Option.None}, then this returns {@link Option.None}. * * @param values An {@code Iterable} of {@code Option}s * @param type of the Options * @return An {@code Option} of a {@link Seq} of results * @throws NullPointerException if {@code values} is null */ static Option> sequence(Iterable> values) { Objects.requireNonNull(values, "values is null"); Vector vector = Vector.empty(); for (Option value : values) { if (value.isEmpty()) { return Option.none(); } vector = vector.append(value.get()); } return Option.some(vector); } /** * Maps the values of an iterable to a sequence of mapped values into a single {@code Option} by * transforming an {@code Iterable} into a {@code Option>}. *

* * @param values An {@code Iterable} of values. * @param mapper A mapper of values to Options * @param The type of the given values. * @param The mapped value type. * @return A {@code Option} of a {@link Seq} of results. * @throws NullPointerException if values or f is null. */ static Option> traverse(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); Objects.requireNonNull(mapper, "mapper is null"); return sequence(Iterator.ofAll(values).map(mapper)); } /** * Creates a new {@code Some} of a given value. *

* The only difference to {@link Option#of(Object)} is, when called with argument {@code null}. *

     * 
     * Option.of(null);   // = None
     * Option.some(null); // = Some(null)
     * 
     * 
* * @param value A value * @param type of the value * @return {@code Some(value)} */ static Option some(T value) { return new Some<>(value); } /** * Returns the single instance of {@code None} * * @param component type * @return the single instance of {@code None} */ static Option none() { @SuppressWarnings("unchecked") final None none = (None) None.INSTANCE; return none; } /** * Narrows a widened {@code Option} to {@code Option} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param option A {@code Option}. * @param Component type of the {@code Option}. * @return the given {@code option} instance as narrowed type {@code Option}. */ @SuppressWarnings("unchecked") static Option narrow(Option option) { return (Option) option; } /** * Creates {@code Some} of suppliers value if condition is true, or {@code None} in other case * * @param type of the optional value * @param condition A boolean value * @param supplier An optional value supplier, may supply {@code null} * @return return {@code Some} of supplier's value if condition is true, or {@code None} in other case * @throws NullPointerException if the given {@code supplier} is null */ static Option when(boolean condition, Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return condition ? some(supplier.get()) : none(); } /** * Creates {@code Some} of value if condition is true, or {@code None} in other case * * @param type of the optional value * @param condition A boolean value * @param value An optional value, may be {@code null} * @return return {@code Some} of value if condition is true, or {@code None} in other case */ static Option when(boolean condition, T value) { return condition ? some(value) : none(); } /** * Wraps a Java Optional to a new Option * * @param optional a given optional to wrap in {@code Option} * @param type of the value * @return {@code Some(optional.get())} if value is Java {@code Optional} is present, {@code None} otherwise */ @SuppressWarnings("OptionalUsedAsFieldOrParameterType") static Option ofOptional(Optional optional) { Objects.requireNonNull(optional, "optional is null"); return optional.>map(Option::of).orElseGet(Option::none); } /** * Collects value that is in the domain of the given {@code partialFunction} by mapping the value to type {@code R}. * *
{@code
     * partialFunction.isDefinedAt(value)
     * }
* * If the element makes it through that filter, the mapped instance is wrapped in {@code Option} * *
{@code
     * R newValue = partialFunction.apply(value)
     * }
* * * @param partialFunction A function that is not necessarily defined on value of this option. * @param The new value type * @return A new {@code Option} instance containing value of type {@code R} * @throws NullPointerException if {@code partialFunction} is null */ default Option collect(PartialFunction partialFunction) { Objects.requireNonNull(partialFunction, "partialFunction is null"); return flatMap(partialFunction.lift()::apply); } /** * Returns true, if this is {@code None}, otherwise false, if this is {@code Some}. * * @return true, if this {@code Option} is empty, false otherwise */ @Override boolean isEmpty(); /** * Runs a Java Runnable passed as parameter if this {@code Option} is empty. * * @param action a given Runnable to be run * @return this {@code Option} */ default Option onEmpty(Runnable action) { Objects.requireNonNull(action, "action is null"); if (isEmpty()) { action.run(); } return this; } /** * An {@code Option}'s value is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } /** * Returns true, if this is {@code Some}, otherwise false, if this is {@code None}. *

* Please note that it is possible to create {@code new Some(null)}, which is defined. * * @return true, if this {@code Option} has a defined value, false otherwise */ default boolean isDefined() { return !isEmpty(); } /** * An {@code Option}'s value is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } /** * An {@code Option} is single-valued. * * @return {@code true} */ @Override default boolean isSingleValued() { return true; } /** * Gets the value if this is a {@code Some} or throws if this is a {@code None}. * * @return the value * @throws NoSuchElementException if this is a {@code None}. */ @Override T get(); /** * Returns the value if this is a {@code Some} or the {@code other} value if this is a {@code None}. *

* Please note, that the other value is eagerly evaluated. * * @param other An alternative value * @return This value, if this Option is defined or the {@code other} value, if this Option is empty. */ @Override default T getOrElse(T other) { return isEmpty() ? other : get(); } /** * Returns this {@code Option} if it is nonempty, otherwise return the alternative. * * @param other An alternative {@code Option} * @return this {@code Option} if it is nonempty, otherwise return the alternative. */ @SuppressWarnings("unchecked") default Option orElse(Option other) { Objects.requireNonNull(other, "other is null"); return isEmpty() ? (Option) other : this; } /** * Returns this {@code Option} if it is nonempty, otherwise return the result of evaluating supplier. * * @param supplier An alternative {@code Option} supplier * @return this {@code Option} if it is nonempty, otherwise return the result of evaluating supplier. */ @SuppressWarnings("unchecked") default Option orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isEmpty() ? (Option) supplier.get() : this; } /** * Returns the value if this is a {@code Some}, otherwise the {@code other} value is returned, * if this is a {@code None}. *

* Please note, that the other value is lazily evaluated. * * @param supplier An alternative value supplier * @return This value, if this Option is defined or the {@code other} value, if this Option is empty. */ @Override default T getOrElse(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isEmpty() ? supplier.get() : get(); } /** * Returns the value if this is a {@code Some}, otherwise throws an exception. * * @param exceptionSupplier An exception supplier * @param A throwable * @return This value, if this Option is defined, otherwise throws X * @throws X a throwable */ @Override default T getOrElseThrow(Supplier exceptionSupplier) throws X { Objects.requireNonNull(exceptionSupplier, "exceptionSupplier is null"); if (isEmpty()) { throw exceptionSupplier.get(); } else { return get(); } } /** * Returns {@code Some(value)} if this is a {@code Some} and the value satisfies the given predicate. * Otherwise {@code None} is returned. * * @param predicate A predicate which is used to test an optional value * @return {@code Some(value)} or {@code None} as specified */ default Option filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return isEmpty() || predicate.test(get()) ? this : none(); } /** * Maps the value to a new {@code Option} if this is a {@code Some}, otherwise returns {@code None}. * * @param mapper A mapper * @param Component type of the resulting Option * @return a new {@code Option} */ @SuppressWarnings("unchecked") default Option flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? none() : (Option) mapper.apply(get()); } /** * Maps the value and wraps it in a new {@code Some} if this is a {@code Some}, returns {@code None}. * * @param mapper A value mapper * @param The new value type * @return a new {@code Some} containing the mapped value if this Option is defined, otherwise {@code None}, if this is empty. */ @Override default Option map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? none() : some(mapper.apply(get())); } /** * Folds either the {@code None} or the {@code Some} side of the Option value. * * @param ifNone maps the left value if this is a None * @param f maps the value if this is a Some * @param type of the folded value * @return A value of type U */ default U fold(Supplier ifNone, Function f) { return this.map(f).getOrElse(ifNone); } /** * Applies an action to this value, if this option is defined, otherwise does nothing. * * @param action An action which can be applied to an optional value * @return this {@code Option} */ @Override default Option peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isDefined()) { action.accept(get()); } return this; } /** * Transforms this {@code Option}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override default Iterator iterator() { return isEmpty() ? Iterator.empty() : Iterator.of(get()); } @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); /** * Some represents a defined {@link Option}. It contains a value which may be null. However, to * create an Option containing null, {@code new Some(null)} has to be called. In all other cases * {@link Option#of(Object)} is sufficient. * * @param The type of the optional value. * @author Daniel Dietrich */ final class Some implements Option, Serializable { private static final long serialVersionUID = 1L; private final T value; /** * Creates a new Some containing the given value. * * @param value A value, may be null */ private Some(T value) { this.value = value; } @Override public T get() { return value; } @Override public boolean isEmpty() { return false; } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Some && Objects.equals(value, ((Some) obj).value)); } @Override public int hashCode() { return Objects.hashCode(value); } @Override public String stringPrefix() { return "Some"; } @Override public String toString() { return stringPrefix() + "(" + value + ")"; } } /** * None is a singleton representation of the undefined {@link Option}. * * @param The type of the optional value. * @author Daniel Dietrich */ final class None implements Option, Serializable { private static final long serialVersionUID = 1L; /** * The singleton instance of None. */ private static final None INSTANCE = new None<>(); /** * Hidden constructor. */ private None() { } @Override public T get() { throw new NoSuchElementException("No value present"); } @Override public boolean isEmpty() { return true; } @Override public boolean equals(Object o) { return o == this; } @Override public int hashCode() { return 1; } @Override public String stringPrefix() { return "None"; } @Override public String toString() { return stringPrefix(); } // -- Serializable implementation /** * Instance control for object serialization. * * @return The singleton instance of None. * @see Serializable */ private Object readResolve() { return INSTANCE; } } } vavr-0.10.0/vavr/src/main/java/io/vavr/control/Try.java000066400000000000000000002052711342074374400226650ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.control; import io.vavr.*; import io.vavr.collection.Seq; import io.vavr.collection.Iterator; import io.vavr.collection.Vector; import java.io.Serializable; import java.util.Arrays; import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.Callable; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import static io.vavr.API.Match; import static io.vavr.control.TryModule.isFatal; import static io.vavr.control.TryModule.sneakyThrow; /** * The Try control gives us the ability write safe code without focusing on try-catch blocks in the presence of exceptions. *

* The following exceptions are considered to be fatal/non-recoverable: *

    *
  • {@linkplain InterruptedException}
  • *
  • {@linkplain LinkageError}
  • *
  • {@linkplain ThreadDeath}
  • *
  • {@linkplain VirtualMachineError} (i.e. {@linkplain OutOfMemoryError} or {@linkplain StackOverflowError})
  • *
*

* Important note: Try may re-throw (undeclared) exceptions, e.g. on {@code get()}. From within a * dynamic proxy {@link java.lang.reflect.InvocationHandler} this will lead to an * {@link java.lang.reflect.UndeclaredThrowableException}. For more information, please read * Dynamic Proxy Classes. * * @param Value type in the case of success. * @author Daniel Dietrich */ public interface Try extends Value, Serializable { long serialVersionUID = 1L; /** * Creates a Try of a CheckedFunction0. * * @param supplier A checked supplier * @param Component type * @return {@code Success(supplier.apply())} if no exception occurs, otherwise {@code Failure(throwable)} if an * exception occurs calling {@code supplier.apply()}. */ static Try of(CheckedFunction0 supplier) { Objects.requireNonNull(supplier, "supplier is null"); try { return new Success<>(supplier.apply()); } catch (Throwable t) { return new Failure<>(t); } } /** * Creates a Try of a Supplier. * * @param supplier A supplier * @param Component type * @return {@code Success(supplier.get())} if no exception occurs, otherwise {@code Failure(throwable)} if an * exception occurs calling {@code supplier.get()}. */ static Try ofSupplier(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return of(supplier::get); } /** * Creates a Try of a Callable. * * @param callable A callable * @param Component type * @return {@code Success(callable.call())} if no exception occurs, otherwise {@code Failure(throwable)} if an * exception occurs calling {@code callable.call()}. */ static Try ofCallable(Callable callable) { Objects.requireNonNull(callable, "callable is null"); return of(callable::call); } /** * Creates a Try of a CheckedRunnable. * * @param runnable A checked runnable * @return {@code Success(null)} if no exception occurs, otherwise {@code Failure(throwable)} if an exception occurs * calling {@code runnable.run()}. */ static Try run(CheckedRunnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); try { runnable.run(); return new Success<>(null); // null represents the absence of an value, i.e. Void } catch (Throwable t) { return new Failure<>(t); } } /** * Creates a Try of a Runnable. * * @param runnable A runnable * @return {@code Success(null)} if no exception occurs, otherwise {@code Failure(throwable)} if an exception occurs * calling {@code runnable.run()}. */ static Try runRunnable(Runnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); return run(runnable::run); } /** * Reduces many {@code Try}s into a single {@code Try} by transforming an * {@code Iterable>} into a {@code Try>}. If any of * the {@code Try}s are {@link Try.Failure}, then this returns a {@link Try.Failure}. * * @param values An {@link Iterable} of {@code Try}s * @param type of the Trys * @return A {@code Try} of a {@link Seq} of results * @throws NullPointerException if {@code values} is null */ static Try> sequence(Iterable> values) { Objects.requireNonNull(values, "values is null"); Vector vector = Vector.empty(); for (Try value : values) { if (value.isFailure()) { return Try.failure(value.getCause()); } vector = vector.append(value.get()); } return Try.success(vector); } /** * Maps the values of an iterable to a sequence of mapped values into a single {@code Try} by * transforming an {@code Iterable} into a {@code Try>}. *

* * @param values An {@code Iterable} of values. * @param mapper A mapper of values to Trys * @param The type of the given values. * @param The mapped value type. * @return A {@code Try} of a {@link Seq} of results. * @throws NullPointerException if values or f is null. */ static Try> traverse(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); Objects.requireNonNull(mapper, "mapper is null"); return sequence(Iterator.ofAll(values).map(mapper)); } /** * Creates a {@link Success} that contains the given {@code value}. Shortcut for {@code new Success<>(value)}. * * @param value A value. * @param Type of the given {@code value}. * @return A new {@code Success}. */ static Try success(T value) { return new Success<>(value); } /** * Creates a {@link Failure} that contains the given {@code exception}. Shortcut for {@code new Failure<>(exception)}. * * @param exception An exception. * @param Component type of the {@code Try}. * @return A new {@code Failure}. */ static Try failure(Throwable exception) { return new Failure<>(exception); } /** * Narrows a widened {@code Try} to {@code Try} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param t A {@code Try}. * @param Component type of the {@code Try}. * @return the given {@code t} instance as narrowed type {@code Try}. */ @SuppressWarnings("unchecked") static Try narrow(Try t) { return (Try) t; } /** * Shortcut for {@code andThenTry(consumer::accept)}, see {@link #andThenTry(CheckedConsumer)}. * * @param consumer A consumer * @return this {@code Try} if this is a {@code Failure} or the consumer succeeded, otherwise the * {@code Failure} of the consumption. * @throws NullPointerException if {@code consumer} is null */ default Try andThen(Consumer consumer) { Objects.requireNonNull(consumer, "consumer is null"); return andThenTry(consumer::accept); } /** * Passes the result to the given {@code consumer} if this is a {@code Success}. *

* The main use case is chaining checked functions using method references: * *

     * 
     * Try.of(() -> 100)
     *    .andThen(i -> System.out.println(i));
     *
     * 
     * 
* * @param consumer A checked consumer * @return this {@code Try} if this is a {@code Failure} or the consumer succeeded, otherwise the * {@code Failure} of the consumption. * @throws NullPointerException if {@code consumer} is null */ default Try andThenTry(CheckedConsumer consumer) { Objects.requireNonNull(consumer, "consumer is null"); if (isFailure()) { return this; } else { try { consumer.accept(get()); return this; } catch (Throwable t) { return new Failure<>(t); } } } /** * Shortcut for {@code andThenTry(runnable::run)}, see {@link #andThenTry(CheckedRunnable)}. * * @param runnable A runnable * @return this {@code Try} if this is a {@code Failure} or the runnable succeeded, otherwise the * {@code Failure} of the run. * @throws NullPointerException if {@code runnable} is null */ default Try andThen(Runnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); return andThenTry(runnable::run); } /** * Runs the given runnable if this is a {@code Success}, otherwise returns this {@code Failure}. *

* The main use case is chaining runnables using method references: * *

     * 
     * Try.run(A::methodRef).andThen(B::methodRef).andThen(C::methodRef);
     * 
     * 
* * Please note that these lines are semantically the same: * *
     * 
     * Try.run(this::doStuff)
     *    .andThen(this::doMoreStuff)
     *    .andThen(this::doEvenMoreStuff);
     *
     * Try.run(() -> {
     *     doStuff();
     *     doMoreStuff();
     *     doEvenMoreStuff();
     * });
     * 
     * 
* * @param runnable A checked runnable * @return this {@code Try} if this is a {@code Failure} or the runnable succeeded, otherwise the * {@code Failure} of the run. * @throws NullPointerException if {@code runnable} is null */ default Try andThenTry(CheckedRunnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); if (isFailure()) { return this; } else { try { runnable.run(); return this; } catch (Throwable t) { return new Failure<>(t); } } } /** * Collects value that is in the domain of the given {@code partialFunction} by mapping the value to type {@code R}. * *
{@code
     * partialFunction.isDefinedAt(value)
     * }
* * If the element makes it through that filter, the mapped instance is wrapped in {@code Try} * *
{@code
     * R newValue = partialFunction.apply(value)
     * }
* * * @param partialFunction A function that is not necessarily defined on value of this try. * @param The new value type * @return A new {@code Try} instance containing value of type {@code R} * @throws NullPointerException if {@code partialFunction} is null */ @SuppressWarnings("unchecked") default Try collect(PartialFunction partialFunction){ Objects.requireNonNull(partialFunction, "partialFunction is null"); return filter(partialFunction::isDefinedAt).map(partialFunction::apply); } /** * Returns {@code Success(throwable)} if this is a {@code Failure(throwable)}, otherwise * a {@code Failure(new NoSuchElementException("Success.failed()"))} if this is a Success. * * @return a new Try */ default Try failed() { if (isFailure()) { return new Success<>(getCause()); } else { return new Failure<>(new NoSuchElementException("Success.failed()")); } } /** * Shortcut for {@code filterTry(predicate::test, throwableSupplier)}, see * {@link #filterTry(CheckedPredicate, Supplier)}}. * * @param predicate A predicate * @param throwableSupplier A supplier of a throwable * @return a {@code Try} instance * @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is null */ default Try filter(Predicate predicate, Supplier throwableSupplier) { Objects.requireNonNull(predicate, "predicate is null"); Objects.requireNonNull(throwableSupplier, "throwableSupplier is null"); return filterTry(predicate::test, throwableSupplier); } /** * Shortcut for {@code filterTry(predicate::test, errorProvider::apply)}, see * {@link #filterTry(CheckedPredicate, CheckedFunction1)}}. * * @param predicate A predicate * @param errorProvider A function that provides some kind of Throwable for T * @return a {@code Try} instance * @throws NullPointerException if {@code predicate} or {@code errorProvider} is null */ default Try filter(Predicate predicate, Function errorProvider) { Objects.requireNonNull(predicate, "predicate is null"); Objects.requireNonNull(errorProvider, "errorProvider is null"); return filterTry(predicate::test, errorProvider::apply); } /** * Shortcut for {@code filterTry(predicate::test)}, see {@link #filterTry(CheckedPredicate)}}. * * @param predicate A predicate * @return a {@code Try} instance * @throws NullPointerException if {@code predicate} is null */ default Try filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filterTry(predicate::test); } /** * Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate. *

* Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception * occurs testing the predicate. The returned Failure wraps a Throwable instance provided by the given * {@code throwableSupplier}. * * @param predicate A checked predicate * @param throwableSupplier A supplier of a throwable * @return a {@code Try} instance * @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is null */ default Try filterTry(CheckedPredicate predicate, Supplier throwableSupplier) { Objects.requireNonNull(predicate, "predicate is null"); Objects.requireNonNull(throwableSupplier, "throwableSupplier is null"); if (isFailure()) { return this; } else { try { if (predicate.test(get())) { return this; } else { return new Failure<>(throwableSupplier.get()); } } catch (Throwable t) { return new Failure<>(t); } } } /** * Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate. *

* Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception * occurs testing the predicate. The returned Failure wraps a Throwable instance provided by the given * {@code errorProvider}. * * @param predicate A checked predicate * @param errorProvider A provider of a throwable * @return a {@code Try} instance * @throws NullPointerException if {@code predicate} or {@code errorProvider} is null */ default Try filterTry(CheckedPredicate predicate, CheckedFunction1 errorProvider) { Objects.requireNonNull(predicate, "predicate is null"); Objects.requireNonNull(errorProvider, "errorProvider is null"); return flatMapTry(t -> predicate.test(t) ? this : failure(errorProvider.apply(t))); } /** * Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate. *

* Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception * occurs testing the predicate. The returned Failure wraps a {@link NoSuchElementException} instance. * * @param predicate A checked predicate * @return a {@code Try} instance * @throws NullPointerException if {@code predicate} is null */ default Try filterTry(CheckedPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filterTry(predicate, () -> new NoSuchElementException("Predicate does not hold for " + get())); } /** * Shortcut for {@code flatMapTry(mapper::apply)}, see {@link #flatMapTry(CheckedFunction1)}. * * @param mapper A mapper * @param The new component type * @return a {@code Try} * @throws NullPointerException if {@code mapper} is null */ default Try flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return flatMapTry((CheckedFunction1>) mapper::apply); } /** * FlatMaps the value of a Success or returns a Failure. * * @param mapper A mapper * @param The new component type * @return a {@code Try} * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") default Try flatMapTry(CheckedFunction1> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isFailure()) { return (Failure) this; } else { try { return (Try) mapper.apply(get()); } catch (Throwable t) { return new Failure<>(t); } } } /** * Gets the result of this Try if this is a {@code Success} or throws if this is a {@code Failure}. *

* IMPORTANT! If this is a {@link Failure}, the underlying {@code cause} of type {@link Throwable} is thrown. *

* The thrown exception is exactly the same as the result of {@link #getCause()}. * * @return The result of this {@code Try}. */ @Override T get(); /** * Gets the cause if this is a Failure or throws if this is a Success. * * @return The cause if this is a Failure * @throws UnsupportedOperationException if this is a Success */ Throwable getCause(); /** * A {@code Try}'s value is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } /** * Checks whether this Try has no result, i.e. is a Failure. * * @return true if this is a Failure, returns false if this is a Success. */ @Override boolean isEmpty(); /** * Checks if this is a Failure. * * @return true, if this is a Failure, otherwise false, if this is a Success */ boolean isFailure(); /** * A {@code Try}'s value is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } /** * A {@code Try} is a single-valued. * * @return {@code true} */ @Override default boolean isSingleValued() { return true; } /** * Checks if this is a Success. * * @return true, if this is a Success, otherwise false, if this is a Failure */ boolean isSuccess(); @Override default Iterator iterator() { return isSuccess() ? Iterator.of(get()) : Iterator.empty(); } /** * Shortcut for {@code mapTry(mapper::apply)}, see {@link #mapTry(CheckedFunction1)}. * * @param The new component type * @param mapper A checked function * @return a {@code Try} * @throws NullPointerException if {@code mapper} is null */ @Override default Try map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return mapTry(mapper::apply); } /** * Maps the cause to a new exception if this is a {@code Failure} or returns this instance if this is a {@code Success}. *

* If none of the given cases matches the cause, the same {@code Failure} is returned. * * @param cases A not necessarily exhaustive sequence of cases that will be matched against a cause. * @return A new {@code Try} if this is a {@code Failure}, otherwise this. */ @GwtIncompatible @SuppressWarnings({ "unchecked", "varargs" }) default Try mapFailure(Match.Case... cases) { if (isSuccess()) { return this; } else { final Option x = Match(getCause()).option(cases); return x.isEmpty() ? this : failure(x.get()); } } /** * Runs the given checked function if this is a {@link Try.Success}, * passing the result of the current expression to it. * If this expression is a {@link Try.Failure} then it'll return a new * {@link Try.Failure} of type R with the original exception. *

* The main use case is chaining checked functions using method references: * *

     * 
     * Try.of(() -> 0)
     *    .map(x -> 1 / x); // division by zero
     * 
     * 
* * @param The new component type * @param mapper A checked function * @return a {@code Try} * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") default Try mapTry(CheckedFunction1 mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isFailure()) { return (Failure) this; } else { try { return new Success<>(mapper.apply(get())); } catch (Throwable t) { return new Failure<>(t); } } } /** * Consumes the cause if this is a {@link Try.Failure}. * *
{@code
     * // (does not print anything)
     * Try.success(1).onFailure(System.out::println);
     *
     * // prints "java.lang.Error"
     * Try.failure(new Error()).onFailure(System.out::println);
     * }
* * @param action An exception consumer * @return this * @throws NullPointerException if {@code action} is null */ default Try onFailure(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isFailure()) { action.accept(getCause()); } return this; } /** * Consumes the cause if this is a {@link Try.Failure} and the cause is instance of {@code X}. * *
{@code
     * // (does not print anything)
     * Try.success(1).onFailure(Error.class, System.out::println);
     *
     * // prints "Error"
     * Try.failure(new Error())
     *    .onFailure(RuntimeException.class, x -> System.out.println("Runtime exception"))
     *    .onFailure(Error.class, x -> System.out.println("Error"));
     * }
* * @param exceptionType the exception type that is handled * @param action an excpetion consumer * @param the exception type that should be handled * @return this * @throws NullPointerException if {@code exceptionType} or {@code action} is null */ @GwtIncompatible @SuppressWarnings("unchecked") default Try onFailure(Class exceptionType, Consumer action) { Objects.requireNonNull(exceptionType, "exceptionType is null"); Objects.requireNonNull(action, "action is null"); if (isFailure() && exceptionType.isAssignableFrom(getCause().getClass())) { action.accept((X) getCause()); } return this; } /** * Consumes the value if this is a {@link Try.Success}. * *
{@code
     * // prints "1"
     * Try.success(1).onSuccess(System.out::println);
     *
     * // (does not print anything)
     * Try.failure(new Error()).onSuccess(System.out::println);
     * }
* * @param action A value consumer * @return this * @throws NullPointerException if {@code action} is null */ default Try onSuccess(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isSuccess()) { action.accept(get()); } return this; } @SuppressWarnings("unchecked") default Try orElse(Try other) { Objects.requireNonNull(other, "other is null"); return isSuccess() ? this : (Try) other; } @SuppressWarnings("unchecked") default Try orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isSuccess() ? this : (Try) supplier.get(); } default T getOrElseGet(Function other) { Objects.requireNonNull(other, "other is null"); if (isFailure()) { return other.apply(getCause()); } else { return get(); } } default void orElseRun(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isFailure()) { action.accept(getCause()); } } default T getOrElseThrow(Function exceptionProvider) throws X { Objects.requireNonNull(exceptionProvider, "exceptionProvider is null"); if (isFailure()) { throw exceptionProvider.apply(getCause()); } else { return get(); } } /** * Folds either the {@code Failure} or the {@code Success} side of the Try value. * * @param ifFail maps the left value if this is a {@code Failure} * @param f maps the value if this is a {@code Success} * @param type of the folded value * @return A value of type X */ default X fold(Function ifFail, Function f) { if (isFailure()) { return ifFail.apply(getCause()); } else { return f.apply(get()); } } /** * Applies the action to the value of a Success or does nothing in the case of a Failure. * * @param action A Consumer * @return this {@code Try} * @throws NullPointerException if {@code action} is null */ @Override default Try peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isSuccess()) { action.accept(get()); } return this; } /** * Returns {@code this}, if this is a {@code Success} or this is a {@code Failure} and the cause is not assignable * from {@code cause.getClass()}. Otherwise tries to recover the exception of the failure with {@code f}, * i.e. calling {@code Try.of(() -> f.apply((X) getCause())}. * *
{@code
     * // = Success(13)
     * Try.of(() -> 27/2).recover(ArithmeticException.class, x -> Integer.MAX_VALUE);
     *
     * // = Success(2147483647)
     * Try.of(() -> 1/0)
     *    .recover(Error.class, x -> -1)
     *    .recover(ArithmeticException.class, x -> Integer.MAX_VALUE);
     *
     * // = Failure(java.lang.ArithmeticException: / by zero)
     * Try.of(() -> 1/0).recover(Error.class, x -> Integer.MAX_VALUE);
     * }
* * @param Exception type * @param exceptionType The specific exception type that should be handled * @param f A recovery function taking an exception of type {@code X} * @return a {@code Try} * @throws NullPointerException if {@code exception} is null or {@code f} is null */ @GwtIncompatible @SuppressWarnings("unchecked") default Try recover(Class exceptionType, Function f) { Objects.requireNonNull(exceptionType, "exceptionType is null"); Objects.requireNonNull(f, "f is null"); if (isFailure()) { final Throwable cause = getCause(); if (exceptionType.isAssignableFrom(cause.getClass())) { return Try.of(() -> f.apply((X) cause)); } } return this; } /** * Returns {@code this}, if this is a {@code Success} or this is a {@code Failure} and the cause is not assignable * from {@code cause.getClass()}. Otherwise tries to recover the exception of the failure with {@code f} which returns Try. * If {@link Try#isFailure()} returned by {@code f} function is true it means that recovery cannot take place due to some circumstances. * *
{@code
     * // = Success(13)
     * Try.of(() -> 27/2).recoverWith(ArithmeticException.class, x -> Try.success(Integer.MAX_VALUE));
     *
     * // = Success(2147483647)
     * Try.of(() -> 1/0)
     *    .recoverWith(Error.class, x -> Try.success(-1))
     *    .recoverWith(ArithmeticException.class, x -> Try.success(Integer.MAX_VALUE));
     *
     * // = Failure(java.lang.ArithmeticException: / by zero)
     * Try.of(() -> 1/0).recoverWith(Error.class, x -> Try.success(Integer.MAX_VALUE));
     * }
* * @param Exception type * @param exceptionType The specific exception type that should be handled * @param f A recovery function taking an exception of type {@code X} and returning Try as a result of recovery. * If Try is {@link Try#isSuccess()} then recovery ends up successfully. Otherwise the function was not able to recover. * @return a {@code Try} * @throws NullPointerException if {@code exceptionType} or {@code f} is null */ @GwtIncompatible @SuppressWarnings("unchecked") default Try recoverWith(Class exceptionType, Function> f){ Objects.requireNonNull(exceptionType, "exceptionType is null"); Objects.requireNonNull(f, "f is null"); if(isFailure()){ final Throwable cause = getCause(); if (exceptionType.isAssignableFrom(cause.getClass())) { try { return narrow(f.apply((X) cause)); } catch (Throwable t) { return new Failure<>(t); } } } return this; } /** * Recovers this {@code Try} with the given {@code recovered}, if this is a {@link Try.Failure} * and the given {@code exceptionType} is assignable to the underlying cause type. * *
{@code
     * // = Success(13)
     * Try.of(() -> 27/2).recoverWith(ArithmeticException.class, Try.success(Integer.MAX_VALUE));
     *
     * // = Success(2147483647)
     * Try.of(() -> 1/0)
     *    .recoverWith(Error.class, Try.success(-1))
     *    .recoverWith(ArithmeticException.class, Try.success(Integer.MAX_VALUE));
     *
     * // = Failure(java.lang.ArithmeticException: / by zero)
     * Try.of(() -> 1/0).recoverWith(Error.class, Try.success(Integer.MAX_VALUE));
     * }
* * @param exceptionType the exception type that is recovered * @param recovered the substitute for a matching {@code Failure} * @param type of the exception that should be recovered * @return the given {@code recovered} if this is a {@link Try.Failure} and the cause is of type {@code X}, else {@code this} * @throws NullPointerException if {@code exceptionType} or {@code recovered} is null */ @GwtIncompatible default Try recoverWith(Class exceptionType, Try recovered){ Objects.requireNonNull(exceptionType, "exeptionType is null"); Objects.requireNonNull(recovered, "recovered is null"); return (isFailure() && exceptionType.isAssignableFrom(getCause().getClass())) ? narrow(recovered) : this; } /** * Returns {@code this}, if this is a {@link Try.Success} or this is a {@code Failure} and the cause is not assignable * from {@code cause.getClass()}. Otherwise returns a {@link Try.Success} containing the given {@code value}. * *
{@code
     * // = Success(13)
     * Try.of(() -> 27/2).recover(ArithmeticException.class, Integer.MAX_VALUE);
     *
     * // = Success(2147483647)
     * Try.of(() -> 1/0)
     *    .recover(Error.class, -1);
     *    .recover(ArithmeticException.class, Integer.MAX_VALUE);
     *
     * // = Failure(java.lang.ArithmeticException: / by zero)
     * Try.of(() -> 1/0).recover(Error.class, Integer.MAX_VALUE);
     * }
* * @param Exception type * @param exceptionType The specific exception type that should be handled * @param value A value that is used in case of a recovery * @return a {@code Try} * @throws NullPointerException if {@code exception} is null */ @GwtIncompatible default Try recover(Class exceptionType, T value) { Objects.requireNonNull(exceptionType, "exceptionType is null"); return (isFailure() && exceptionType.isAssignableFrom(getCause().getClass())) ? Try.success(value) : this; } /** * Returns {@code this}, if this is a {@code Success}, otherwise tries to recover the exception of the failure with {@code f}, * i.e. calling {@code Try.of(() -> f.apply(throwable))}. * *
{@code
     * // = Success(13)
     * Try.of(() -> 27/2).recover(x -> Integer.MAX_VALUE);
     *
     * // = Success(2147483647)
     * Try.of(() -> 1/0).recover(x -> Integer.MAX_VALUE);
     * }
* * @param f A recovery function taking a Throwable * @return a {@code Try} * @throws NullPointerException if {@code f} is null */ default Try recover(Function f) { Objects.requireNonNull(f, "f is null"); if (isFailure()) { return Try.of(() -> f.apply(getCause())); } else { return this; } } /** * Returns {@code this}, if this is a Success, otherwise tries to recover the exception of the failure with {@code f}, * i.e. calling {@code f.apply(cause.getCause())}. If an error occurs recovering a Failure, then the new Failure is * returned. * *
{@code
     * // = Success(13)
     * Try.of(() -> 27/2).recoverWith(x -> Try.success(Integer.MAX_VALUE));
     *
     * // = Success(2147483647)
     * Try.of(() -> 1/0).recoverWith(x -> Try.success(Integer.MAX_VALUE));
     * }
* * @param f A recovery function taking a Throwable * @return a {@code Try} * @throws NullPointerException if {@code f} is null */ @SuppressWarnings("unchecked") default Try recoverWith(Function> f) { Objects.requireNonNull(f, "f is null"); if (isFailure()) { try { return (Try) f.apply(getCause()); } catch (Throwable t) { return new Failure<>(t); } } else { return this; } } /** * Converts this {@code Try} to an {@link Either}. * * @return A new {@code Either} */ default Either toEither() { if (isFailure()) { return Either.left(getCause()); } else { return Either.right(get()); } } /** * Converts this {@code Try} to a {@link Validation}. * * @return A new {@code Validation} */ default Validation toValidation() { return toValidation(Function.identity()); } /** * Converts this {@code Try} to a {@link Validation}, converting the Throwable (if present) * to another object using passed {@link Function}. * *
{@code
     * Validation = Try.of(() -> 1/0).toValidation(Throwable::getMessage));
     * }
* * @param result type of the throwable mapper * @param throwableMapper A transformation from throwable to desired invalid type of new {@code Validation} * @return A new {@code Validation} * @throws NullPointerException if the given {@code throwableMapper} is null. */ default Validation toValidation(Function throwableMapper) { Objects.requireNonNull(throwableMapper, "throwableMapper is null"); if (isFailure()) { return Validation.invalid(throwableMapper.apply(getCause())); } else { return Validation.valid(get()); } } /** * Transforms this {@code Try}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } /** * Provides try's finally behavior no matter what the result of the operation is. * * @param runnable A runnable * @return this {@code Try}. * @throws NullPointerException if {@code runnable} is null */ default Try andFinally(Runnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); return andFinallyTry(runnable::run); } /** * Provides try's finally behavior no matter what the result of the operation is. * * @param runnable A runnable * @return this {@code Try}. * @throws NullPointerException if {@code runnable} is null */ default Try andFinallyTry(CheckedRunnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); try { runnable.run(); return this; } catch (Throwable t) { return new Failure<>(t); } } @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); /** * A succeeded Try. * * @param component type of this Success * @author Daniel Dietrich */ final class Success implements Try, Serializable { private static final long serialVersionUID = 1L; private final T value; /** * Constructs a Success. * * @param value The value of this Success. */ private Success(T value) { this.value = value; } @Override public T get() { return value; } @Override public Throwable getCause() { throw new UnsupportedOperationException("getCause on Success"); } @Override public boolean isEmpty() { return false; } @Override public boolean isFailure() { return false; } @Override public boolean isSuccess() { return true; } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Success && Objects.equals(value, ((Success) obj).value)); } @Override public int hashCode() { return Objects.hashCode(value); } @Override public String stringPrefix() { return "Success"; } @Override public String toString() { return stringPrefix() + "(" + value + ")"; } } /** * A failed Try. * * @param component type of this Failure * @author Daniel Dietrich */ final class Failure implements Try, Serializable { private static final long serialVersionUID = 1L; private final Throwable cause; /** * Constructs a Failure. * * @param cause A cause of type Throwable, may not be null. * @throws NullPointerException if {@code cause} is null * @throws Throwable if the given {@code cause} is fatal, i.e. non-recoverable */ private Failure(Throwable cause) { Objects.requireNonNull(cause, "cause is null"); if (isFatal(cause)) { sneakyThrow(cause); } this.cause = cause; } @Override public T get() { return sneakyThrow(cause); } @Override public Throwable getCause() { return cause; } @Override public boolean isEmpty() { return true; } @Override public boolean isFailure() { return true; } @Override public boolean isSuccess() { return false; } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Failure && Arrays.deepEquals(cause.getStackTrace(), ((Failure) obj).cause.getStackTrace())); } @Override public String stringPrefix() { return "Failure"; } @Override public int hashCode() { return Arrays.hashCode(cause.getStackTrace()); } @Override public String toString() { return stringPrefix() + "(" + cause + ")"; } } // -- try with resources /** * Creates a {@code Try}-with-resources builder that operates on one {@link AutoCloseable} resource. * * @param t1Supplier The supplier of the first resource. * @param Type of the 1st resource. * @return a new {@link WithResources1} instance. */ static WithResources1 withResources(CheckedFunction0 t1Supplier) { return new WithResources1<>(t1Supplier); } /** * Creates a {@code Try}-with-resources builder that operates on two {@link AutoCloseable} resources. * * @param t1Supplier The supplier of the 1st resource. * @param t2Supplier The supplier of the 2nd resource. * @param Type of the 1st resource. * @param Type of the 2nd resource. * @return a new {@link WithResources2} instance. */ static WithResources2 withResources(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier) { return new WithResources2<>(t1Supplier, t2Supplier); } /** * Creates a {@code Try}-with-resources builder that operates on three {@link AutoCloseable} resources. * * @param t1Supplier The supplier of the 1st resource. * @param t2Supplier The supplier of the 2nd resource. * @param t3Supplier The supplier of the 3rd resource. * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @return a new {@link WithResources3} instance. */ static WithResources3 withResources(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier) { return new WithResources3<>(t1Supplier, t2Supplier, t3Supplier); } /** * Creates a {@code Try}-with-resources builder that operates on four {@link AutoCloseable} resources. * * @param t1Supplier The supplier of the 1st resource. * @param t2Supplier The supplier of the 2nd resource. * @param t3Supplier The supplier of the 3rd resource. * @param t4Supplier The supplier of the 4th resource. * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @return a new {@link WithResources4} instance. */ static WithResources4 withResources(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier) { return new WithResources4<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier); } /** * Creates a {@code Try}-with-resources builder that operates on five {@link AutoCloseable} resources. * * @param t1Supplier The supplier of the 1st resource. * @param t2Supplier The supplier of the 2nd resource. * @param t3Supplier The supplier of the 3rd resource. * @param t4Supplier The supplier of the 4th resource. * @param t5Supplier The supplier of the 5th resource. * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. * @return a new {@link WithResources5} instance. */ static WithResources5 withResources(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier) { return new WithResources5<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier); } /** * Creates a {@code Try}-with-resources builder that operates on six {@link AutoCloseable} resources. * * @param t1Supplier The supplier of the 1st resource. * @param t2Supplier The supplier of the 2nd resource. * @param t3Supplier The supplier of the 3rd resource. * @param t4Supplier The supplier of the 4th resource. * @param t5Supplier The supplier of the 5th resource. * @param t6Supplier The supplier of the 6th resource. * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. * @param Type of the 6th resource. * @return a new {@link WithResources6} instance. */ static WithResources6 withResources(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier, CheckedFunction0 t6Supplier) { return new WithResources6<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier, t6Supplier); } /** * Creates a {@code Try}-with-resources builder that operates on seven {@link AutoCloseable} resources. * * @param t1Supplier The supplier of the 1st resource. * @param t2Supplier The supplier of the 2nd resource. * @param t3Supplier The supplier of the 3rd resource. * @param t4Supplier The supplier of the 4th resource. * @param t5Supplier The supplier of the 5th resource. * @param t6Supplier The supplier of the 6th resource. * @param t7Supplier The supplier of the 7th resource. * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. * @param Type of the 6th resource. * @param Type of the 7th resource. * @return a new {@link WithResources7} instance. */ static WithResources7 withResources(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier, CheckedFunction0 t6Supplier, CheckedFunction0 t7Supplier) { return new WithResources7<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier, t6Supplier, t7Supplier); } /** * Creates a {@code Try}-with-resources builder that operates on eight {@link AutoCloseable} resources. * * @param t1Supplier The supplier of the 1st resource. * @param t2Supplier The supplier of the 2nd resource. * @param t3Supplier The supplier of the 3rd resource. * @param t4Supplier The supplier of the 4th resource. * @param t5Supplier The supplier of the 5th resource. * @param t6Supplier The supplier of the 6th resource. * @param t7Supplier The supplier of the 7th resource. * @param t8Supplier The supplier of the 8th resource. * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. * @param Type of the 6th resource. * @param Type of the 7th resource. * @param Type of the 8th resource. * @return a new {@link WithResources8} instance. */ static WithResources8 withResources(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier, CheckedFunction0 t6Supplier, CheckedFunction0 t7Supplier, CheckedFunction0 t8Supplier) { return new WithResources8<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier, t6Supplier, t7Supplier, t8Supplier); } /** * A {@code Try}-with-resources builder that operates on one {@link AutoCloseable} resource. * * @param Type of the 1st resource. */ final class WithResources1 { private final CheckedFunction0 t1Supplier; private WithResources1(CheckedFunction0 t1Supplier) { this.t1Supplier = t1Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes one {@code AutoClosable} resource. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ public Try of(CheckedFunction1 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply()) { return f.apply(t1); } }); } } /** * A {@code Try}-with-resources builder that operates on two {@link AutoCloseable} resources. * * @param Type of the 1st resource. * @param Type of the 2nd resource. */ final class WithResources2 { private final CheckedFunction0 t1Supplier; private final CheckedFunction0 t2Supplier; private WithResources2(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier) { this.t1Supplier = t1Supplier; this.t2Supplier = t2Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes two {@code AutoClosable} resources. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ public Try of(CheckedFunction2 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply()) { return f.apply(t1, t2); } }); } } /** * A {@code Try}-with-resources builder that operates on three {@link AutoCloseable} resources. * * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. */ final class WithResources3 { private final CheckedFunction0 t1Supplier; private final CheckedFunction0 t2Supplier; private final CheckedFunction0 t3Supplier; private WithResources3(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier) { this.t1Supplier = t1Supplier; this.t2Supplier = t2Supplier; this.t3Supplier = t3Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes three {@code AutoClosable} resources. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ public Try of(CheckedFunction3 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply()) { return f.apply(t1, t2, t3); } }); } } /** * A {@code Try}-with-resources builder that operates on four {@link AutoCloseable} resources. * * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. */ final class WithResources4 { private final CheckedFunction0 t1Supplier; private final CheckedFunction0 t2Supplier; private final CheckedFunction0 t3Supplier; private final CheckedFunction0 t4Supplier; private WithResources4(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier) { this.t1Supplier = t1Supplier; this.t2Supplier = t2Supplier; this.t3Supplier = t3Supplier; this.t4Supplier = t4Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes four {@code AutoClosable} resources. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ public Try of(CheckedFunction4 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply()) { return f.apply(t1, t2, t3, t4); } }); } } /** * A {@code Try}-with-resources builder that operates on five {@link AutoCloseable} resources. * * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. */ final class WithResources5 { private final CheckedFunction0 t1Supplier; private final CheckedFunction0 t2Supplier; private final CheckedFunction0 t3Supplier; private final CheckedFunction0 t4Supplier; private final CheckedFunction0 t5Supplier; private WithResources5(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier) { this.t1Supplier = t1Supplier; this.t2Supplier = t2Supplier; this.t3Supplier = t3Supplier; this.t4Supplier = t4Supplier; this.t5Supplier = t5Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes five {@code AutoClosable} resources. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ public Try of(CheckedFunction5 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply()) { return f.apply(t1, t2, t3, t4, t5); } }); } } /** * A {@code Try}-with-resources builder that operates on six {@link AutoCloseable} resources. * * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. * @param Type of the 6th resource. */ final class WithResources6 { private final CheckedFunction0 t1Supplier; private final CheckedFunction0 t2Supplier; private final CheckedFunction0 t3Supplier; private final CheckedFunction0 t4Supplier; private final CheckedFunction0 t5Supplier; private final CheckedFunction0 t6Supplier; private WithResources6(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier, CheckedFunction0 t6Supplier) { this.t1Supplier = t1Supplier; this.t2Supplier = t2Supplier; this.t3Supplier = t3Supplier; this.t4Supplier = t4Supplier; this.t5Supplier = t5Supplier; this.t6Supplier = t6Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes six {@code AutoClosable} resources. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ public Try of(CheckedFunction6 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply(); T6 t6 = t6Supplier.apply()) { return f.apply(t1, t2, t3, t4, t5, t6); } }); } } /** * A {@code Try}-with-resources builder that operates on seven {@link AutoCloseable} resources. * * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. * @param Type of the 6th resource. * @param Type of the 7th resource. */ final class WithResources7 { private final CheckedFunction0 t1Supplier; private final CheckedFunction0 t2Supplier; private final CheckedFunction0 t3Supplier; private final CheckedFunction0 t4Supplier; private final CheckedFunction0 t5Supplier; private final CheckedFunction0 t6Supplier; private final CheckedFunction0 t7Supplier; private WithResources7(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier, CheckedFunction0 t6Supplier, CheckedFunction0 t7Supplier) { this.t1Supplier = t1Supplier; this.t2Supplier = t2Supplier; this.t3Supplier = t3Supplier; this.t4Supplier = t4Supplier; this.t5Supplier = t5Supplier; this.t6Supplier = t6Supplier; this.t7Supplier = t7Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes seven {@code AutoClosable} resources. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ public Try of(CheckedFunction7 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply(); T6 t6 = t6Supplier.apply(); T7 t7 = t7Supplier.apply()) { return f.apply(t1, t2, t3, t4, t5, t6, t7); } }); } } /** * A {@code Try}-with-resources builder that operates on eight {@link AutoCloseable} resources. * * @param Type of the 1st resource. * @param Type of the 2nd resource. * @param Type of the 3rd resource. * @param Type of the 4th resource. * @param Type of the 5th resource. * @param Type of the 6th resource. * @param Type of the 7th resource. * @param Type of the 8th resource. */ final class WithResources8 { private final CheckedFunction0 t1Supplier; private final CheckedFunction0 t2Supplier; private final CheckedFunction0 t3Supplier; private final CheckedFunction0 t4Supplier; private final CheckedFunction0 t5Supplier; private final CheckedFunction0 t6Supplier; private final CheckedFunction0 t7Supplier; private final CheckedFunction0 t8Supplier; private WithResources8(CheckedFunction0 t1Supplier, CheckedFunction0 t2Supplier, CheckedFunction0 t3Supplier, CheckedFunction0 t4Supplier, CheckedFunction0 t5Supplier, CheckedFunction0 t6Supplier, CheckedFunction0 t7Supplier, CheckedFunction0 t8Supplier) { this.t1Supplier = t1Supplier; this.t2Supplier = t2Supplier; this.t3Supplier = t3Supplier; this.t4Supplier = t4Supplier; this.t5Supplier = t5Supplier; this.t6Supplier = t6Supplier; this.t7Supplier = t7Supplier; this.t8Supplier = t8Supplier; } /** * Wraps the result of a computation that may fail in a {@code Try}. * * @param f A computation that takes eight {@code AutoClosable} resources. * @param Result type of the computation. * @return A new {@code Try} instance. */ @SuppressWarnings("try"/* https://bugs.openjdk.java.net/browse/JDK-8155591 */) public Try of(CheckedFunction8 f) { return Try.of(() -> { try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply(); T6 t6 = t6Supplier.apply(); T7 t7 = t7Supplier.apply(); T8 t8 = t8Supplier.apply()) { return f.apply(t1, t2, t3, t4, t5, t6, t7, t8); } }); } } } interface TryModule { static boolean isFatal(Throwable throwable) { return throwable instanceof InterruptedException || throwable instanceof LinkageError || throwable instanceof ThreadDeath || throwable instanceof VirtualMachineError; } // DEV-NOTE: we do not plan to expose this as public API @SuppressWarnings("unchecked") static R sneakyThrow(Throwable t) throws T { throw (T) t; } } vavr-0.10.0/vavr/src/main/java/io/vavr/control/Validation.java000066400000000000000000001101151342074374400241710ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.control; import io.vavr.*; import io.vavr.collection.Seq; import io.vavr.collection.Iterator; import io.vavr.collection.List; import java.io.Serializable; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * An implementation similar to scalaz's Validation control. * *

* The Validation type is different from a Monad type, it is an applicative * functor. Whereas a Monad will short circuit after the first error, the * applicative functor will continue on, accumulating ALL errors. This is * especially helpful in cases such as validation, where you want to know * all the validation errors that have occurred, not just the first one. *

* *
 * 
 * Validation construction:
 *
 * Valid:
 * Validation<String,Integer> valid = Validation.valid(5);
 *
 * Invalid:
 * Validation<List<String>,Integer> invalid = Validation.invalid(List.of("error1","error2"));
 *
 * Validation combination:
 *
 * Validation<String,String> valid1 = Validation.valid("John");
 * Validation<String,Integer> valid2 = Validation.valid(5);
 * Validation<String,Option<String>> valid3 = Validation.valid(Option.of("123 Fake St."));
 * Function3<String,Integer,Option<String>,Person> f = ...;
 *
 * Validation<List<String>,String> result = valid1.combine(valid2).ap((name,age) -> "Name: "+name+" Age: "+age);
 * Validation<List<String>,Person> result2 = valid1.combine(valid2).combine(valid3).ap(f);
 *
 * Another form of combining validations:
 *
 * Validation<List<String>,Person> result3 = Validation.combine(valid1, valid2, valid3).ap(f);
 * 
 * 
* * @param value type in the case of invalid * @param value type in the case of valid * @author Eric Nelson * @see Validation */ public interface Validation extends Value, Serializable { long serialVersionUID = 1L; /** * Creates a {@link Valid} that contains the given {@code value}. * * @param type of the error * @param type of the given {@code value} * @param value A value * @return {@code Valid(value)} */ static Validation valid(T value) { return new Valid<>(value); } /** * Creates an {@link Invalid} that contains the given {@code error}. * * @param type of the given {@code error} * @param type of the value * @param error An error * @return {@code Invalid(error)} * @throws NullPointerException if error is null */ static Validation invalid(E error) { Objects.requireNonNull(error, "error is null"); return new Invalid<>(error); } /** * Creates a {@code Validation} of an {@code Either}. * * @param either An {@code Either} * @param error type * @param value type * @return A {@code Valid(either.get())} if either is a Right, otherwise {@code Invalid(either.getLeft())}. * @throws NullPointerException if either is null */ static Validation fromEither(Either either) { Objects.requireNonNull(either, "either is null"); return either.isRight() ? valid(either.get()) : invalid(either.getLeft()); } /** * Creates a {@code Validation} of an {@code Try}. * * @param t A {@code Try} * @param type of the valid value * @return A {@code Valid(t.get())} if t is a Success, otherwise {@code Invalid(t.getCause())}. * @throws NullPointerException if {@code t} is null */ static Validation fromTry(Try t) { Objects.requireNonNull(t, "t is null"); return t.isSuccess() ? valid(t.get()) : invalid(t.getCause()); } /** * Reduces many {@code Validation} instances into a single {@code Validation} by transforming an * {@code Iterable>} into a {@code Validation>}. * * @param value type in the case of invalid * @param value type in the case of valid * @param values An iterable of Validation instances. * @return A valid Validation of a sequence of values if all Validation instances are valid * or an invalid Validation containing an accumulated List of errors. * @throws NullPointerException if values is null */ static Validation, Seq> sequence(Iterable, ? extends T>> values) { Objects.requireNonNull(values, "values is null"); List errors = List.empty(); List list = List.empty(); for (Validation, ? extends T> value : values) { if (value.isInvalid()) { errors = errors.prependAll(value.getError().reverse()); } else if (errors.isEmpty()) { list = list.prepend(value.get()); } } return errors.isEmpty() ? valid(list.reverse()) : invalid(errors.reverse()); } /** * Maps the values of an iterable to a sequence of mapped values into a single {@code Validation} by * transforming an {@code Iterable} into a {@code Validation>}. *

* * @param values An {@code Iterable} of values. * @param mapper A mapper of values to Validations * @param The type of the given values. * @param The mapped error value type. * @param The mapped valid value type. * @return A {@code Validation} of a {@link Seq} of results. * @throws NullPointerException if values or f is null. */ static Validation, Seq> traverse(Iterable values, Function, ? extends U>> mapper) { Objects.requireNonNull(values, "values is null"); Objects.requireNonNull(mapper, "mapper is null"); return sequence(Iterator.ofAll(values).map(mapper)); } /** * Narrows a widened {@code Validation} to {@code Validation} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param validation A {@code Validation}. * @param type of error * @param type of valid value * @return the given {@code validation} instance as narrowed type {@code Validation}. */ @SuppressWarnings("unchecked") static Validation narrow(Validation validation) { return (Validation) validation; } /** * Combines two {@code Validation}s into a {@link Builder}. * * @param type of error * @param type of first valid value * @param type of second valid value * @param validation1 first validation * @param validation2 second validation * @return an instance of Builder<E,T1,T2> * @throws NullPointerException if validation1 or validation2 is null */ static Builder combine(Validation validation1, Validation validation2) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); return new Builder<>(validation1, validation2); } /** * Combines three {@code Validation}s into a {@link Builder3}. * * @param type of error * @param type of first valid value * @param type of second valid value * @param type of third valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @return an instance of Builder3<E,T1,T2,T3> * @throws NullPointerException if validation1, validation2 or validation3 is null */ static Builder3 combine(Validation validation1, Validation validation2, Validation validation3) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); return new Builder3<>(validation1, validation2, validation3); } /** * Combines four {@code Validation}s into a {@link Builder4}. * * @param type of error * @param type of first valid value * @param type of second valid value * @param type of third valid value * @param type of fourth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @return an instance of Builder3<E,T1,T2,T3,T4> * @throws NullPointerException if validation1, validation2, validation3 or validation4 is null */ static Builder4 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); return new Builder4<>(validation1, validation2, validation3, validation4); } /** * Combines five {@code Validation}s into a {@link Builder5}. * * @param type of error * @param type of first valid value * @param type of second valid value * @param type of third valid value * @param type of fourth valid value * @param type of fifth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5> * @throws NullPointerException if validation1, validation2, validation3, validation4 or validation5 is null */ static Builder5 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); return new Builder5<>(validation1, validation2, validation3, validation4, validation5); } /** * Combines six {@code Validation}s into a {@link Builder6}. * * @param type of error * @param type of first valid value * @param type of second valid value * @param type of third valid value * @param type of fourth valid value * @param type of fifth valid value * @param type of sixth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @param validation6 sixth validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6> * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5 or validation6 is null */ static Builder6 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5, Validation validation6) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); Objects.requireNonNull(validation6, "validation6 is null"); return new Builder6<>(validation1, validation2, validation3, validation4, validation5, validation6); } /** * Combines seven {@code Validation}s into a {@link Builder7}. * * @param type of error * @param type of first valid value * @param type of second valid value * @param type of third valid value * @param type of fourth valid value * @param type of fifth valid value * @param type of sixth valid value * @param type of seventh valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @param validation6 sixth validation * @param validation7 seventh validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6,T7> * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5, validation6 or validation7 is null */ static Builder7 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5, Validation validation6, Validation validation7) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); Objects.requireNonNull(validation6, "validation6 is null"); Objects.requireNonNull(validation7, "validation7 is null"); return new Builder7<>(validation1, validation2, validation3, validation4, validation5, validation6, validation7); } /** * Combines eight {@code Validation}s into a {@link Builder8}. * * @param type of error * @param type of first valid value * @param type of second valid value * @param type of third valid value * @param type of fourth valid value * @param type of fifth valid value * @param type of sixth valid value * @param type of seventh valid value * @param type of eighth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @param validation6 sixth validation * @param validation7 seventh validation * @param validation8 eighth validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6,T7,T8> * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5, validation6, validation7 or validation8 is null */ static Builder8 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5, Validation validation6, Validation validation7, Validation validation8) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); Objects.requireNonNull(validation6, "validation6 is null"); Objects.requireNonNull(validation7, "validation7 is null"); Objects.requireNonNull(validation8, "validation8 is null"); return new Builder8<>(validation1, validation2, validation3, validation4, validation5, validation6, validation7, validation8); } /** * Check whether this is of type {@code Valid} * * @return true if is a Valid, false if is an Invalid */ boolean isValid(); /** * Check whether this is of type {@code Invalid} * * @return true if is an Invalid, false if is a Valid */ boolean isInvalid(); /** * Returns this {@code Validation} if it is valid, otherwise return the alternative. * * @param other An alternative {@code Validation} * @return this {@code Validation} if it is valid, otherwise return the alternative. */ @SuppressWarnings("unchecked") default Validation orElse(Validation other) { Objects.requireNonNull(other, "other is null"); return isValid() ? this : (Validation) other; } /** * Returns this {@code Validation} if it is valid, otherwise return the result of evaluating supplier. * * @param supplier An alternative {@code Validation} supplier * @return this {@code Validation} if it is valid, otherwise return the result of evaluating supplier. */ @SuppressWarnings("unchecked") default Validation orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isValid() ? this : (Validation) supplier.get(); } @Override default boolean isEmpty() { return isInvalid(); } /** * Gets the value of this {@code Validation} if is a {@code Valid} or throws if this is an {@code Invalid}. * * @return The value of this {@code Validation} * @throws NoSuchElementException if this is an {@code Invalid} */ @Override T get(); /** * Gets the value if it is a Valid or an value calculated from the error. * * @param other a function which converts an error to an alternative value * @return the value, if the underlying Validation is a Valid, or else the alternative value * provided by {@code other} by applying the error. */ default T getOrElseGet(Function other) { Objects.requireNonNull(other, "other is null"); if (isValid()) { return get(); } else { return other.apply(getError()); } } /** * Gets the error of this Validation if it is an {@code Invalid} or throws if this is a {@code Valid}. * * @return The error, if present * @throws RuntimeException if this is a {@code Valid} */ E getError(); /** * Converts this Validation to an {@link Either}. * * @return {@code Either.right(get())} if this is valid, otherwise {@code Either.left(getError())}. */ default Either toEither() { return isValid() ? Either.right(get()) : Either.left(getError()); } @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); /** * Performs the given action for the value contained in {@code Valid}, or does nothing * if this is an {@code Invalid}. * * @param action the action to be performed on the contained value * @throws NullPointerException if action is null */ @Override default void forEach(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isValid()) { action.accept(get()); } } /** * Transforms this {@code Validation} to a value of type {@code U}. *

* Example: *

{@code
     * Validation, String> valid = ...;
* int i = valid.fold(List::length, String::length); * }
* * @param the fold result type * @param ifInvalid an error mapper * @param ifValid an mapper for a valid value * @return {@code ifValid.apply(get())} if this is valid, otherwise {@code ifInvalid.apply(getError())}. * @throws NullPointerException if one of the given mappers {@code ifInvalid} or {@code ifValid} is null */ default U fold(Function ifInvalid, Function ifValid) { Objects.requireNonNull(ifInvalid, "ifInvalid is null"); Objects.requireNonNull(ifValid, "ifValid is null"); return isValid() ? ifValid.apply(get()) : ifInvalid.apply(getError()); } /** * Flip the valid/invalid values for this Validation. If this is a Valid<E,T>, returns Invalid<T,E>. * Or if this is an Invalid<E,T>, return a Valid<T,E>. * * @return a flipped instance of Validation */ default Validation swap() { if (isInvalid()) { final E error = this.getError(); return Validation.valid(error); } else { final T value = this.get(); return Validation.invalid(value); } } @Override default Validation map(Function f) { Objects.requireNonNull(f, "f is null"); if (isInvalid()) { return Validation.invalid(this.getError()); } else { final T value = this.get(); return Validation.valid(f.apply(value)); } } /** * Whereas map only performs a mapping on a valid Validation, and mapError performs a mapping on an invalid * Validation, bimap allows you to provide mapping actions for both, and will give you the result based * on what type of Validation this is. Without this, you would have to do something like: * * validation.map(...).mapError(...); * * @param type of the mapping result if this is an invalid * @param type of the mapping result if this is a valid * @param errorMapper the invalid mapping operation * @param valueMapper the valid mapping operation * @return an instance of Validation<U,R> * @throws NullPointerException if invalidMapper or validMapper is null */ default Validation bimap(Function errorMapper, Function valueMapper) { Objects.requireNonNull(errorMapper, "errorMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); if (isInvalid()) { final E error = this.getError(); return Validation.invalid(errorMapper.apply(error)); } else { final T value = this.get(); return Validation.valid(valueMapper.apply(value)); } } /** * Applies a function f to the error of this Validation if this is an Invalid. Otherwise does nothing * if this is a Valid. * * @param type of the error resulting from the mapping * @param f a function that maps the error in this Invalid * @return an instance of Validation<U,T> * @throws NullPointerException if mapping operation f is null */ default Validation mapError(Function f) { Objects.requireNonNull(f, "f is null"); if (isInvalid()) { final E error = this.getError(); return Validation.invalid(f.apply(error)); } else { return Validation.valid(this.get()); } } default Validation, U> ap(Validation, ? extends Function> validation) { Objects.requireNonNull(validation, "validation is null"); if (isValid()) { if (validation.isValid()) { final Function f = validation.get(); final U u = f.apply(this.get()); return valid(u); } else { final Seq errors = validation.getError(); return invalid(errors); } } else { if (validation.isValid()) { final E error = this.getError(); return invalid(List.of(error)); } else { final Seq errors = validation.getError(); final E error = this.getError(); return invalid(errors.append(error)); } } } /** * Combines two {@code Validation}s to form a {@link Builder}, which can then be used to perform further * combines, or apply a function to it in order to transform the {@link Builder} into a {@code Validation}. * * @param type of the value contained in validation * @param validation the validation object to combine this with * @return an instance of Builder */ default Builder combine(Validation validation) { return new Builder<>(this, validation); } // -- Implementation of Value default Option> filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return isInvalid() || predicate.test(get()) ? Option.some(this) : Option.none(); } @SuppressWarnings("unchecked") default Validation flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isInvalid() ? (Validation) this : (Validation) mapper.apply(get()); } @Override default Validation peek(Consumer action) { if (isValid()) { action.accept(get()); } return this; } /** * A {@code Validation}'s value is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } /** * A {@code Validation}'s value is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } @Override default boolean isSingleValued() { return true; } @Override default Iterator iterator() { return isValid() ? Iterator.of(get()) : Iterator.empty(); } /** * A valid Validation * * @param type of the error of this Validation * @param type of the value of this Validation */ final class Valid implements Validation, Serializable { private static final long serialVersionUID = 1L; private final T value; /** * Construct a {@code Valid} * * @param value The value of this success */ private Valid(T value) { this.value = value; } @Override public boolean isValid() { return true; } @Override public boolean isInvalid() { return false; } @Override public T get() { return value; } @Override public E getError() throws RuntimeException { throw new NoSuchElementException("error of 'valid' Validation"); } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Valid && Objects.equals(value, ((Valid) obj).value)); } @Override public int hashCode() { return Objects.hashCode(value); } @Override public String stringPrefix() { return "Valid"; } @Override public String toString() { return stringPrefix() + "(" + value + ")"; } } /** * An invalid Validation * * @param type of the error of this Validation * @param type of the value of this Validation */ final class Invalid implements Validation, Serializable { private static final long serialVersionUID = 1L; private final E error; /** * Construct an {@code Invalid} * * @param error The value of this error */ private Invalid(E error) { this.error = error; } @Override public boolean isValid() { return false; } @Override public boolean isInvalid() { return true; } @Override public T get() throws RuntimeException { throw new NoSuchElementException("get of 'invalid' Validation"); } @Override public E getError() { return error; } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Invalid && Objects.equals(error, ((Invalid) obj).error)); } @Override public int hashCode() { return Objects.hashCode(error); } @Override public String stringPrefix() { return "Invalid"; } @Override public String toString() { return stringPrefix() + "(" + error + ")"; } } final class Builder { private Validation v1; private Validation v2; private Builder(Validation v1, Validation v2) { this.v1 = v1; this.v2 = v2; } public Validation, R> ap(Function2 f) { return v2.ap(v1.ap(Validation.valid(f.curried()))); } public Builder3 combine(Validation v3) { return new Builder3<>(v1, v2, v3); } } final class Builder3 { private Validation v1; private Validation v2; private Validation v3; private Builder3(Validation v1, Validation v2, Validation v3) { this.v1 = v1; this.v2 = v2; this.v3 = v3; } public Validation, R> ap(Function3 f) { return v3.ap(v2.ap(v1.ap(Validation.valid(f.curried())))); } public Builder4 combine(Validation v4) { return new Builder4<>(v1, v2, v3, v4); } } final class Builder4 { private Validation v1; private Validation v2; private Validation v3; private Validation v4; private Builder4(Validation v1, Validation v2, Validation v3, Validation v4) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; } public Validation, R> ap(Function4 f) { return v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried()))))); } public Builder5 combine(Validation v5) { return new Builder5<>(v1, v2, v3, v4, v5); } } final class Builder5 { private Validation v1; private Validation v2; private Validation v3; private Validation v4; private Validation v5; private Builder5(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; } public Validation, R> ap(Function5 f) { return v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried())))))); } public Builder6 combine(Validation v6) { return new Builder6<>(v1, v2, v3, v4, v5, v6); } } final class Builder6 { private Validation v1; private Validation v2; private Validation v3; private Validation v4; private Validation v5; private Validation v6; private Builder6(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5, Validation v6) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; this.v6 = v6; } public Validation, R> ap(Function6 f) { return v6.ap(v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried()))))))); } public Builder7 combine(Validation v7) { return new Builder7<>(v1, v2, v3, v4, v5, v6, v7); } } final class Builder7 { private Validation v1; private Validation v2; private Validation v3; private Validation v4; private Validation v5; private Validation v6; private Validation v7; private Builder7(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; this.v6 = v6; this.v7 = v7; } public Validation, R> ap(Function7 f) { return v7.ap(v6.ap(v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried())))))))); } public Builder8 combine(Validation v8) { return new Builder8<>(v1, v2, v3, v4, v5, v6, v7, v8); } } final class Builder8 { private Validation v1; private Validation v2; private Validation v3; private Validation v4; private Validation v5; private Validation v6; private Validation v7; private Validation v8; private Builder8(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; this.v6 = v6; this.v7 = v7; this.v8 = v8; } public Validation, R> ap(Function8 f) { return v8.ap(v7.ap(v6.ap(v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried()))))))))); } } } vavr-0.10.0/vavr/src/main/java/io/vavr/control/package-info.java000066400000000000000000000026211342074374400244250ustar00rootroot00000000000000/** * Control structures like the disjoint union type {@linkplain io.vavr.control.Either}, the optional value type * {@linkplain io.vavr.control.Option} and {@linkplain io.vavr.control.Try} for exception handling. *

* Either *

* The control package contains an implementation of the {@linkplain io.vavr.control.Either} control which is either Left or Right. * A given Either is projected to a Left or a Right. * Both cases can be further processed with control operations map, flatMap, filter. * If a Right is projected to a Left, the Left control operations have no effect on the Right value. * If a Left is projected to a Right, the Right control operations have no effect on the Left value. *

* Option *

* The Option control is a replacement for {@linkplain java.util.Optional}. An Option is either * {@linkplain io.vavr.control.Option.Some} value or {@linkplain io.vavr.control.Option.None}. * In contrast to Optional, Option supports null values, i.e. it is possible to call {@code new Some(null)}. * However, {@code Option.of(null)} results in None. *

* Try *

* Exceptions are handled with the {@linkplain io.vavr.control.Try} control which is either a * {@linkplain io.vavr.control.Try.Success}, containing a result, or a {@linkplain io.vavr.control.Try.Failure}, * containing an Exception. */ package io.vavr.control; vavr-0.10.0/vavr/src/main/java/io/vavr/package-info.java000066400000000000000000000002031342074374400227370ustar00rootroot00000000000000/** * Beside {@link io.vavr.API} the io.vavr package contains core types like (Checked)Functions and Tuples. */ package io.vavr; vavr-0.10.0/vavr/src/main/java/io/vavr/readme-contributing.md000066400000000000000000000011651342074374400240440ustar00rootroot00000000000000Please ensure that all major types but Functions, currently Tuples, Values and Traversables, have a `transform` method. Example (`TYPE` is replaced by the actual type): ```java /** * Transforms this {@code TYPE}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } ``` See also [#716](https://github.com/vavr-io/vavr/issues/716#issuecomment-163399633). vavr-0.10.0/vavr/src/main/javadoc/000077500000000000000000000000001342074374400166565ustar00rootroot00000000000000vavr-0.10.0/vavr/src/main/javadoc/overview.html000066400000000000000000000002241342074374400214100ustar00rootroot00000000000000 API Overview

This is the documentation for the Vavr library.

vavr-0.10.0/vavr/src/test/000077500000000000000000000000001342074374400153025ustar00rootroot00000000000000vavr-0.10.0/vavr/src/test/java/000077500000000000000000000000001342074374400162235ustar00rootroot00000000000000vavr-0.10.0/vavr/src/test/java/io/000077500000000000000000000000001342074374400166325ustar00rootroot00000000000000vavr-0.10.0/vavr/src/test/java/io/vavr/000077500000000000000000000000001342074374400176105ustar00rootroot00000000000000vavr-0.10.0/vavr/src/test/java/io/vavr/AbstractValueTest.java000066400000000000000000001125771342074374400240700ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.*; import io.vavr.control.Either; import io.vavr.control.Try; import io.vavr.control.Validation; import io.vavr.collection.Array; import io.vavr.collection.CharSeq; import io.vavr.collection.Stream; import io.vavr.concurrent.Future; import io.vavr.control.Option; import org.assertj.core.api.*; import org.junit.Test; import java.io.Serializable; import java.util.*; import java.util.Collections; import java.util.function.Function; import java.util.function.Supplier; import static io.vavr.API.*; import static io.vavr.Predicates.anyOf; import static io.vavr.Predicates.instanceOf; @SuppressWarnings("deprecation") public abstract class AbstractValueTest { protected Random getRandom(int seed) { if (seed >= 0) { return new Random(seed); } else { final Random random = new Random(); seed = random.nextInt(); System.out.println("using seed: " + seed); random.setSeed(seed); return random; } } protected IterableAssert assertThat(Iterable actual) { return new IterableAssert(actual) {}; } protected ObjectAssert assertThat(T actual) { return new ObjectAssert(actual) {}; } protected ObjectArrayAssert assertThat(T[] actual) { return new ObjectArrayAssert(actual) {}; } protected BooleanAssert assertThat(Boolean actual) { return new BooleanAssert(actual) {}; } protected DoubleAssert assertThat(Double actual) { return new DoubleAssert(actual) {}; } protected IntegerAssert assertThat(Integer actual) { return new IntegerAssert(actual) {}; } protected LongAssert assertThat(Long actual) { return new LongAssert(actual) {}; } protected StringAssert assertThat(String actual) { return new StringAssert(actual) {}; } abstract protected Value empty(); abstract protected Value of(T element); @SuppressWarnings("unchecked") abstract protected Value of(T... elements); // TODO: Eliminate this method. Switching the behavior of unit tests is evil. Tests should not contain additional logic. Also it seems currently to be used in different sematic contexts. abstract protected boolean useIsEqualToInsteadOfIsSameAs(); // returns the peek result of the specific Traversable implementation abstract protected int getPeekNonNilPerformingAnAction(); // -- get() @Test(expected = NoSuchElementException.class) public void shouldGetEmpty() { empty().get(); } @Test public void shouldGetNonEmpty() { assertThat(of(1).get()).isEqualTo(1); } // -- getOrElse(T) @Test public void shouldCalculateGetOrElseWithNull() { assertThat(this. empty().getOrElse((Integer) null)).isEqualTo(null); assertThat(of(1).getOrElse((Integer) null)).isEqualTo(1); } @Test public void shouldCalculateGetOrElseWithNonNull() { assertThat(empty().getOrElse(1)).isEqualTo(1); assertThat(of(1).getOrElse(2)).isEqualTo(1); } // -- getOrElse(Supplier) @Test(expected = NullPointerException.class) public void shouldThrowOnGetOrElseWithNullSupplier() { final Supplier supplier = null; empty().getOrElse(supplier); } @Test public void shouldCalculateGetOrElseWithSupplier() { assertThat(empty().getOrElse(() -> 1)).isEqualTo(1); assertThat(of(1).getOrElse(() -> 2)).isEqualTo(1); } // -- getOrElseThrow @Test(expected = ArithmeticException.class) public void shouldThrowOnGetOrElseThrowIfEmpty() { empty().getOrElseThrow(ArithmeticException::new); } @Test public void shouldNotThrowOnGetOrElseThrowIfNonEmpty() { assertThat(of(1).getOrElseThrow(ArithmeticException::new)).isEqualTo(1); } // -- getOrElseTry @Test public void shouldReturnUnderlyingValueWhenCallingGetOrElseTryOnNonEmptyValue() { assertThat(of(1).getOrElseTry(() -> 2)).isEqualTo(1); } @Test public void shouldReturnAlternateValueWhenCallingGetOrElseTryOnEmptyValue() { assertThat(empty().getOrElseTry(() -> 2)).isEqualTo(2); } @Test(expected = Error.class) public void shouldThrowWhenCallingGetOrElseTryOnEmptyValueAndTryIsAFailure() { empty().getOrElseTry(() -> { throw new Error(); }); } // -- getOrNull @Test public void shouldReturnNullWhenGetOrNullOfEmpty() { assertThat(empty().getOrNull()).isEqualTo(null); } @Test public void shouldReturnValueWhenGetOrNullOfNonEmpty() { assertThat(of(1).getOrNull()).isEqualTo(1); } // -- forEach @Test public void shouldPerformsActionOnEachElement() { final int[] consumer = new int[1]; final Value value = of(1, 2, 3); value.forEach(i -> consumer[0] += i); assertThat(consumer[0]).isEqualTo(value.isSingleValued() ? 1 : 6); } // -- isAsync @Test public void shouldVerifyAsyncProperty() { assertThat(empty().isAsync()).isFalse(); assertThat(of(1).isAsync()).isFalse(); } // -- isEmpty @Test public void shouldCalculateIsEmpty() { assertThat(empty().isEmpty()).isTrue(); assertThat(of(1).isEmpty()).isFalse(); } // -- isLazy @Test public void shouldVerifyLazyProperty() { assertThat(empty().isLazy()).isFalse(); assertThat(of(1).isLazy()).isFalse(); } // -- peek @Test public void shouldPeekNil() { assertThat(empty().peek(t -> {})).isEqualTo(empty()); } @Test public void shouldPeekNonNilPerformingNoAction() { assertThat(of(1).peek(t -> {})).isEqualTo(of(1)); } @Test public void shouldPeekSingleValuePerformingAnAction() { final int[] effect = { 0 }; final Value actual = of(1).peek(i -> effect[0] = i); assertThat(actual).isEqualTo(of(1)); assertThat(effect[0]).isEqualTo(1); } @Test public void shouldPeekNonNilPerformingAnAction() { final int[] effect = { 0 }; final Value actual = of(1, 2, 3).peek(i -> effect[0] = i); assertThat(actual).isEqualTo(of(1, 2, 3)); // traverses all elements in the lazy case assertThat(effect[0]).isEqualTo(getPeekNonNilPerformingAnAction()); } // -- Conversions toXxx() @Test public void shouldConvertToArray() { final Value value = of(1, 2, 3); final Array array = value.toArray(); if (value.isSingleValued()) { assertThat(array).isEqualTo(Array.of(1)); } else { assertThat(array).isEqualTo(Array.of(1, 2, 3)); } } @Test public void shouldConvertToCharSeq() { final Value value = of(1, 2, 3); final CharSeq charSeq = value.toCharSeq(); final CharSeq expected = CharSeq.of(of(1, 2, 3).iterator().mkString()); assertThat(charSeq).isEqualTo(expected); } @Test public void shouldConvertToList() { final Value value = of(1, 2, 3); final io.vavr.collection.List list = value.toList(); if (value.isSingleValued()) { assertThat(list).isEqualTo(io.vavr.collection.List.of(1)); } else { assertThat(list).isEqualTo(io.vavr.collection.List.of(1, 2, 3)); } } @Test public void shouldConvertToHashMap() { final Value value = of(9, 5, 1); final io.vavr.collection.Map map = value.toMap(i -> Tuple.of(i, i)); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.HashMap.of(9, 9)); } else { assertThat(map).isEqualTo(io.vavr.collection.HashMap.of(1, 1, 5, 5, 9, 9)); } } @Test public void shouldConvertToHashMapTwoFunctions() { final Value value = of(9, 5, 1); final io.vavr.collection.Map map = value.toMap(Function.identity(), Function.identity()); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.HashMap.of(9, 9)); } else { assertThat(map).isEqualTo(io.vavr.collection.HashMap.of(1, 1, 5, 5, 9, 9)); } } @Test public void shouldConvertToLinkedMap() { final Value value = of(1, 5, 9); final io.vavr.collection.Map map = value.toLinkedMap(i -> Tuple.of(i, i)); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.LinkedHashMap.of(1, 1)); } else { assertThat(map).isEqualTo(io.vavr.collection.LinkedHashMap.of(1, 1, 5, 5, 9, 9)); } } @Test public void shouldConvertToLinkedMapTwoFunctions() { final Value value = of(1, 5, 9); final io.vavr.collection.Map map = value.toLinkedMap(Function.identity(), Function.identity()); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.LinkedHashMap.of(1, 1)); } else { assertThat(map).isEqualTo(io.vavr.collection.LinkedHashMap.of(1, 1, 5, 5, 9, 9)); } } @Test public void shouldConvertToSortedMap() { final Value value = of(9, 5, 1); final io.vavr.collection.SortedMap map = value.toSortedMap(i -> Tuple.of(i, i)); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(9, 9)); } else { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(1, 1, 5, 5, 9, 9)); } } @Test public void shouldConvertToSortedMapTwoFunctions() { final Value value = of(9, 5, 1); final io.vavr.collection.SortedMap map = value.toSortedMap(Function.identity(), Function.identity()); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(9, 9)); } else { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(1, 1, 5, 5, 9, 9)); } } @Test public void shouldConvertToSortedMapWithComparator() { final Value value = of(9, 5, 1); final Comparator comparator = ((Comparator) Integer::compareTo).reversed(); final io.vavr.collection.SortedMap map = value.toSortedMap(comparator, i -> Tuple.of(i, i)); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(comparator, 9, 9)); } else { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(comparator, 9, 9, 5, 5, 1, 1)); } } @Test public void shouldConvertToSortedMapTwoFunctionsWithComparator() { final Value value = of(9, 5, 1); final Comparator comparator = ((Comparator) Integer::compareTo).reversed(); final io.vavr.collection.SortedMap map = value.toSortedMap(comparator, Function.identity(), Function.identity()); if (value.isSingleValued()) { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(comparator, 9, 9)); } else { assertThat(map).isEqualTo(io.vavr.collection.TreeMap.of(comparator, 9, 9, 5, 5, 1, 1)); } } @Test public void shouldConvertToOption() { assertThat(empty().toOption()).isSameAs(Option.none()); assertThat(of(1).toOption()).isEqualTo(Option.of(1)); } @Test public void shouldConvertToEither() { assertThat(empty().toEither("test")).isEqualTo(Left("test")); assertThat(empty().toEither(() -> "test")).isEqualTo(Left("test")); assertThat(of(1).toEither("test")).isEqualTo(Right(1)); } @Test public void shouldConvertToValidation() { assertThat(empty().toValidation("test")).isEqualTo(Invalid("test")); assertThat(empty().toValidation(() -> "test")).isEqualTo(Invalid("test")); assertThat(of(1).toValidation("test")).isEqualTo(Valid(1)); } @Test public void shouldConvertToQueue() { final Value value = of(1, 2, 3); final io.vavr.collection.Queue queue = value.toQueue(); if (value.isSingleValued()) { assertThat(queue).isEqualTo(io.vavr.collection.Queue.of(1)); } else { assertThat(queue).isEqualTo(io.vavr.collection.Queue.of(1, 2, 3)); } } @Test public void shouldConvertToPriorityQueueUsingImplicitComparator() { final Value value = of(1, 3, 2); final io.vavr.collection.PriorityQueue queue = value.toPriorityQueue(); if (value.isSingleValued()) { assertThat(queue).isEqualTo(io.vavr.collection.PriorityQueue.of(1)); } else { assertThat(queue).isEqualTo(io.vavr.collection.PriorityQueue.of(1, 2, 3)); } } @Test public void shouldConvertToPriorityQueueUsingExplicitComparator() { final Comparator comparator = Comparator.naturalOrder(); final Value value = of(1, 3, 2); final io.vavr.collection.PriorityQueue queue = value.toPriorityQueue(comparator); if (value.isSingleValued()) { assertThat(queue).isEqualTo(io.vavr.collection.PriorityQueue.of(comparator, 1)); } else { assertThat(queue).isEqualTo(io.vavr.collection.PriorityQueue.of(comparator, 1, 2, 3)); } } @Test public void shouldConvertToPriorityQueueUsingSerializableComparator() { final Value value = of(1, 3, 2); final io.vavr.collection.PriorityQueue queue = value.toPriorityQueue(); final io.vavr.collection.PriorityQueue actual = Serializables.deserialize(Serializables.serialize(queue)); assertThat(actual).isEqualTo(queue); } @Test public void shouldConvertToSet() { final Value value = of(1, 2, 3); final io.vavr.collection.Set set = value.toSet(); if (value.isSingleValued()) { assertThat(set).isEqualTo(io.vavr.collection.HashSet.of(1)); } else { assertThat(set).isEqualTo(io.vavr.collection.HashSet.of(1, 2, 3)); } } @Test public void shouldConvertToLinkedSet() { final Value value = of(3, 7, 1, 15, 0); final io.vavr.collection.Set set = value.toLinkedSet(); if (value.isSingleValued()) { assertThat(set).isEqualTo(io.vavr.collection.LinkedHashSet.of(3)); } else { final io.vavr.collection.List itemsInOrder; if (value instanceof Traversable && !((Traversable) value).isTraversableAgain()) { itemsInOrder = io.vavr.collection.List.of(3, 7, 1, 15, 0); } else { itemsInOrder = value.toList(); } assertThat(set).isEqualTo(itemsInOrder.foldLeft(io.vavr.collection.LinkedHashSet.empty(), io.vavr.collection.LinkedHashSet::add)); } } @Test public void shouldConvertToSortedSetWithoutComparatorOnComparable() { final Value value = of(3, 7, 1, 15, 0); final io.vavr.collection.SortedSet set = value.toSortedSet(); if (value.isSingleValued()) { assertThat(set).isEqualTo(io.vavr.collection.TreeSet.of(3)); } else { assertThat(set).isEqualTo(io.vavr.collection.TreeSet.of(0, 1, 3, 7, 15)); } } @Test(expected = ClassCastException.class) public void shouldThrowOnConvertToSortedSetWithoutComparatorOnNonComparable() { final Value value = of(new Object(), new Object()); final io.vavr.collection.SortedSet set = value.toSortedSet(); if (value.isSingleValued()) { // Comparator wasn't used on of(...) set.add(new Object()); } } @Test public void shouldConvertToSortedSet() { final Value value = of(3, 7, 1, 15, 0); final Comparator comparator = Comparator.comparingInt(Integer::bitCount); final io.vavr.collection.SortedSet set = value.toSortedSet(comparator.reversed()); if (value.isSingleValued()) { assertThat(set).isEqualTo(io.vavr.collection.TreeSet.of(3)); } else { assertThat(set).isEqualTo(io.vavr.collection.TreeSet.of(comparator.reversed(), 0, 1, 3, 7, 15)); } } @Test public void shouldConvertToSortedSetUsingSerializableComparator() { final Value value = of(1, 3, 2); final io.vavr.collection.SortedSet set = value.toSortedSet(); final io.vavr.collection.SortedSet actual = Serializables.deserialize(Serializables.serialize(set)); assertThat(actual).isEqualTo(set); } @Test public void shouldConvertToStream() { final Value value = of(1, 2, 3); final Stream stream = value.toStream(); if (value.isSingleValued()) { assertThat(stream).isEqualTo(Stream.of(1)); } else { assertThat(stream).isEqualTo(Stream.of(1, 2, 3)); } } @Test public void shouldConvertNonEmptyToTry() { assertThat(of(1, 2, 3).toTry()).isEqualTo(Try.of(() -> 1)); } @Test public void shouldConvertEmptyToTry() { final Try actual = empty().toTry(); assertThat(actual.isFailure()).isTrue(); assertThat(actual.getCause()).isInstanceOf(NoSuchElementException.class); } @Test public void shouldConvertNonEmptyToTryUsingExceptionSupplier() { final Exception x = new Exception("test"); assertThat(of(1, 2, 3).toTry(() -> x)).isEqualTo(Try.of(() -> 1)); } @Test public void shouldConvertEmptyToTryUsingExceptionSupplier() { final Exception x = new Exception("test"); assertThat(empty().toTry(() -> x)).isEqualTo(Try.failure(x)); } @Test public void shouldConvertToVector() { final Value value = of(1, 2, 3); final io.vavr.collection.Vector vector = value.toVector(); if (value.isSingleValued()) { assertThat(vector).isEqualTo(io.vavr.collection.Vector.of(1)); } else { assertThat(vector).isEqualTo(io.vavr.collection.Vector.of(1, 2, 3)); } } @Test public void shouldConvertToJavaArray() { final Value value = of(1, 2, 3); final Object[] ints = value.toJavaArray(); if (value.isSingleValued()) { assertThat(ints).isEqualTo(new int[] { 1 }); } else { assertThat(ints).isEqualTo(new int[] { 1, 2, 3 }); } } @Test public void shouldConvertToJavaArrayWithFactory() { final Value value = of(1, 2, 3); final Integer[] ints = value.toJavaArray(Integer[]::new); if (value.isSingleValued()) { assertThat(ints).containsOnly(1); } else { assertThat(ints).containsOnly(1, 2, 3); } } @Test public void shouldConvertToJavaArrayWithTypeHint() { final Value value = of(1, 2, 3); @SuppressWarnings("deprecation") final Integer[] ints = value.toJavaArray(Integer.class); if (value.isSingleValued()) { assertThat(ints).containsOnly(1); } else { assertThat(ints).containsOnly(1, 2, 3); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveBoolean() { final Value value = of(true, false); @SuppressWarnings("deprecation") final Boolean[] array = value.toJavaArray(boolean.class); if (value.isSingleValued()) { assertThat(array).containsOnly(true); } else { assertThat(array).containsOnly(true, false); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveByte() { final Value value = of((byte) 1, (byte) 2); @SuppressWarnings("deprecation") final Byte[] array = value.toJavaArray(byte.class); if (value.isSingleValued()) { assertThat(array).containsOnly((byte) 1); } else { assertThat(array).containsOnly((byte) 1, (byte) 2); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveChar() { final Value value = of('a', 'b'); @SuppressWarnings("deprecation") final Character[] array = value.toJavaArray(char.class); if (value.isSingleValued()) { assertThat(array).containsOnly('a'); } else { assertThat(array).containsOnly('a', 'b'); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveDouble() { final Value value = of(.1, .2); @SuppressWarnings("deprecation") final Double[] array = value.toJavaArray(double.class); if (value.isSingleValued()) { assertThat(array).containsOnly(.1); } else { assertThat(array).containsOnly(.1, .2); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveFloat() { final Value value = of(.1f, .2f); @SuppressWarnings("deprecation") final Float[] array = value.toJavaArray(float.class); if (value.isSingleValued()) { assertThat(array).containsOnly(.1f); } else { assertThat(array).containsOnly(.1f, .2f); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveInt() { final Value value = of(1, 2); @SuppressWarnings("deprecation") final Integer[] array = value.toJavaArray(int.class); if (value.isSingleValued()) { assertThat(array).containsOnly(1); } else { assertThat(array).containsOnly(1, 2); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveLong() { final Value value = of(1L, 2L); @SuppressWarnings("deprecation") final Long[] array = value.toJavaArray(long.class); if (value.isSingleValued()) { assertThat(array).containsOnly(1L); } else { assertThat(array).containsOnly(1L, 2L); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveShort() { final Value value = of((short) 1, (short) 2); @SuppressWarnings("deprecation") final Short[] array = value.toJavaArray(short.class); if (value.isSingleValued()) { assertThat(array).containsOnly((short) 1); } else { assertThat(array).containsOnly((short) 1, (short) 2); } } @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveVoid() { final Value value = of((Void) null); @SuppressWarnings("deprecation") final Void[] array = value.toJavaArray(void.class); assertThat(array).containsOnly((Void) null); } @Test public void shouldConvertToJavaCollectionUsingSupplier() { final Value value = of(1, 2, 3); final java.util.List ints = value.toJavaCollection(ArrayList::new); if (value.isSingleValued()) { assertThat(ints).isEqualTo(Collections.singletonList(1)); } else { assertThat(ints).isEqualTo(Arrays.asList(1, 2, 3)); } } @Test public void shouldConvertToJavaList() { final Value value = of(1, 2, 3); final java.util.List list = value.toJavaList(); if (value.isSingleValued()) { assertThat(list).isEqualTo(Collections.singletonList(1)); } else { assertThat(list).isEqualTo(Arrays.asList(1, 2, 3)); } } @Test public void shouldConvertToJavaListUsingSupplier() { final Value value = of(1, 2, 3); final java.util.List ints = value.toJavaList(ArrayList::new); if (value.isSingleValued()) { assertThat(ints).isEqualTo(Collections.singletonList(1)); } else { assertThat(ints).isEqualTo(Arrays.asList(1, 2, 3)); } } @Test public void shouldConvertToJavaMapUsingFunction() { final Value value = of(1, 2, 3); final java.util.Map map = value.toJavaMap(v -> Tuple.of(v, v)); if (value.isSingleValued()) { assertThat(map).isEqualTo(JavaCollections.javaMap(1, 1)); } else { assertThat(map).isEqualTo(JavaCollections.javaMap(1, 1, 2, 2, 3, 3)); } } @Test public void shouldConvertToJavaMapUsingSupplierAndFunction() { final Value value = of(1, 2, 3); final java.util.Map map = value.toJavaMap(java.util.HashMap::new, i -> Tuple.of(i, i)); if (value.isSingleValued()) { assertThat(map).isEqualTo(JavaCollections.javaMap(1, 1)); } else { assertThat(map).isEqualTo(JavaCollections.javaMap(1, 1, 2, 2, 3, 3)); } } @Test public void shouldConvertToJavaMapUsingSupplierAndTwoFunction() { final Value value = of(1, 2, 3); final java.util.Map map = value.toJavaMap(java.util.HashMap::new, Function.identity(), String::valueOf); if (value.isSingleValued()) { assertThat(map).isEqualTo(JavaCollections.javaMap(1, "1")); } else { assertThat(map).isEqualTo(JavaCollections.javaMap(1, "1", 2, "2", 3, "3")); } } @Test public void shouldConvertToJavaOptional() { assertThat(of(1, 2, 3).toJavaOptional()).isEqualTo(Optional.of(1)); } @Test public void shouldConvertToJavaSet() { final Value value = of(1, 2, 3); final java.util.Set set = value.toJavaSet(); if (value.isSingleValued()) { assertThat(set).isEqualTo(JavaCollections.javaSet(1)); } else { assertThat(set).isEqualTo(JavaCollections.javaSet(1, 2, 3)); } } @Test public void shouldConvertToJavaSetUsingSupplier() { final Value value = of(1, 2, 3); final java.util.Set set = value.toJavaSet(java.util.HashSet::new); if (value.isSingleValued()) { assertThat(set).isEqualTo(JavaCollections.javaSet(1)); } else { assertThat(set).isEqualTo(JavaCollections.javaSet(1, 2, 3)); } } @Test public void shouldConvertToJavaStream() { final Value value = of(1, 2, 3); final java.util.stream.Stream s1 = value.toJavaStream(); //noinspection Duplicates if (value.isSingleValued()) { final java.util.stream.Stream s2 = java.util.stream.Stream.of(1); assertThat(io.vavr.collection.List.ofAll(s1::iterator)).isEqualTo(io.vavr.collection.List.ofAll(s2::iterator)); } else { final java.util.stream.Stream s2 = java.util.stream.Stream.of(1, 2, 3); assertThat(io.vavr.collection.List.ofAll(s1::iterator)).isEqualTo(io.vavr.collection.List.ofAll(s2::iterator)); } } @Test public void shouldConvertToJavaParallelStream() { final Value value = of(1, 2, 3); final java.util.stream.Stream s1 = value.toJavaParallelStream(); assertThat(s1.isParallel()).isTrue(); //noinspection Duplicates if (value.isSingleValued()) { final java.util.stream.Stream s2 = java.util.stream.Stream.of(1); assertThat(io.vavr.collection.List.ofAll(s1::iterator)).isEqualTo(io.vavr.collection.List.ofAll(s2::iterator)); } else { final java.util.stream.Stream s2 = java.util.stream.Stream.of(1, 2, 3); assertThat(io.vavr.collection.List.ofAll(s1::iterator)).isEqualTo(io.vavr.collection.List.ofAll(s2::iterator)); } } // toLeft / toRight @Test public void shouldConvertToEitherLeftFromValueSupplier() { final Either either = of(0).toLeft(() -> "fallback"); assertThat(either.isLeft()).isTrue(); assertThat(either.getLeft()).isEqualTo(0); final Either either2 = empty().toLeft(() -> "fallback"); assertThat(either2.isRight()).isTrue(); assertThat(either2.get()).isEqualTo("fallback"); } @Test public void shouldConvertToEitherLeftFromValue() { final Either either = of(0).toLeft("fallback"); assertThat(either.isLeft()).isTrue(); assertThat(either.getLeft()).isEqualTo(0); final Either either2 = empty().toLeft("fallback"); assertThat(either2.isRight()).isTrue(); assertThat(either2.get()).isEqualTo("fallback"); } @Test public void shouldConvertToEitherRightFromValueSupplier() { final Either either = of(0).toRight(() -> "fallback"); assertThat(either.isRight()).isTrue(); assertThat(either.get()).isEqualTo(0); final Either either2 = empty().toRight(() -> "fallback"); assertThat(either2.isLeft()).isTrue(); assertThat(either2.getLeft()).isEqualTo("fallback"); } @Test public void shouldConvertToEitherRightFromValue() { final Either either = of(0).toRight("fallback"); assertThat(either.isRight()).isTrue(); assertThat(either.get()).isEqualTo(0); final Either either2 = empty().toRight("fallback"); assertThat(either2.isLeft()).isTrue(); assertThat(either2.getLeft()).isEqualTo("fallback"); } // toValid / toInvalid @Test public void shouldConvertToValidationInvalidFromValueSupplier() { final Validation validation = of(0).toInvalid(() -> "fallback"); assertThat(validation.isInvalid()).isTrue(); assertThat(validation.getError()).isEqualTo(0); final Validation validation2 = empty().toInvalid(() -> "fallback"); assertThat(validation2.isValid()).isTrue(); assertThat(validation2.get()).isEqualTo("fallback"); } @Test public void shouldConvertToValidationInvalidFromValue() { final Validation validation = of(0).toInvalid("fallback"); assertThat(validation.isInvalid()).isTrue(); assertThat(validation.getError()).isEqualTo(0); final Validation validation2 = empty().toInvalid("fallback"); assertThat(validation2.isValid()).isTrue(); assertThat(validation2.get()).isEqualTo("fallback"); } @Test public void shouldConvertToValidationRightFromValueSupplier() { final Validation validation = of(0).toValid(() -> "fallback"); assertThat(validation.isValid()).isTrue(); assertThat(validation.get()).isEqualTo(0); final Validation validation2 = empty().toValid(() -> "fallback"); assertThat(validation2.isInvalid()).isTrue(); assertThat(validation2.getError()).isEqualTo("fallback"); } @Test public void shouldConvertToValidationValidFromValue() { final Validation validation = of(0).toValid("fallback"); assertThat(validation.isValid()).isTrue(); assertThat(validation.get()).isEqualTo(0); final Validation validation2 = empty().toValid("fallback"); assertThat(validation2.isInvalid()).isTrue(); assertThat(validation2.getError()).isEqualTo("fallback"); } // -- exists @Test public void shouldBeAwareOfExistingElement() { final Value value = of(1, 2); if (value.isSingleValued()) { assertThat(value.exists(i -> i == 1)).isTrue(); } else { assertThat(value.exists(i -> i == 2)).isTrue(); } } @Test public void shouldBeAwareOfNonExistingElement() { assertThat(this. empty().exists(i -> i == 1)).isFalse(); } // -- forAll @Test public void shouldBeAwareOfPropertyThatHoldsForAll() { assertThat(of(2, 4).forAll(i -> i % 2 == 0)).isTrue(); } @Test public void shouldBeAwareOfPropertyThatNotHoldsForAll() { assertThat(of(1, 2).forAll(i -> i % 2 == 0)).isFalse(); } // ### ValueModule.Iterable ### // -- corresponds @Test public void shouldntCorrespondsNilNil() { assertThat(empty().corresponds(empty(), (o1, o2) -> true)).isTrue(); } @Test public void shouldntCorrespondsNilNonNil() { assertThat(empty().corresponds(of(1), (o1, i2) -> true)).isFalse(); } @Test public void shouldntCorrespondsNonNilNil() { assertThat(of(1).corresponds(empty(), (i1, o2) -> true)).isFalse(); } @Test public void shouldntCorrespondsDifferentLengths() { if (!empty().isSingleValued()) { assertThat(of(1, 2, 3).corresponds(of(1, 2), (i1, i2) -> true)).isFalse(); assertThat(of(1, 2).corresponds(of(1, 2, 3), (i1, i2) -> true)).isFalse(); } } @Test public void shouldCorresponds() { assertThat(of(1, 2, 3).corresponds(of(3, 4, 5), (i1, i2) -> i1 == i2 - 2)).isTrue(); assertThat(of(1, 2, 3).corresponds(of(1, 2, 3), (i1, i2) -> i1 == i2 + 1)).isFalse(); } @Test public void shouldHaveAReasonableToString() { final Value value = of(1, 2); value.toList(); // evaluate all elements (e.g. for Stream) final String actual = value.toString(); if (value.isSingleValued()) { assertThat(actual).contains("1"); } else { assertThat(actual).contains("1", "2"); } } // -- Serialization /** * States whether the specific Value implementation is Serializable. *

* Test classes override this method to return false if needed. * * @return true (by default), if the Value is Serializable, false otherwise */ private boolean isSerializable() { final Object nonEmpty = of(1); if (empty() instanceof Serializable != nonEmpty instanceof Serializable) { throw new Error("empty and non-empty do not consistently implement Serializable"); } final boolean actual = nonEmpty instanceof Serializable; final boolean expected = Match(nonEmpty).of( Case($(anyOf( instanceOf(Either.LeftProjection.class), instanceOf(Either.RightProjection.class), instanceOf(Future.class), instanceOf(io.vavr.collection.Iterator.class) )), false), Case($(anyOf( instanceOf(Either.class), instanceOf(Lazy.class), instanceOf(Option.class), instanceOf(Try.class), instanceOf(Traversable.class), instanceOf(Validation.class) )), true) ); assertThat(actual).isEqualTo(expected); return actual; } @Test public void shouldSerializeDeserializeEmpty() { if (isSerializable()) { final Value testee = empty(); final Value actual = Serializables.deserialize(Serializables.serialize(testee)); assertThat(actual).isEqualTo(testee); } } @Test public void shouldSerializeDeserializeSingleValued() { if (isSerializable()) { final Value testee = of(1); final Value actual = Serializables.deserialize(Serializables.serialize(testee)); assertThat(actual).isEqualTo(testee); } } @Test public void shouldSerializeDeserializeMultiValued() { if (isSerializable()) { final Value testee = of(1, 2, 3); final Value actual = Serializables.deserialize(Serializables.serialize(testee)); assertThat(actual).isEqualTo(testee); } } @Test public void shouldPreserveSingletonInstanceOnDeserialization() { if (isSerializable() && !useIsEqualToInsteadOfIsSameAs()) { final Value empty = empty(); final Value actual = Serializables.deserialize(Serializables.serialize(empty)); assertThat(actual).isSameAs(empty); } } // -- equals @Test public void shouldRecognizeSameObject() { final Value v = of(1); //noinspection EqualsWithItself assertThat(v.equals(v)).isTrue(); } @Test public void shouldRecognizeEqualObjects() { final Value v1 = of(1); final Value v2 = of(1); assertThat(v1.equals(v2)).isTrue(); } @Test public void shouldRecognizeUnequalObjects() { final Value v1 = of(1); final Value v2 = of(2); assertThat(v1.equals(v2)).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/AssertionsExtensions.java000066400000000000000000000030471342074374400246710ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import org.assertj.core.api.Assertions; import java.lang.reflect.Constructor; public final class AssertionsExtensions { private AssertionsExtensions() { } public static ClassAssert assertThat(Class clazz) { return new ClassAssert(clazz); } public static class ClassAssert { final Class clazz; ClassAssert(Class clazz) { this.clazz = clazz; } @SuppressWarnings("deprecation") public void isNotInstantiable() { try { final Constructor cons = clazz.getDeclaredConstructor(); Assertions.assertThat(cons.isAccessible()).isFalse(); } catch (NoSuchMethodException e) { throw new AssertionError("no default constructor found"); } } } } vavr-0.10.0/vavr/src/test/java/io/vavr/CheckedConsumerTest.java000066400000000000000000000075771342074374400243750ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import org.junit.Assert; import org.junit.Test; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; public class CheckedConsumerTest { // -- of @Test public void shouldCreateCheckedConsumerUsingLambda() { final CheckedConsumer consumer = CheckedConsumer.of(obj -> {}); assertThat(consumer).isNotNull(); } @Test public void shouldCreateCheckedConsumerUsingMethodReference() { final CheckedConsumer consumer = CheckedConsumer.of(CheckedConsumerTest::accept); assertThat(consumer).isNotNull(); } private static void accept(Object obj) { } // -- accept @Test public void shouldApplyNonThrowingCheckedConsumer() { final CheckedConsumer f = t -> {}; try { f.accept(null); } catch(Throwable x) { fail("should not have thrown", x); } } @Test public void shouldApplyThrowingCheckedConsumer() { final CheckedConsumer f = t -> { throw new Error(); }; try { f.accept(null); fail("should have thrown"); } catch(Throwable x) { // ok } } // -- andThen @Test public void shouldThrowWhenComposingCheckedConsumerUsingAndThenWithNullParameter() { final CheckedConsumer f = t -> {}; assertThatThrownBy(() -> f.andThen(null)).isInstanceOf(NullPointerException.class); } @Test public void shouldComposeCheckedConsumerUsingAndThenWhenFirstOneSucceeds() { final AtomicBoolean result = new AtomicBoolean(false); final CheckedConsumer f = t -> {}; try { f.andThen(ignored -> result.set(true)).accept(null); assertThat(result.get()).isTrue(); } catch(Throwable x) { fail("should not have thrown", x); } } @Test public void shouldComposeCheckedConsumerUsingAndThenWhenFirstOneFails() { final AtomicBoolean result = new AtomicBoolean(false); final CheckedConsumer f = t -> { throw new Error(); }; try { f.andThen(ignored -> result.set(true)).accept(null); fail("should have thrown"); } catch(Throwable x) { assertThat(result.get()).isFalse(); } } // -- unchecked @Test public void shouldApplyAnUncheckedFunctionThatDoesNotThrow() { final Consumer consumer = CheckedConsumer.of(obj -> {}).unchecked(); try { consumer.accept(null); } catch(Throwable x) { Assert.fail("Did not excepect an exception but received: " + x.getMessage()); } } @Test public void shouldApplyAnUncheckedFunctionThatThrows() { final Consumer consumer = CheckedConsumer.of(obj -> { throw new Error(); }).unchecked(); try { consumer.accept(null); Assert.fail("Did excepect an exception."); } catch(Error x) { // ok! } } } vavr-0.10.0/vavr/src/test/java/io/vavr/CheckedPredicateTest.java000066400000000000000000000041741342074374400244700ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import org.junit.Assert; import org.junit.Test; import java.util.function.Predicate; import static org.assertj.core.api.Assertions.assertThat; public class CheckedPredicateTest { // -- of @Test public void shouldCreateCheckedPredicateUsingLambda() { final CheckedPredicate predicate = CheckedPredicate.of(obj -> true); assertThat(predicate).isNotNull(); } @Test public void shouldCreateCheckedPredicateUsingMethodReference() { final CheckedPredicate predicate = CheckedPredicate.of(CheckedPredicateTest::test); assertThat(predicate).isNotNull(); } private static boolean test(Object obj) { return true; } // -- unchecked @Test public void shouldApplyAnUncheckedFunctionThatDoesNotThrow() { final Predicate preciate = CheckedPredicate.of(obj -> true).unchecked(); try { preciate.test(null); } catch(Throwable x) { Assert.fail("Did not excepect an exception but received: " + x.getMessage()); } } @Test public void shouldApplyAnUncheckedFunctionThatThrows() { final Predicate preciate = CheckedPredicate.of(obj -> { throw new Error(); }).unchecked(); try { preciate.test(null); Assert.fail("Did excepect an exception."); } catch(Error x) { // ok! } } } vavr-0.10.0/vavr/src/test/java/io/vavr/CheckedRunnableTest.java000066400000000000000000000037611342074374400243370ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import org.junit.Assert; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; public class CheckedRunnableTest { // -- of @Test public void shouldCreateCheckedRunnableUsingLambda() { final CheckedRunnable runnable = CheckedRunnable.of(() -> {}); assertThat(runnable).isNotNull(); } @Test public void shouldCreateCheckedRunnableUsingMethodReference() { final CheckedRunnable runnable = CheckedRunnable.of(CheckedRunnableTest::run); assertThat(runnable).isNotNull(); } private static void run() { } // -- unchecked @Test public void shouldApplyAnUncheckedFunctionThatDoesNotThrow() { final Runnable runnable = CheckedRunnable.of(() -> {}).unchecked(); try { runnable.run(); } catch(Throwable x) { Assert.fail("Did not excepect an exception but received: " + x.getMessage()); } } @Test public void shouldApplyAnUncheckedFunctionThatThrows() { final Runnable runnable = CheckedRunnable.of(() -> { throw new Error(); }).unchecked(); try { runnable.run(); Assert.fail("Did excepect an exception."); } catch(Error x) { // ok! } } } vavr-0.10.0/vavr/src/test/java/io/vavr/IterableTest.java000066400000000000000000000041111342074374400230370ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.Queue; import io.vavr.collection.Stream; import io.vavr.collection.List; import io.vavr.control.Option; import org.junit.Test; import java.util.Arrays; import java.util.Collections; import static org.assertj.core.api.Assertions.assertThat; // Specific tests. For general tests, see AbstractIterableTest. public class IterableTest { // -- eq @Test public void shouldEqNoneAndEmptyList() { assertThat(Option.none().eq(List.empty())).isTrue(); assertThat(Option.none().eq(List.of(1))).isFalse(); } @Test public void shouldEqSomeAndNonEmptyList() { assertThat(Option.some(1).eq(List.of(1))).isTrue(); assertThat(Option.some(1).eq(List.of(2))).isFalse(); assertThat(Option.some(1).eq(List.empty())).isFalse(); } @Test public void shouldEqIterableAndJavaIterable() { assertThat(List.of(1, 2, 3).eq(Arrays.asList(1, 2, 3))).isTrue(); } @Test public void shouldEqNestedIterables() { // ((1, 2), ((3))) final Value i1 = List.of(List.of(1, 2), Collections.singletonList(List.of(3))); final Value i2 = Queue.of(Stream.of(1, 2), List.of(Lazy.of(() -> 3))); final Value i3 = Queue.of(Stream.of(1, 2), List.of(List.of())); assertThat(i1.eq(i2)).isTrue(); assertThat(i1.eq(i3)).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/JavaCollections.java000066400000000000000000000030431342074374400235330ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import java.util.*; final class JavaCollections { private JavaCollections() { } @SuppressWarnings("unchecked") static Map javaMap(Object... pairs) { Objects.requireNonNull(pairs, "pairs is null"); if ((pairs.length & 1) != 0) { throw new IllegalArgumentException("Odd length of key-value pairs list"); } final Map map = new HashMap<>(); for (int i = 0; i < pairs.length; i += 2) { map.put((K) pairs[i], (V) pairs[i + 1]); } return map; } @SuppressWarnings("unchecked") static Set javaSet(T... elements) { Objects.requireNonNull(elements, "elements is null"); final Set set = new HashSet<>(); Collections.addAll(set, elements); return set; } } vavr-0.10.0/vavr/src/test/java/io/vavr/LazyTest.java000066400000000000000000000333751342074374400222450ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.Seq; import io.vavr.control.Try; import io.vavr.collection.Iterator; import io.vavr.collection.List; import io.vavr.collection.Vector; import io.vavr.control.Option; import org.junit.Test; import java.io.Serializable; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Spliterator; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Function; import static java.util.concurrent.CompletableFuture.runAsync; import static io.vavr.collection.Iterator.range; public class LazyTest extends AbstractValueTest { @SuppressWarnings("unchecked") @Override protected Undefined empty() { return (Undefined) Undefined.INSTANCE; } @Override protected Lazy of(T element) { return Lazy.of(() -> element); } @SafeVarargs @Override protected final Lazy of(T... elements) { return of(elements[0]); } @Override protected boolean useIsEqualToInsteadOfIsSameAs() { return false; } @Override protected int getPeekNonNilPerformingAnAction() { return 1; } // -- static narrow @Test public void shouldNarrow() { final String expected = "Zero args"; final Lazy wideFunction = Lazy.of(() -> expected); final Lazy actual = Lazy.narrow(wideFunction); assertThat(actual.get()).isEqualTo(expected); } // -- of(Supplier) @Test public void shouldNotChangeLazy() { final Lazy expected = Lazy.of(() -> 1); assertThat(Lazy.of(expected)).isSameAs(expected); } @Test(expected = NullPointerException.class) public void shouldThrowOnNullSupplier() { Lazy.of(null); } @Test public void shouldMemoizeValues() { final Lazy testee = Lazy.of(Math::random); final double expected = testee.get(); for (int i = 0; i < 10; i++) { final double actual = testee.get(); assertThat(actual).isEqualTo(expected); } } // -- iterate @Test public void shouldIterate() { final Iterator iterator = Lazy.of(() -> 1).iterator(); assertThat(iterator.next()).isEqualTo(1); assertThat(iterator.hasNext()).isFalse(); } // -- peek @Test public void shouldPeek() { final Lazy lazy = Lazy.of(() -> 1); final Lazy peek = lazy.peek(v -> assertThat(v).isEqualTo(1)); assertThat(peek).isSameAs(lazy); } // -- sequence(Iterable) @Test public void shouldSequenceEmpty() { final List> testee = List.empty(); final Lazy> sequence = Lazy.sequence(testee); assertThat(sequence.get()).isEqualTo(Vector.empty()); } @Test public void shouldSequenceNonEmptyLazy() { final List> testee = List.of(1, 2, 3).map(i -> Lazy.of(() -> i)); final Lazy> sequence = Lazy.sequence(testee); assertThat(sequence.get()).isEqualTo(Vector.of(1, 2, 3)); } @Test public void shouldNotEvaluateEmptySequence() { final List> testee = List.empty(); final Lazy> sequence = Lazy.sequence(testee); assertThat(sequence.isEvaluated()).isFalse(); } @Test public void shouldNotEvaluateNonEmptySequence() { final List> testee = List.of(1, 2, 3).map(i -> Lazy.of(() -> i)); final Lazy> sequence = Lazy.sequence(testee); assertThat(sequence.isEvaluated()).isFalse(); } @Test public void shouldMapOverLazyValue() { final Lazy testee = Lazy.of(() -> 42); final Lazy expected = Lazy.of(() -> 21); assertThat(testee.map(i -> i / 2)).isEqualTo(expected); } @Test public void shouldFilterOverLazyValue() { final Lazy testee = Lazy.of(() -> 42); final Option expectedPositive = Option.some(42); final Option expectedNegative = Option.none(); assertThat(testee.filter(i -> i % 2 == 0)).isEqualTo(expectedPositive); assertThat(testee.filter(i -> i % 2 != 0)).isEqualTo(expectedNegative); } @Test public void shouldTransformLazyValue() { final Lazy testee = Lazy.of(() -> 42); final Integer expected = 21; final Integer actual = testee.transform(lazy -> lazy.get() / 2); assertThat(actual).isEqualTo(expected); } @Test public void shouldNotBeEmpty() { assertThat(Lazy.of(Option::none).isEmpty()).isFalse(); } @Test public void shouldContainASingleValue() { assertThat(Lazy.of(Option::none).isSingleValued()).isTrue(); } // -- val(Supplier, Class) -- Proxy @Test public void shouldCreateLazyProxy() { final String[] evaluated = new String[] { null }; final CharSequence chars = Lazy.val(() -> { final String value = "Yay!"; evaluated[0] = value; return value; }, CharSequence.class); assertThat(evaluated[0]).isEqualTo(null); assertThat(chars).isEqualTo("Yay!"); assertThat(evaluated[0]).isEqualTo("Yay!"); } @Test(expected = NullPointerException.class) public void shouldThrowWhenCreatingLazyProxyAndSupplierIsNull() { Lazy.val(null, CharSequence.class); } @Test(expected = NullPointerException.class) public void shouldThrowWhenCreatingLazyProxyAndTypeIsNull() { Lazy.val(() -> "", null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCreatingLazyProxyOfObjectType() { Lazy.val(() -> "", String.class); } @Test public void shouldBehaveLikeValueWhenCreatingProxy() { final CharSequence chars = Lazy.val(() -> "Yay!", CharSequence.class); assertThat(chars.toString()).isEqualTo("Yay!"); } // -- isEvaluated() @Test public void shouldBeAwareOfEvaluated() { final Lazy lazy = Lazy.of(() -> null); assertThat(lazy.isEvaluated()).isFalse(); assertThat(lazy.isEvaluated()).isFalse(); // remains not evaluated lazy.get(); assertThat(lazy.isEvaluated()).isTrue(); } // -- Serialization @Test public void shouldSerializeDeserializeNonNil() { final Object actual = Serializables.deserialize(Serializables.serialize(Lazy.of(() -> 1))); final Object expected = Lazy.of(() -> 1); assertThat(actual).isEqualTo(expected); } // -- concurrency @Test public void shouldSupportMultithreading() { final AtomicBoolean isEvaluated = new AtomicBoolean(); final AtomicBoolean lock = new AtomicBoolean(); final Lazy lazy = Lazy.of(() -> { while (lock.get()) { Try.run(() -> Thread.sleep(300)); } return 1; }); new Thread(() -> { Try.run(() -> Thread.sleep(100)); new Thread(() -> { Try.run(() -> Thread.sleep(100)); lock.set(false); }).start(); isEvaluated.compareAndSet(false, lazy.isEvaluated()); lazy.get(); }).start(); assertThat(isEvaluated.get()).isFalse(); assertThat(lazy.get()).isEqualTo(1); } @Test @SuppressWarnings({ "StatementWithEmptyBody", "rawtypes" }) public void shouldBeConsistentFromMultipleThreads() throws Exception { for (int i = 0; i < 100; i++) { final AtomicBoolean canProceed = new AtomicBoolean(false); final Vector> futures = Vector.range(0, 10).map(j -> { final AtomicBoolean isEvaluated = new AtomicBoolean(false); final Integer expected = ((j % 2) == 1) ? null : j; Lazy lazy = Lazy.of(() -> { assertThat(isEvaluated.getAndSet(true)).isFalse(); return expected; }); return Tuple.of(lazy, expected); }).flatMap(t -> range(0, 5).map(j -> runAsync(() -> { while (!canProceed.get()) { /* busy wait */ } assertThat(t._1.get()).isEqualTo(t._2); })) ); final CompletableFuture all = CompletableFuture.allOf(futures.toJavaList().toArray(new CompletableFuture[0])); canProceed.set(true); all.join(); } } // -- equals @SuppressWarnings({ "EqualsBetweenInconvertibleTypes", "EqualsWithItself" }) @Test public void shouldDetectEqualObject() { assertThat(Lazy.of(() -> 1).equals("")).isFalse(); assertThat(Lazy.of(() -> 1).equals(Lazy.of(() -> 1))).isTrue(); assertThat(Lazy.of(() -> 1).equals(Lazy.of(() -> 2))).isFalse(); final Lazy same = Lazy.of(() -> 1); assertThat(same.equals(same)).isTrue(); } @SuppressWarnings({ "EqualsBetweenInconvertibleTypes", "EqualsWithItself" }) @Test public void shouldUseDefaultEqualsSemanticsForArrays() { assertThat(Lazy.of(() -> new Integer[] {1}).equals("")).isFalse(); assertThat(Lazy.of(() -> new Integer[] {1}).equals(Lazy.of(() -> new Integer[] {1}))).isFalse(); final Lazy same = Lazy.of(() -> new Integer[] {1}); assertThat(same.equals(same)).isTrue(); } @Test public void shouldDetectUnequalObject() { assertThat(Lazy.of(() -> 1).equals(Lazy.of(() -> 2))).isFalse(); } // -- hashCode @Test public void shouldComputeHashCode() { assertThat(Lazy.of(() -> 1).hashCode()).isEqualTo(Objects.hashCode(1)); } @Test public void shouldComputeHashCodeForArrays() { Integer[] value = new Integer[] {1}; //noinspection ArrayHashCode assertThat(Lazy.of(() -> value).hashCode()).isEqualTo(value.hashCode()); } // -- toString @Test public void shouldConvertNonEvaluatedValueToString() { final Lazy lazy = Lazy.of(() -> 1); assertThat(lazy.toString()).isEqualTo("Lazy(?)"); } @Test public void shouldConvertEvaluatedValueToString() { final Lazy lazy = Lazy.of(() -> 1); lazy.get(); assertThat(lazy.toString()).isEqualTo("Lazy(1)"); } // -- spliterator @Test public void shouldHaveSizedSpliterator() { assertThat(Lazy.of(() -> 1).spliterator().hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue(); } @Test public void shouldHaveOrderedSpliterator() { assertThat(Lazy.of(() -> 1).spliterator().hasCharacteristics(Spliterator.ORDERED)).isTrue(); } @Test public void shouldReturnSizeWhenSpliterator() { assertThat(Lazy.of(() -> 1).spliterator().getExactSizeIfKnown()).isEqualTo(1); } // === OVERRIDDEN // -- isLazy @Override @Test public void shouldVerifyLazyProperty() { assertThat(empty().isLazy()).isTrue(); assertThat(of(1).isLazy()).isTrue(); } } /** * Lazy can't be empty. It is a placeholder for an existing value, but only evaluated when needed. * In order to re-use existing unit tests, that are valid for all Value implementations, * we provide here an _imaginary_ empty Lazy implementation, called 'undefined'. *

* Note: It is no good idea to leak it outside of the test scope into the core library (otherwise Undefined will be the new null). */ final class Undefined implements Value, Serializable { private static final long serialVersionUID = 1L; static final Undefined INSTANCE = new Undefined<>(); private Lazy prototype = Lazy.of(() -> null); private Undefined() { } @Override public T get() { throw new NoSuchElementException(); } @Override public boolean isAsync() { return prototype.isAsync(); } @Override public boolean isEmpty() { return true; } @Override public boolean isLazy() { return prototype.isLazy(); } @Override public boolean isSingleValued() { return prototype.isSingleValued(); } @Override public Value peek(Consumer action) { return this; } @Override public String stringPrefix() { return null; } @Override public Iterator iterator() { return Iterator.empty(); } @SuppressWarnings("unchecked") @Override public Value map(Function mapper) { return (Value) this; } @Override public boolean equals(Object o) { return o == INSTANCE; } @Override public int hashCode() { return 1; } @Override public String toString() { return "Lazy()"; } /** * Instance control for object serialization. * * @return The singleton instance of Undefined. * @see java.io.Serializable */ private Object readResolve() { return INSTANCE; } } vavr-0.10.0/vavr/src/test/java/io/vavr/MatchErrorTest.java000066400000000000000000000025411342074374400233630ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import org.junit.Test; import static io.vavr.API.$; import static io.vavr.API.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; public class MatchErrorTest { @Test public void shouldReturnCorrectObject() { final Object obj = new Object(); try { Match(obj).of( Case($(0), 0) ); failBecauseExceptionWasNotThrown(MatchError.class); } catch (MatchError matchError) { assertThat(matchError.getObject()).isEqualTo(obj); } } } vavr-0.10.0/vavr/src/test/java/io/vavr/MatchTest.java000066400000000000000000000407511342074374400223560ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.List; import io.vavr.collection.Set; import io.vavr.control.Either; import io.vavr.control.Option; import io.vavr.control.Option.Some; import io.vavr.control.Validation; import io.vavr.match.annotation.Patterns; import io.vavr.match.annotation.Unapply; import org.junit.Test; import java.math.BigDecimal; import java.time.Year; import java.util.function.Predicate; import static io.vavr.API.$; import static io.vavr.API.*; import static io.vavr.MatchTest_DeveloperPatterns.$Developer; import static io.vavr.Patterns.*; import static io.vavr.Predicates.*; import static org.assertj.core.api.Assertions.assertThat; public class MatchTest { // -- MatchError @Test(expected = MatchError.class) public void shouldThrowIfNotMatching() { Match(new Object()).of( Case($(ignored -> false), o -> null) ); } // -- $() @Test public void shouldMatchNullWithAnyReturningValue() { final Match.Case _case = Case($(), 1); final Object obj = null; assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldMatchAnyReturningValue() { final Match.Case _case = Case($(), 1); final Object obj = new Object(); assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldMatchNullWithAnyReturningAppliedFunction() { final Match.Case _case = Case($(), o -> 1); final Object obj = null; assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldMatchAnyReturningAppliedFunction() { final Match.Case _case = Case($(), o -> 1); final Object obj = new Object(); assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldTakeFirstMatch() { final String actual = Match(new Object()).of( Case($(), "first"), Case($(), "second") ); assertThat(actual).isEqualTo("first"); } // -- $(value) @Test public void shouldMatchValueReturningValue() { final Object obj = new Object(); final Match.Case _case = Case($(obj), 1); assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldMatchValueReturningValue_NegativeCase() { final Object obj = new Object(); final Match.Case _case = Case($(obj), 1); assertThat(_case.isDefinedAt(new Object())).isFalse(); } @Test public void shouldMatchValueReturningAppliedFunction() { final Object obj = new Object(); final Match.Case _case = Case($(obj), o -> 1); assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldMatchValueReturningAppliedFunction_NegativeCase() { final Object obj = new Object(); final Match.Case _case = Case($(obj), o -> 1); assertThat(_case.isDefinedAt(new Object())).isFalse(); } // -- $(predicate) @Test public void shouldMatchPredicateReturningValue() { final Object obj = new Object(); final Match.Case _case = Case($(is(obj)), 1); assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldMatchPredicateReturningValue_NegativeCase() { final Object obj = new Object(); final Match.Case _case = Case($(is(obj)), 1); assertThat(_case.isDefinedAt(new Object())).isFalse(); } @Test public void shouldMatchPredicateReturningAppliedFunction() { final Object obj = new Object(); final Match.Case _case = Case($(is(obj)), o -> 1); assertThat(_case.isDefinedAt(obj)).isTrue(); assertThat(_case.apply(obj)).isEqualTo(1); } @Test public void shouldMatchPredicateReturningAppliedFunction_NegativeCase() { final Object obj = new Object(); final Match.Case _case = Case($(is(obj)), o -> 1); assertThat(_case.isDefinedAt(new Object())).isFalse(); } // -- multiple cases // i match { // case 1 => "one" // case 2 => "two" // case _ => "many" // } @Test public void shouldMatchIntUsingPatterns() { final String actual = Match(3).of( Case($(1), "one"), Case($(2), "two"), Case($(), "many") ); assertThat(actual).isEqualTo("many"); } @Test public void shouldMatchIntUsingPredicates() { final String actual = Match(3).of( Case($(is(1)), "one"), Case($(is(2)), "two"), Case($(), "many") ); assertThat(actual).isEqualTo("many"); } @Test public void shouldComputeUpperBoundOfReturnValue() { final Number num = Match(3).of( Case($(is(1)), 1), Case($(is(2)), 2.0), Case($(), i -> new BigDecimal("" + i)) ); assertThat(num).isEqualTo(new BigDecimal("3")); } // -- instanceOf @Test public void shouldMatchUsingInstanceOf() { final Object obj = 1; final int actual = Match(obj).of( Case($(instanceOf(Year.class)), y -> 0), Case($(instanceOf(Integer.class)), i -> 1) ); assertThat(actual).isEqualTo(1); } // -- Either @Test public void shouldMatchLeft() { final Either either = Either.left(1); final String actual = Match(either).of( Case($Left($()), l -> "left: " + l), Case($Right($()), r -> "right: " + r) ); assertThat(actual).isEqualTo("left: 1"); } @Test public void shouldMatchRight() { final Either either = Either.right("a"); final String actual = Match(either).of( Case($Left($()), l -> "left: " + l), Case($Right($()), r -> "right: " + r) ); assertThat(actual).isEqualTo("right: a"); } // -- Option @Test public void shouldMatchSome() { final Option opt = Option.some(1); final String actual = Match(opt).of( Case($None(), "no value"), Case($Some($()), String::valueOf) ); assertThat(actual).isEqualTo("1"); } @Test public void shouldMatchNone() { final Option opt = Option.none(); final String actual = Match(opt).of( Case($Some($()), String::valueOf), Case($None(), "no value") ); assertThat(actual).isEqualTo("no value"); } @Test public void shouldDecomposeSomeTuple() { final Option> tuple2Option = Option.of(Tuple.of("Test", 123)); final Tuple2 actual = Match(tuple2Option).of( Case($Some($()), value -> { @SuppressWarnings("UnnecessaryLocalVariable") final Tuple2 tuple2 = value; // types are inferred correctly! return tuple2; }) ); assertThat(actual).isEqualTo(Tuple.of("Test", 123)); } @Test public void shouldDecomposeSomeSomeTuple() { final Option>> tuple2OptionOption = Option.of(Option.of(Tuple.of("Test", 123))); final Some> actual = Match(tuple2OptionOption).of( Case($Some($Some($(Tuple.of("Test", 123)))), value -> { @SuppressWarnings("UnnecessaryLocalVariable") final Some> some = value; // types are inferred correctly! return some; }) ); assertThat(actual).isEqualTo(Option.of(Tuple.of("Test", 123))); } // -- List @Test public void shouldDecomposeEmptyList() { final List list = List.empty(); final boolean isEmpty = Match(list).of( Case($Cons($(), $()), (x, xs) -> false), Case($Nil(), true) ); assertThat(isEmpty).isTrue(); } @Test public void shouldDecomposeNonEmptyList() { final List list = List.of(1); final boolean isNotEmpty = Match(list).of( Case($Nil(), false), Case($Cons($(), $()), (x, xs) -> true) ); assertThat(isNotEmpty).isTrue(); } @SuppressWarnings("UnnecessaryLocalVariable") @Test public void shouldDecomposeListOfTuple3() { final List> tuple3List = List.of( Tuple.of("begin", 10, 4.5), Tuple.of("middle", 11, 0.0), Tuple.of("end", 12, 1.2)); final String actual = Match(tuple3List).of( Case($Cons($(), $()), (x, xs) -> { // types are inferred correctly! final Tuple3 head = x; final List> tail = xs; return head + "::" + tail; }) ); assertThat(actual).isEqualTo("(begin, 10, 4.5)::List((middle, 11, 0.0), (end, 12, 1.2))"); } /* JDK 9 compiler errors: [ERROR] incompatible types: inferred type does not conform to equality constraint(s) inferred: io.vavr.control.Option.Some equality constraints(s): io.vavr.control.Option.Some @SuppressWarnings("UnnecessaryLocalVariable") @Test public void shouldDecomposeListWithNonEmptyTail() { final List> numberOptionList = List.of(Option.some(1), Option.some(2.0)); final String actual = Match(numberOptionList).of( Case($Cons($Some($(1)), $Cons($Some($(2.0)), $())), (x, xs) -> { final Option head = x; final List> tail = xs; return head + "::" + tail; }) ); assertThat(actual).isEqualTo("Some(1)::List(Some(2.0))"); } */ // -- Set @Test public void shouldDecomposeSet() { final Set abc = Set("abc"); final Set result = Match(abc).of( // Does not compile: the Java inference engine sees abc as a Function1 before a Set thus expects result to be of type Boolean Case($(), () -> abc) ); assertThat(result).isEqualTo(abc); } // -- Validation @Test public void shouldDecomposeValid() { final Validation valid = Validation.valid(1); final String actual = Match(valid).of( Case($Valid($(1)), i -> "ok"), Case($Invalid($()), error -> error) ); assertThat(actual).isEqualTo("ok"); } @Test public void shouldDecomposeInvalid() { final Validation valid = Validation.invalid("ok"); final String actual = Match(valid).of( Case($Valid($()), i -> "error"), Case($Invalid($("ok")), error -> error) ); assertThat(actual).isEqualTo("ok"); } // -- run @Test public void shouldRunUnitOfWork() { class OuterWorld { String effect = null; void displayHelp() { effect = "help"; } void displayVersion() { effect = "version"; } } final OuterWorld outerWorld = new OuterWorld(); Match("-v").of( Case($(isIn("-h", "--help")), o -> run(outerWorld::displayHelp)), Case($(isIn("-v", "--version")), o -> run(outerWorld::displayVersion)), Case($(), o -> { throw new IllegalArgumentException(); }) ); assertThat(outerWorld.effect).isEqualTo("version"); } @Test public void shouldRunWithInferredArguments() { class OuterWorld { Number effect = null; void writeInt(int i) { effect = i; } void writeDouble(double d) { effect = d; } } final OuterWorld outerWorld = new OuterWorld(); final Object obj = .1d; Match(obj).of( Case($(instanceOf(Integer.class)), i -> run(() -> outerWorld.writeInt(i))), Case($(instanceOf(Double.class)), d -> run(() -> outerWorld.writeDouble(d))), Case($(), o -> { throw new NumberFormatException(); }) ); assertThat(outerWorld.effect).isEqualTo(.1d); } // -- Developer @Test public void shouldMatchCustomTypeWithUnapplyMethod() { final Person person = new Developer("Daniel", true, Option.some(13)); final String actual = Match(person).of( Case($Developer($("Daniel"), $(true), $()), Person.Util::devInfo), Case($(), p -> "Unknown person: " + p.getName()) ); assertThat(actual).isEqualTo("Daniel is caffeinated."); } interface Person { String getName(); class Util { static String devInfo(String name, boolean isCaffeinated, Option number) { return name + " is " + (isCaffeinated ? "" : "not ") + "caffeinated."; } } } static final class Developer implements Person { private final String name; private final boolean isCaffeinated; private final Option number; Developer(String name, boolean isCaffeinated, Option number) { this.name = name; this.isCaffeinated = isCaffeinated; this.number = number; } public String getName() { return name; } public boolean isCaffeinated() { return isCaffeinated; } public Option number() { return number; } @Patterns static class $ { @Unapply static Tuple3> Developer(Developer dev) { return Tuple.of(dev.getName(), dev.isCaffeinated(), dev.number()); } } } // Ambiguity check @Test public void shouldNotAmbiguous() { { // value // Case("1", o -> "ok"); // Not possible, would lead to ambiguities (see below) assertThat(Case($("1"), () -> "ok").apply("1")).isEqualTo("ok"); assertThat(Case($("1"), "ok").apply("1")).isEqualTo("ok"); } { // predicate as variable Predicate p = s -> true; assertThat(Case($(p), o -> "ok").apply("1")).isEqualTo("ok"); // ambiguous, if Case(T, Function) present assertThat(Case($(p), () -> "ok").apply("1")).isEqualTo("ok"); assertThat(Case($(p), "ok").apply("1")).isEqualTo("ok"); } { // $(predicate) assertThat(Case($(o -> true), o -> "ok").apply("1")).isEqualTo("ok"); // ambiguous, if Case(T, Function) present assertThat(Case($(o -> true), () -> "ok").apply("1")).isEqualTo("ok"); assertThat(Case($(o -> true), "ok").apply("1")).isEqualTo("ok"); } { // $(value) assertThat(Case($("1"), o -> "ok").apply("1")).isEqualTo("ok"); // ambiguous, if Case(T, Function) present assertThat(Case($("1"), () -> "ok").apply("1")).isEqualTo("ok"); assertThat(Case($("1"), "ok").apply("1")).isEqualTo("ok"); } } } vavr-0.10.0/vavr/src/test/java/io/vavr/OutputTester.java000066400000000000000000000131221342074374400231410ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import org.junit.Test; import java.io.*; import java.nio.charset.Charset; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; /** * Small utility that allows to test code which write to standard error or standard out. * * @author Sebastian Zarnekow */ public class OutputTester { @Test public void shouldNormalizeToUnixLineSeparators() { assertThat(captureStdOut(() -> System.out.print("\r\n"))).isEqualTo("\n"); } /** * Encapsulate the standard output and error stream accessors. */ private enum Output { OUT { @Override void set(PrintStream stream) { System.setOut(stream); } @Override PrintStream get() { return System.out; } }, ERR { @Override void set(PrintStream stream) { System.setErr(stream); } @Override PrintStream get() { return System.err; } }; /** * Modifier for the output slot. */ abstract void set(PrintStream stream); /** * Accessor for the output slot. */ abstract PrintStream get(); /** * Capture the output written to this standard stream and normalize to unix line endings. */ String capture(Runnable action) { synchronized (this) { try { PrintStream orig = get(); try (ByteArrayOutputStream out = new ByteArrayOutputStream(); PrintStream inmemory = new PrintStream(out) { }) { set(inmemory); action.run(); return new String(out.toByteArray(), Charset.defaultCharset()).replace("\r\n", "\n"); } finally { set(orig); } } catch (IOException e) { fail("Unexpected IOException", e); return "UNREACHABLE"; } } } /** * Each attempt to write the this standard output will fail with an IOException */ void failOnWrite(Runnable action) { synchronized (this) { final PrintStream original = get(); try (PrintStream failingPrintStream = failingPrintStream()) { set(failingPrintStream); action.run(); } finally { set(original); } } } } private static OutputStream failingOutputStream() { return new OutputStream() { @Override public void write(int b) throws IOException { throw new IOException(); } }; } /** * Obtain a stream that fails on every attempt to write a byte. * * @return a new stram that will fail immediately. */ public static PrintStream failingPrintStream() { return new PrintStream(failingOutputStream()); } /** * Obtain a writer that fails on every attempt to write a byte. * * @return a new stram that will fail immediately. */ public static PrintWriter failingPrintWriter() { return new PrintWriter(failingOutputStream()); } /** * Execute the given runnable in a context, where each attempt to * write to stderr will fail with an {@link IOException} * * @param runnable the runnable to be executed. */ public static void withFailingErrOut(Runnable runnable) { Output.ERR.failOnWrite(runnable); } /** * Execute the given runnable in a context, where each attempt to * write to stdout will fail with an {@link IOException} * * @param runnable the runnable to be executed. */ public static void withFailingStdOut(Runnable runnable) { Output.OUT.failOnWrite(runnable); } /** * Execute the given runnable and capture everything that written * to stdout. The written text is normalized to unix line feeds before its returned. * * @param runnable the runnable to be executed. * @return the content written to stdout, normalized to unix line endings. */ public static String captureStdOut(Runnable runnable) { return Output.OUT.capture(runnable); } /** * Execute the given runnable and capture everything that written * to stderr. The written text is normalized to unix line feeds before its returned. * * @param runnable the runnable to be executed. * @return the content written to stderr, normalized to unix line endings. */ public static String captureErrOut(Runnable runnable) { return Output.ERR.capture(runnable); } } vavr-0.10.0/vavr/src/test/java/io/vavr/PartialFunctionTest.java000066400000000000000000000055041342074374400244210ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.HashMap; import io.vavr.collection.List; import io.vavr.control.Either; import io.vavr.control.Option; import org.junit.Test; import java.util.function.Predicate; import static org.assertj.core.api.Assertions.assertThat; public class PartialFunctionTest { @Test public void shouldReturnSome() { Option oneToOne = HashMap.of(1, "One").lift().apply(1); assertThat(oneToOne).isEqualTo(Option.some("One")); } @Test public void shouldReturnNone() { Option oneToOne = HashMap.empty().lift().apply(1); assertThat(oneToOne).isEqualTo(Option.none()); } @Test public void shouldUnliftTotalFunctionReturningAnOption() { final Predicate isEven = n -> n.intValue() % 2 == 0; final Function1> totalFunction = n -> isEven.test(n) ? Option.some("even") : Option.none(); final PartialFunction partialFunction = PartialFunction.unlift(totalFunction); assertThat(partialFunction.isDefinedAt(1)).isFalse(); assertThat(partialFunction.isDefinedAt(2)).isTrue(); assertThat(partialFunction.apply(2)).isEqualTo("even"); } @Test public void shouldNotBeDefinedAtLeft() { final Either left = Either.left(new RuntimeException()); assertThat(PartialFunction.getIfDefined().isDefinedAt(left)).isFalse(); } @Test public void shouldBeDefinedAtRight() { Either right = Either.right(42); PartialFunction, Number> ifDefined = PartialFunction.getIfDefined(); assertThat(ifDefined.isDefinedAt(right)).isTrue(); assertThat(ifDefined.apply(right)).isEqualTo(42); } @Test public void shouldCollectSomeValuesAndIgnoreNone() { final List evenNumbers = List.range(0, 10) .map(n -> n % 2 == 0 ? Option.some(n) : Option.none()) .collect(PartialFunction.getIfDefined()); assertThat(evenNumbers).containsExactly(0, 2, 4, 6, 8); } } vavr-0.10.0/vavr/src/test/java/io/vavr/PredicatesTest.java000066400000000000000000000140511342074374400233770ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.List; import org.junit.Test; import java.math.BigDecimal; import java.util.function.Predicate; import static io.vavr.API.$; import static io.vavr.API.*; import static io.vavr.Predicates.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class PredicatesTest { private static final Predicate IS_RUNTIME_EXCEPTION = instanceOf(RuntimeException.class); private static final Predicate IS_GT_ONE = i -> i > 1; private static final Predicate IS_GT_TWO = i -> i > 2; // -- allOf @Test public void shouldTestAllOf_PositiveCase() { assertThat(allOf().test(1)).isTrue(); assertThat(allOf(IS_GT_ONE, IS_GT_TWO).test(3)).isTrue(); } @Test public void shouldTestAllOf_NegativeCase() { assertThat(allOf(IS_GT_ONE, IS_GT_TWO).test(2)).isFalse(); } // -- anyOf @Test public void shouldTestAnyOf_PositiveCase() { assertThat(anyOf(IS_GT_ONE, IS_GT_TWO).test(3)).isTrue(); assertThat(anyOf(IS_GT_ONE, IS_GT_TWO).test(2)).isTrue(); } @Test public void shouldTestAnyOf_NegativeCase() { assertThat(anyOf().test(1)).isFalse(); assertThat(anyOf(IS_GT_ONE, IS_GT_TWO).test(1)).isFalse(); } // -- exits @Test public void shouldTestExists_PositiveCase() { assertThat(exists(IS_GT_ONE).test(List.of(1, 3))).isTrue(); } @Test public void shouldTestExists_NegativeCase() { assertThat(exists(IS_GT_ONE).test(List.of(1, 0))).isFalse(); } @Test public void shouldCheckExistsByLiftingPredicateInContravariantPositionToPredicateInCovariantPosition() { final List list = List(1, 2, 3); final Predicate p = n -> n.intValue() % 2 == 0; final boolean actual = Match(list).of( Case($(exists(p)), true), Case($(), false) ); assertThat(actual).isTrue(); } // -- forAll @Test public void shouldTestForAll_PositiveCase() { assertThat(forAll(IS_GT_ONE).test(List.of(2, 3))).isTrue(); } @Test public void shouldTestForAll_NegativeCase() { assertThat(forAll(IS_GT_ONE).test(List.of(3, 0))).isFalse(); } @Test public void shouldCheckForAllByLiftingPredicateInContravariantPositionToPredicateInCovariantPosition() { final List list = List(1, 2, 3); final Predicate p = n -> n.intValue() > 0; final boolean actual = Match(list).of( Case($(forAll(p)), true), Case($(), false) ); assertThat(actual).isTrue(); } // -- instanceOf @Test public void shouldTestInstanceOf_PositiveCase() { assertThat(instanceOf(Number.class).test(1)).isTrue(); assertThat(instanceOf(Number.class).test(new BigDecimal("1"))).isTrue(); assertThat(IS_RUNTIME_EXCEPTION.test(new NullPointerException())).isTrue(); } @Test public void shouldTestInstanceOf_NegativeCase() { assertThat(IS_RUNTIME_EXCEPTION.test(new Exception())).isFalse(); assertThat(IS_RUNTIME_EXCEPTION.test(new Error("error"))).isFalse(); assertThat(IS_RUNTIME_EXCEPTION.test(null)).isFalse(); } // -- is @Test public void shouldTestIs_PositiveCase() { assertThat(is(1).test(1)).isTrue(); assertThat(is((CharSequence) "1").test("1")).isTrue(); } @Test public void shouldTestIs_NegativeCase() { assertThat(is(1).test(2)).isFalse(); assertThat(is((CharSequence) "1").test(new StringBuilder("1"))).isFalse(); } // -- isIn @Test public void shouldTestIsIn_PositiveCase() { assertThat(isIn(1, 2, 3).test(2)).isTrue(); assertThat(isIn((CharSequence) "1", "2", "3").test("2")).isTrue(); } @Test public void shouldTestIsIn_NegativeCase() { assertThat(isIn(1, 2, 3).test(4)).isFalse(); assertThat(isIn((CharSequence) "1", "2", "3").test("4")).isFalse(); } // -- isNull @Test public void shouldTestIsNull_PositiveCase() { assertThat(isNull().test(null)).isTrue(); } @Test public void shouldTestIsNull_NegativeCase() { assertThat(isNull().test("")).isFalse(); } // -- isNotNull @Test public void shouldTestIsNotNull_PositiveCase() { assertThat(isNotNull().test("")).isTrue(); } @Test public void shouldTestIsNotNull_NegativeCase() { assertThat(isNotNull().test(null)).isFalse(); } // -- noneOf @Test public void shouldTestNoneOf_PositiveCase() { assertThat(noneOf().test(1)).isTrue(); assertThat(noneOf(IS_GT_ONE, IS_GT_TWO).test(1)).isTrue(); } @Test public void shouldTestNoneOf_NegativeCase() { assertThat(noneOf(IS_GT_ONE).test(2)).isFalse(); assertThat(noneOf(IS_GT_ONE, IS_GT_TWO).test(2)).isFalse(); } // -- not @Test public void shouldThrowWhenNegatingNull() { assertThatThrownBy(() -> not(null)).isInstanceOf(NullPointerException.class); } @Test public void shouldNegate_PositiveCase() { assertThat(not(IS_GT_ONE).test(0)).isTrue(); } @Test public void shouldNegate_NegativeCase() { assertThat(not(IS_GT_ONE).test(2)).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/Serializables.java000066400000000000000000000062541342074374400232530ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public final class Serializables { private Serializables() { } /** * Serializes a given object. * * @param obj An object. * @return IllegalStateException if an IOException occurs when writing the obj to the ObjectOutputStream. */ public static byte[] serialize(Object obj) { try (ByteArrayOutputStream buf = new ByteArrayOutputStream(); ObjectOutputStream stream = new ObjectOutputStream(buf)) { stream.writeObject(obj); return buf.toByteArray(); } catch (IOException x) { throw new IllegalStateException("Error serializing object", x); } } /** * Deserializes a given object, returning the correct target type of assignment or cast. *

* Examples: * *

     * 
     * // variable assignment
     * final CharSequence s = deserialize(serialize("test"));
     *
     * // type casting
     * final int i = ((String) deserialize(serialize("test"))).length();
     * 
     * 
* * @param Target type the deserialized object will be casted to. * @param objectData A serialized object. * @return The deserialized Object. * @throws IllegalStateException if an IOException occurs when reading from the ObjectInputStream or the serialized * class cannot be found. */ @SuppressWarnings("unchecked") public static T deserialize(byte[] objectData) { try (ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(objectData))) { return (T) stream.readObject(); } catch (IOException | ClassNotFoundException x) { throw new IllegalStateException("Error deserializing object", x); } } public static void callReadObject(Object o) throws Throwable { final byte[] objectData = Serializables.serialize(o); try (ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(objectData))) { final Method method = o.getClass().getDeclaredMethod("readObject", ObjectInputStream.class); method.setAccessible(true); try { method.invoke(o, stream); } catch (InvocationTargetException x) { throw (x.getCause() != null) ? x.getCause() : x; } } } } vavr-0.10.0/vavr/src/test/java/io/vavr/TestComparators.java000066400000000000000000000017711342074374400236130ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import java.util.Comparator; import static java.util.Comparator.comparing; public final class TestComparators { private TestComparators() { } public static Comparator toStringComparator() { return comparing(String::valueOf); } } vavr-0.10.0/vavr/src/test/java/io/vavr/TupleTest.java000066400000000000000000000434061342074374400224130ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.List; import org.assertj.core.api.Assertions; import org.junit.Test; import java.math.BigDecimal; import java.util.AbstractMap; import java.util.Objects; import static org.assertj.core.api.Assertions.assertThat; public class TupleTest { // -- Tuple0 @Test public void shouldCreateEmptyTuple() { assertThat(Tuple.empty().toString()).isEqualTo("()"); } @Test public void shouldHashTuple0() { assertThat(tuple0().hashCode()).isEqualTo(Objects.hash()); } @Test public void shouldReturnCorrectArityOfTuple0() { assertThat(tuple0().arity()).isEqualTo(0); } @Test public void shouldReturnCorrectSeqOfTuple0() { Assertions.assertThat(tuple0().toSeq()).isEqualTo(List.empty()); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple0Instances() { final Tuple0 t = tuple0(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple0EqualsNull() { assertThat(tuple0().equals(null)).isFalse(); } @Test public void shouldNotTuple0EqualsObject() { assertThat(tuple0().equals(new Object())).isFalse(); } @SuppressWarnings("EqualsWithItself") @Test public void shouldTuple0EqualTuple0() { assertThat(tuple0().equals(tuple0())).isTrue(); } @Test public void shouldDeserializeSingletonOfTuple0() { final Object tuple0 = Serializables.deserialize(Serializables.serialize(Tuple0.instance())); assertThat(tuple0 == Tuple0.instance()).isTrue(); } @Test public void shouldReturnComparator() { assertThat(Tuple0.comparator().compare(Tuple0.instance(), Tuple0.instance())).isEqualTo(0); } @Test public void shouldApplyTuple0() { assertThat(Tuple0.instance().apply(() -> 1) == 1).isTrue(); } @Test public void shouldCompareTuple0() { assertThat(Tuple0.instance().compareTo(Tuple0.instance())).isEqualTo(0); } // -- Tuple1 @Test public void shouldCreateSingle() { assertThat(tuple1().toString()).isEqualTo("(1)"); } @Test public void shouldHashTuple1() { final Tuple1 t = tuple1(); assertThat(t.hashCode()).isEqualTo(Tuple.hash(t._1)); } @Test public void shouldReturnCorrectArityOfTuple1() { assertThat(tuple1().arity()).isEqualTo(1); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple1Instances() { final Tuple1 t = tuple1(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple1EqualsNull() { assertThat(tuple1().equals(null)).isFalse(); } @Test public void shouldNotTuple1EqualsObject() { assertThat(tuple1().equals(new Object())).isFalse(); } @Test public void shouldTuple1EqualTuple1() { assertThat(tuple1().equals(tuple1())).isTrue(); } @Test public void shouldNarrowTuple1() { final Tuple1 wideTuple = Tuple.of(1.0d); final Tuple1 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo(1.0d); } // -- Tuple2 @Test public void shouldCreatePair() { assertThat(tuple2().toString()).isEqualTo("(1, 2)"); } @Test public void shouldCreateTuple2FromEntry() { final Tuple2 tuple2FromEntry = Tuple.fromEntry(new AbstractMap.SimpleEntry<>(1, 2)); assertThat(tuple2FromEntry.toString()).isEqualTo("(1, 2)"); } @Test public void shouldHashTuple2() { final Tuple2 t = tuple2(); assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2)); } @Test public void shouldReturnCorrectArityOfTuple2() { assertThat(tuple2().arity()).isEqualTo(2); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple2Instances() { final Tuple2 t = tuple2(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple2EqualsNull() { assertThat(tuple2().equals(null)).isFalse(); } @Test public void shouldNotTuple2EqualsObject() { assertThat(tuple2().equals(new Object())).isFalse(); } @Test public void shouldTuple2EqualTuple2() { assertThat(tuple2().equals(tuple2())).isTrue(); } @Test public void shouldCompareTuple2() { assertThat(Tuple.of(1, 1).compareTo(Tuple.of(1, 1))).isEqualTo(0); assertThat(Tuple.of(2, 1).compareTo(Tuple.of(1, 1))).isEqualTo(1); assertThat(Tuple.of(1, 2).compareTo(Tuple.of(1, 1))).isEqualTo(1); assertThat(Tuple.of(1, 1).compareTo(Tuple.of(2, 1))).isEqualTo(-1); assertThat(Tuple.of(1, 1).compareTo(Tuple.of(1, 2))).isEqualTo(-1); } @Test public void shouldNarrowTuple2() { final Tuple2 wideTuple = Tuple.of("test", 1.0d); final Tuple2 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo("test"); assertThat(narrowTuple._2()).isEqualTo(1.0d); } // -- Tuple3 @Test public void shouldCreateTriple() { assertThat(tuple3().toString()).isEqualTo("(1, 2, 3)"); } @Test public void shouldHashTuple3() { final Tuple3 t = tuple3(); assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2, t._3)); } @Test public void shouldReturnCorrectArityOfTuple3() { assertThat(tuple3().arity()).isEqualTo(3); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple3Instances() { final Tuple3 t = tuple3(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple3EqualsNull() { assertThat(tuple3().equals(null)).isFalse(); } @Test public void shouldNotTuple3EqualsObject() { assertThat(tuple3().equals(new Object())).isFalse(); } @Test public void shouldTuple3EqualTuple3() { assertThat(tuple3().equals(tuple3())).isTrue(); } @Test public void shouldNarrowTuple3() { final Tuple3 wideTuple = Tuple.of("zero", 1.0D, 2.0F); final Tuple3 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo("zero"); assertThat(narrowTuple._2()).isEqualTo(1.0D); assertThat(narrowTuple._3()).isEqualTo(2.0F); } // -- Tuple4 @Test public void shouldCreateQuadruple() { assertThat(tuple4().toString()).isEqualTo("(1, 2, 3, 4)"); } @Test public void shouldHashTuple4() { final Tuple4 t = tuple4(); assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2, t._3, t._4)); } @Test public void shouldReturnCorrectArityOfTuple4() { assertThat(tuple4().arity()).isEqualTo(4); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple4Instances() { final Tuple4 t = tuple4(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple4EqualsNull() { assertThat(tuple4().equals(null)).isFalse(); } @Test public void shouldNotTuple4EqualsObject() { assertThat(tuple4().equals(new Object())).isFalse(); } @Test public void shouldTuple4EqualTuple4() { assertThat(tuple4().equals(tuple4())).isTrue(); } @Test public void shouldNarrowTuple4() { final Tuple4 wideTuple = Tuple.of("zero", 1.0D, 2.0F, 3); final Tuple4 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo("zero"); assertThat(narrowTuple._2()).isEqualTo(1.0D); assertThat(narrowTuple._3()).isEqualTo(2.0F); assertThat(narrowTuple._4()).isEqualTo(3); } // -- Tuple5 @Test public void shouldCreateQuintuple() { assertThat(tuple5().toString()).isEqualTo("(1, 2, 3, 4, 5)"); } @Test public void shouldHashTuple5() { final Tuple5 t = tuple5(); assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2, t._3, t._4, t._5)); } @Test public void shouldReturnCorrectArityOfTuple5() { assertThat(tuple5().arity()).isEqualTo(5); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple5Instances() { final Tuple5 t = tuple5(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple5EqualsNull() { assertThat(tuple5().equals(null)).isFalse(); } @Test public void shouldNotTuple5EqualsObject() { assertThat(tuple5().equals(new Object())).isFalse(); } @Test public void shouldTuple5EqualTuple5() { assertThat(tuple5().equals(tuple5())).isTrue(); } @Test public void shouldNarrowTuple5() { final Tuple5 wideTuple = Tuple.of("zero", 1.0D, 2.0F, 3, 4L); final Tuple5 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo("zero"); assertThat(narrowTuple._2()).isEqualTo(1.0D); assertThat(narrowTuple._3()).isEqualTo(2.0F); assertThat(narrowTuple._4()).isEqualTo(3); assertThat(narrowTuple._5()).isEqualTo(4L); } // -- Tuple6 @Test public void shouldCreateSextuple() { assertThat(tuple6().toString()).isEqualTo("(1, 2, 3, 4, 5, 6)"); } @Test public void shouldHashTuple6() { final Tuple6 t = tuple6(); assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2, t._3, t._4, t._5, t._6)); } @Test public void shouldReturnCorrectArityOfTuple6() { assertThat(tuple6().arity()).isEqualTo(6); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple6Instances() { final Tuple6 t = tuple6(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple6EqualsNull() { assertThat(tuple6().equals(null)).isFalse(); } @Test public void shouldNotTuple6EqualsObject() { assertThat(tuple6().equals(new Object())).isFalse(); } @Test public void shouldTuple6EqualTuple6() { assertThat(tuple6().equals(tuple6())).isTrue(); } @Test public void shouldNarrowTuple6() { final Tuple6 wideTuple = Tuple.of("zero", 1.0D, 2.0F, 3, 4L, (byte) 5); final Tuple6 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo("zero"); assertThat(narrowTuple._2()).isEqualTo(1.0D); assertThat(narrowTuple._3()).isEqualTo(2.0F); assertThat(narrowTuple._4()).isEqualTo(3); assertThat(narrowTuple._5()).isEqualTo(4L); assertThat(narrowTuple._6()).isEqualTo((byte) 5); } // -- Tuple7 @Test public void shouldCreateTuple7() { assertThat(tuple7().toString()).isEqualTo("(1, 2, 3, 4, 5, 6, 7)"); } @Test public void shouldHashTuple7() { final Tuple7 t = tuple7(); assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2, t._3, t._4, t._5, t._6, t._7)); } @Test public void shouldReturnCorrectArityOfTuple7() { assertThat(tuple7().arity()).isEqualTo(7); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple7Instances() { final Tuple7 t = tuple7(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple7EqualsNull() { assertThat(tuple7().equals(null)).isFalse(); } @Test public void shouldNotTuple7EqualsObject() { assertThat(tuple7().equals(new Object())).isFalse(); } @Test public void shouldTuple7EqualTuple7() { assertThat(tuple7().equals(tuple7())).isTrue(); } @Test public void shouldNarrowTuple7() { final Tuple7 wideTuple = Tuple.of("zero", 1.0D, 2.0F, 3, 4L, (byte) 5, (short) 6); final Tuple7 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo("zero"); assertThat(narrowTuple._2()).isEqualTo(1.0D); assertThat(narrowTuple._3()).isEqualTo(2.0F); assertThat(narrowTuple._4()).isEqualTo(3); assertThat(narrowTuple._5()).isEqualTo(4L); assertThat(narrowTuple._6()).isEqualTo((byte) 5); assertThat(narrowTuple._7()).isEqualTo((short) 6); } // -- Tuple8 @Test public void shouldCreateTuple8() { assertThat(tuple8().toString()).isEqualTo("(1, 2, 3, 4, 5, 6, 7, 8)"); } @Test public void shouldHashTuple8() { final Tuple8 t = tuple8(); assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2, t._3, t._4, t._5, t._6, t._7, t._8)); } @Test public void shouldReturnCorrectArityOfTuple8() { assertThat(tuple8().arity()).isEqualTo(8); } @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTuple8Instances() { final Tuple8 t = tuple8(); assertThat(t.equals(t)).isTrue(); } @SuppressWarnings("ObjectEqualsNull") @Test public void shouldNotTuple8EqualsNull() { assertThat(tuple8().equals(null)).isFalse(); } @Test public void shouldNotTuple8EqualsObject() { assertThat(tuple8().equals(new Object())).isFalse(); } @Test public void shouldTuple8EqualTuple8() { assertThat(tuple8().equals(tuple8())).isTrue(); } @Test public void shouldNarrowTuple8() { final Tuple8 wideTuple = Tuple.of("zero", 1.0D, 2.0F, 3, 4L, (byte) 5, (short) 6, new BigDecimal(7)); final Tuple8 narrowTuple = Tuple.narrow(wideTuple); assertThat(narrowTuple._1()).isEqualTo("zero"); assertThat(narrowTuple._2()).isEqualTo(1.0D); assertThat(narrowTuple._3()).isEqualTo(2.0F); assertThat(narrowTuple._4()).isEqualTo(3); assertThat(narrowTuple._5()).isEqualTo(4L); assertThat(narrowTuple._6()).isEqualTo((byte) 5); assertThat(narrowTuple._7()).isEqualTo((short) 6); assertThat(narrowTuple._8()).isEqualTo(new BigDecimal(7)); } // -- nested tuples @Test public void shouldDetectEqualityOnTupleOfTuples() { final Tuple tupleA = Tuple.of(Tuple.of(1), Tuple.of(1)); final Tuple tupleB = Tuple.of(Tuple.of(1), Tuple.of(1)); assertThat(tupleA.equals(tupleB)).isTrue(); } @Test public void shouldDetectUnequalityOnTupleOfTuples() { final Tuple tupleA = Tuple.of(Tuple.of(1), Tuple.of(1)); final Tuple tupleB = Tuple.of(Tuple.of(1), Tuple.of(2)); assertThat(tupleA.equals(tupleB)).isFalse(); } // -- Serializable interface @Test public void shouldSerializeDeserializeTuple0() { final Object actual = Serializables.deserialize(Serializables.serialize(Tuple0.instance())); final Object expected = Tuple0.instance(); assertThat(actual).isEqualTo(expected); } @Test public void shouldPreserveSingletonInstanceOnDeserialization() { final boolean actual = Serializables.deserialize(Serializables.serialize(Tuple0.instance())) == Tuple0.instance(); assertThat(actual).isTrue(); } @Test public void shouldSerializeDeserializeNonEmptyTuple() { final Object actual = Serializables.deserialize(Serializables.serialize(Tuple.of(1, 2, 3))); final Object expected = Tuple.of(1, 2, 3); assertThat(actual).isEqualTo(expected); } // -- helpers private Tuple0 tuple0() { return Tuple.empty(); } private Tuple1 tuple1() { return Tuple.of(1); } private Tuple2 tuple2() { return Tuple.of(1, 2); } private Tuple3 tuple3() { return Tuple.of(1, 2, 3); } private Tuple4 tuple4() { return Tuple.of(1, 2, 3, 4); } private Tuple5 tuple5() { return Tuple.of(1, 2, 3, 4, 5); } private Tuple6 tuple6() { return Tuple.of(1, 2, 3, 4, 5, 6); } private Tuple7 tuple7() { return Tuple.of(1, 2, 3, 4, 5, 6, 7); } private Tuple8 tuple8() { return Tuple.of(1, 2, 3, 4, 5, 6, 7, 8); } } vavr-0.10.0/vavr/src/test/java/io/vavr/ValueTest.java000066400000000000000000000043111342074374400223660ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr; import io.vavr.collection.List; import io.vavr.control.Option; import org.junit.Test; import java.util.ArrayList; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; public class ValueTest { @Test public void shouldNarrowValue() { final Value doubles = List.of(1.0d); final Value numbers = Value.narrow(doubles); assertThat(numbers.get()).isEqualTo(1.0d); } @Test public void collectWorkAsExpectedMultiValue() { final Value doubles = List.of(1.0d, 2.0d); final java.util.List result = doubles.collect(Collectors.toList()); assertThat(result).contains(1.0d, 2.0d); } @Test public void verboseCollectWorkAsExpectedMultiValue() { final Value doubles = List.of(1.0d, 2.0d); final java.util.List result = doubles.collect(ArrayList::new, ArrayList::add, ArrayList::addAll); assertThat(result).contains(1.0d, 2.0d); } @Test public void collectWorkAsExpectedSingleValue() { final Value doubles = Option.of(1.0d); assertThat(doubles.collect(Collectors.toList()).get(0)).isEqualTo(1.0d); } @Test public void verboseCollectWorkAsExpectedSingleValue() { final Value doubles = Option.of(1.0d); assertThat(doubles.collect(ArrayList::new, ArrayList::add, ArrayList::addAll).get(0)).isEqualTo(1.0d); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/000077500000000000000000000000001342074374400217435ustar00rootroot00000000000000vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractIndexedSeqTest.java000066400000000000000000000032161342074374400271650ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import org.junit.Test; import java.math.BigDecimal; import java.util.Spliterator; public abstract class AbstractIndexedSeqTest extends AbstractSeqTest { @Override abstract protected IndexedSeq of(T element); // -- static narrow @Test public void shouldNarrowIndexedSeq() { final IndexedSeq doubles = of(1.0d); final IndexedSeq numbers = IndexedSeq.narrow(doubles); final int actual = numbers.append(new BigDecimal("2.0")).sum().intValue(); assertThat(actual).isEqualTo(3); } // -- spliterator @Test public void shouldHaveSizedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue(); } @Test public void shouldReturnSizeWhenSpliterator() { assertThat(of(1, 2, 3).spliterator().getExactSizeIfKnown()).isEqualTo(3); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractLinearSeqTest.java000066400000000000000000000024101342074374400270120ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import org.junit.Test; import java.math.BigDecimal; public abstract class AbstractLinearSeqTest extends AbstractSeqTest { @Override abstract protected LinearSeq of(T element); // -- static narrow @Test public void shouldNarrowIndexedSeq() { final LinearSeq doubles = of(1.0d); final LinearSeq numbers = LinearSeq.narrow(doubles); final int actual = numbers.append(new BigDecimal("2.0")).sum().intValue(); assertThat(actual).isEqualTo(3); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractMapTest.java000066400000000000000000001621141342074374400256540ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Function1; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import org.assertj.core.api.IterableAssert; import org.junit.Test; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.*; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.stream.Collector; import static java.util.Arrays.asList; import static io.vavr.API.Some; import static io.vavr.Serializables.deserialize; import static io.vavr.Serializables.serialize; public abstract class AbstractMapTest extends AbstractTraversableTest { @Override protected IterableAssert assertThat(Iterable actual) { return new IterableAssert(actual) { @Override public IterableAssert isEqualTo(Object obj) { @SuppressWarnings("unchecked") final Iterable expected = (Iterable) obj; final java.util.Map actualMap = countMap(actual); final java.util.Map expectedMap = countMap(expected); assertThat(actualMap.size()).isEqualTo(expectedMap.size()); actualMap.forEach((k, v) -> assertThat(v).isEqualTo(expectedMap.get(k))); return this; } private java.util.Map countMap(Iterable it) { final java.util.HashMap cnt = new java.util.HashMap<>(); it.forEach(i -> cnt.merge(i, 1, (v1, v2) -> v1 + v2)); return cnt; } }; } @Override protected Collector, IntMap> collector() { final Collector, ArrayList>, ? extends Map> mapCollector = mapCollector(); return new Collector, IntMap>() { @Override public Supplier> supplier() { return ArrayList::new; } @Override public BiConsumer, T> accumulator() { return ArrayList::add; } @Override public BinaryOperator> combiner() { return (left, right) -> fromTuples(mapCollector.combiner().apply(toTuples(left), toTuples(right))); } @Override public Function, IntMap> finisher() { return AbstractMapTest.this::ofAll; } @Override public Set characteristics() { return mapCollector.characteristics(); } private ArrayList> toTuples(java.util.List list) { final ArrayList> result = new ArrayList<>(); Stream.ofAll(list) .zipWithIndex() .map(tu -> Tuple.of(tu._2, tu._1)) .forEach(result::add); return result; } private ArrayList fromTuples(java.util.List> list) { final ArrayList result = new ArrayList<>(); Stream.ofAll(list) .map(tu -> tu._2) .forEach(result::add); return result; } }; } @Override protected IntMap empty() { return IntMap.of(emptyMap()); } @Override protected boolean emptyShouldBeSingleton() { return false; } private Map emptyInt() { return emptyMap(); } protected Map emptyIntInt() { return emptyMap(); } private Map emptyIntString() { return emptyMap(); } protected abstract String className(); abstract java.util.Map javaEmptyMap(); protected abstract , T2> Map emptyMap(); protected abstract , V, T extends V> Collector, ? extends Map> collectorWithMapper( Function keyMapper); protected abstract , V, T> Collector, ? extends Map> collectorWithMappers( Function keyMapper, Function valueMapper); protected boolean emptyMapShouldBeSingleton() { return true; } protected abstract Collector, ArrayList>, ? extends Map> mapCollector(); @SuppressWarnings("unchecked") protected abstract , V> Map mapOfTuples(Tuple2... entries); protected abstract , V> Map mapOfTuples(Iterable> entries); @SuppressWarnings("unchecked") protected abstract , V> Map mapOfEntries(java.util.Map.Entry... entries); protected abstract , V> Map mapOf(K k1, V v1); protected abstract , V> Map mapOf(K k1, V v1, K k2, V v2); protected abstract , V> Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3); protected abstract , V> Map mapOf(java.util.stream.Stream stream, Function keyMapper, Function valueMapper); protected abstract , V> Map mapOf(java.util.stream.Stream stream, Function> f); protected abstract , V> Map mapOfNullKey(K k1, V v1, K k2, V v2); protected abstract , V> Map mapOfNullKey(K k1, V v1, K k2, V v2, K k3, V v3); protected abstract , V> Map mapTabulate(int n, Function> f); protected abstract , V> Map mapFill(int n, Supplier> s); @Override protected boolean useIsEqualToInsteadOfIsSameAs() { return true; } @Override protected int getPeekNonNilPerformingAnAction() { return 1; } @Override protected IntMap of(T element) { Map map = emptyMap(); map = map.put(0, element); return IntMap.of(map); } @SuppressWarnings("unchecked") @Override protected IntMap of(T... elements) { Map map = emptyMap(); for (T element : elements) { map = map.put(map.size(), element); } return IntMap.of(map); } @Override protected IntMap ofAll(Iterable elements) { Map map = emptyMap(); for (T element : elements) { map = map.put(map.size(), element); } return IntMap.of(map); } @Override protected > IntMap ofJavaStream(java.util.stream.Stream javaStream) { return ofAll(io.vavr.collection.Iterator.ofAll(javaStream.iterator())); } @Override protected IntMap ofAll(boolean... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap ofAll(byte... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap ofAll(char... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap ofAll(double... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap ofAll(float... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap ofAll(int... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap ofAll(long... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap ofAll(short... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMap tabulate(int n, Function f) { Map map = emptyMap(); for (int i = 0; i < n; i++) { map = map.put(map.size(), f.apply(i)); } return IntMap.of(map); } @Override protected IntMap fill(int n, Supplier s) { return tabulate(n, anything -> s.get()); } // -- narrow @Test public void shouldNarrowMap() { final Map int2doubleMap = mapOf(1, 1.0d); final Map number2numberMap = Map.narrow(int2doubleMap); final int actual = number2numberMap.put(new BigDecimal("2"), new BigDecimal("2.0")).values().sum().intValue(); assertThat(actual).isEqualTo(3); } // -- mappers collector @Test public void shouldCollectWithKeyMapper() { Map map = java.util.stream.Stream.of(1, 2, 3).collect(collectorWithMapper(i -> i * 2)); assertThat(map).isEqualTo(mapOf(2, 1, 4, 2, 6, 3)); } @Test public void shouldCollectWithKeyValueMappers() { Map map = java.util.stream.Stream.of(1, 2, 3).collect(collectorWithMappers(i -> i * 2, String::valueOf)); assertThat(map).isEqualTo(mapOf(2, "1", 4, "2", 6, "3")); } // -- construction @Test public void shouldBeTheSame() { assertThat(mapOf(1, 2)).isEqualTo(emptyInt().put(1, 2)); } protected static java.util.Map.Entry asJavaEntry(int key, String value) { return new java.util.AbstractMap.SimpleEntry<>(key, value); } @SafeVarargs protected final java.util.Map asJavaMap(java.util.Map.Entry... entries) { final java.util.Map results = javaEmptyMap(); for (java.util.Map.Entry entry : entries) { results.put(entry.getKey(), entry.getValue()); } return results; } @Test public void shouldConstructFromJavaStream() { final java.util.stream.Stream javaStream = java.util.stream.Stream.of(1, 2, 3); final Map map = mapOf(javaStream, String::valueOf, Function.identity()); assertThat(map).isEqualTo(this. emptyMap().put("1", 1).put("2", 2).put("3", 3)); } @Test public void shouldConstructFromJavaStreamWithDuplicatedKeys() { assertThat(mapOf(Stream.range(0, 4).toJavaStream() , i -> Math.max(1, Math.min(i, 2)) , i -> String.valueOf(i + 1) )) .hasSize(2) .isEqualTo(mapOf(1, "2", 2, "4")); } @Test public void shouldConstructFromJavaStreamEntries() { final java.util.stream.Stream javaStream = java.util.stream.Stream.of(1, 2, 3); final Map map = mapOf(javaStream, i -> Tuple.of(String.valueOf(i), i)); assertThat(map).isEqualTo(this. emptyMap().put("1", 1).put("2", 2).put("3", 3)); } @Test public void shouldConstructFromJavaStreamEntriesWithDuplicatedKeys() { assertThat(mapOf(Stream.range(0, 4).toJavaStream(), i -> Map.entry(Math.max(1, Math.min(i, 2)), String.valueOf(i + 1)) )) .hasSize(2) .isEqualTo(mapOf(1, "2", 2, "4")); } @Test @SuppressWarnings("unchecked") public void shouldConstructFromUtilEntries() { final Map actual = mapOfEntries(asJavaEntry(1, "1"), asJavaEntry(2, "2"), asJavaEntry(3, "3")); final Map expected = this.emptyMap().put(1, "1").put(2, "2").put(3, "3"); assertThat(actual).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldConstructFromUtilEntriesWithDuplicatedKeys() { assertThat(mapOfEntries( asJavaEntry(1, "1"), asJavaEntry(1, "2"), asJavaEntry(2, "3"), asJavaEntry(2, "4") )) .hasSize(2) .isEqualTo(mapOf(1, "2", 2, "4")); } @Test @SuppressWarnings("unchecked") public void shouldConstructFromEntriesVararg() { final Map actual = mapOfTuples(Map.entry("1", 1), Map.entry("2", 2), Map.entry("3", 3)); final Map expected = this.emptyMap().put("1", 1).put("2", 2).put("3", 3); assertThat(actual).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldConstructFromEntriesVarargWithDuplicatedKeys() { assertThat(mapOfTuples( Map.entry(1, "1"), Map.entry(1, "2"), Map.entry(2, "3"), Map.entry(2, "4") )) .hasSize(2) .isEqualTo(mapOf(1, "2", 2, "4")); } @Test public void shouldConstructFromEntriesIterable() { final Map actual = mapOfTuples(asList(Map.entry("1", 1), Map.entry("2", 2), Map.entry("3", 3))); final Map expected = this.emptyMap().put("1", 1).put("2", 2).put("3", 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConstructFromEntriesIterableWithDuplicatedKeys() { assertThat(mapOfTuples(asList( Map.entry(1, "1"), Map.entry(1, "2"), Map.entry(2, "3"), Map.entry(2, "4") ))) .hasSize(2) .isEqualTo(mapOf(1, "2", 2, "4")); } @Test public void shouldConstructFromPairs() { final Map actual = mapOf("1", 1, "2", 2, "3", 3); final Map expected = this.emptyMap().put("1", 1).put("2", 2).put("3", 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConstructFromPairsWithDuplicatedKeys() { final Map actual = mapOf(1, "1", 1, "2", 2, "3"); final Map expected = this.emptyMap().put(1, "2").put(2, "3"); assertThat(actual).isEqualTo(expected); } @Test public void shouldConstructWithTabulate() { final Map actual = mapTabulate(4, i -> Tuple.of(i.toString(), i)); final Map expected = this.emptyMap().put("0", 0).put("1", 1).put("2", 2).put("3", 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConstructWithTabulateWithDuplicatedKeys() { assertThat(mapTabulate(4, i -> Tuple.of(Math.max(1, Math.min(i, 2)), String.valueOf(i + 1)) )) .hasSize(2) .isEqualTo(mapOf(1, "2", 2, "4")); } @Test public void shouldConstructWithFill() { AtomicInteger i = new AtomicInteger(); final Map actual = mapFill(4, () -> Tuple.of(String.valueOf(i.get()), i.getAndIncrement())); final Map expected = this.emptyMap().put("0", 0).put("1", 1).put("2", 2).put("3", 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldConstructWithFillWithDuplicatedKeys() { AtomicInteger i = new AtomicInteger(); assertThat(mapFill(4, () -> Tuple.of(Math.max(1, Math.min(i.get(), 2)), String.valueOf(i.getAndIncrement() + 1)) )) .hasSize(2) .isEqualTo(mapOf(1, "2", 2, "4")); } // -- asPartialFunction @Test public void shouldImplementPartialFunction() { PartialFunction f = mapOf(1, "1").asPartialFunction(); assertThat(f.isDefinedAt(1)).isTrue(); assertThat(f.apply(1)).isEqualTo("1"); assertThat(f.isDefinedAt(2)).isFalse(); } @Test public void shouldApplyExistingKey() { assertThat(emptyInt().put(1, 2).asPartialFunction().apply(1)).isEqualTo(2); } @Test(expected = NoSuchElementException.class) public void shouldApplyNonExistingKey() { emptyInt().put(1, 2).asPartialFunction().apply(3); } // -- equality @Test public void shouldObeyEqualityConstraints() { // sequential collections assertThat(emptyMap().equals(io.vavr.collection.HashMap.empty())).isTrue(); assertThat(mapOf(1, "a").equals(io.vavr.collection.HashMap.of(1, "a"))).isTrue(); assertThat(mapOf(1, "a", 2, "b", 3, "c").equals(io.vavr.collection.HashMap.of(1, "a", 2, "b",3, "c"))).isTrue(); assertThat(mapOf(1, "a", 2, "b", 3, "c").equals(io.vavr.collection.HashMap.of(3, "c", 2, "b",1, "a"))).isTrue(); // other classes assertThat(empty().equals(io.vavr.collection.List.empty())).isFalse(); assertThat(empty().equals(HashMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(io.vavr.collection.HashSet.empty())).isFalse(); assertThat(empty().equals(LinkedHashMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(io.vavr.collection.LinkedHashSet.empty())).isFalse(); assertThat(empty().equals(TreeMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(io.vavr.collection.TreeSet.empty())).isFalse(); } // -- head @Test(expected = NoSuchElementException.class) public void shouldThrowWhenHeadEmpty() { emptyMap().head(); } // -- init @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenInitEmpty() { emptyMap().init(); } // -- tail @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenTailEmpty() { emptyMap().tail(); } // -- toString @Test public void shouldMakeString() { assertThat(emptyMap().toString()).isEqualTo(className() + "()"); assertThat(emptyInt().put(1, 2).toString()).isEqualTo(className() + "(" + Tuple.of(1, 2) + ")"); } // -- toJavaMap @Test public void shouldConvertToJavaMap() { final Map actual = mapOf(1, "1", 2, "2", 3, "3"); final java.util.Map expected = asJavaMap(asJavaEntry(1, "1"), asJavaEntry(2, "2"), asJavaEntry(3, "3")); assertThat(actual.toJavaMap()).isEqualTo(expected); } // -- contains @Test public void shouldFindKey() { assertThat(emptyInt().put(1, 2).containsKey(1)).isTrue(); assertThat(emptyInt().put(1, 2).containsKey(2)).isFalse(); } @Test public void shouldFindValue() { assertThat(emptyInt().put(1, 2).containsValue(2)).isTrue(); assertThat(emptyInt().put(1, 2).containsValue(1)).isFalse(); } @Test public void shouldRecognizeNotContainedKeyValuePair() { final io.vavr.collection.TreeMap testee = io.vavr.collection.TreeMap.of(Tuple.of("one", 1)); assertThat(testee.contains(Tuple.of("one", 0))).isFalse(); } @Test public void shouldRecognizeContainedKeyValuePair() { final io.vavr.collection.TreeMap testee = io.vavr.collection.TreeMap.of(Tuple.of("one", 1)); assertThat(testee.contains(Tuple.of("one", 1))).isTrue(); } // -- flatMap @SuppressWarnings("unchecked") @Test public void shouldFlatMapUsingBiFunction() { final Map testee = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)); final Map actual = testee .flatMap((k, v) -> io.vavr.collection.List.of(Tuple.of(String.valueOf(k), String.valueOf(v)), Tuple.of(String.valueOf(k * 10), String.valueOf(v * 10)))); final Map expected = mapOfTuples(Tuple.of("1", "11"), Tuple.of("10", "110"), Tuple.of("2", "22"), Tuple.of("20", "220"), Tuple.of("3", "33"), Tuple.of("30", "330")); assertThat(actual).isEqualTo(expected); } // -- keySet @Test @SuppressWarnings("unchecked") public void shouldReturnKeySet() { final io.vavr.collection.Set actual = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)).keySet(); assertThat(actual).isEqualTo(io.vavr.collection.HashSet.of(1, 2, 3)); } @Test @SuppressWarnings("unchecked") public void shouldReturnKeysIterator() { final Iterator actual = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)).keysIterator(); assertThat(actual).isEqualTo(io.vavr.collection.Iterator.of(1, 2, 3)); } // -- values @Test @SuppressWarnings("unchecked") public void shouldReturnValuesSeq() { final Seq actual = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)).values(); assertThat(actual).isEqualTo(io.vavr.collection.Iterator.of(11, 22, 33)); } @Test @SuppressWarnings("unchecked") public void shouldReturnValuesIterator() { final Iterator actual = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)).valuesIterator(); assertThat(actual).isEqualTo(io.vavr.collection.Iterator.of(11, 22, 33)); } // -- biMap @Test public void shouldBiMapEmpty() { assertThat(emptyInt().bimap(i -> i + 1, o -> o)).isEqualTo(io.vavr.collection.Vector.empty()); } @Test public void shouldBiMapNonEmpty() { final Seq> expected = Stream.of(Tuple.of(2, "1!"), Tuple.of(3, "2!")); final Seq> actual = emptyInt().put(1, "1").put(2, "2").bimap(i -> i + 1, s -> s + "!").toStream(); assertThat(actual).isEqualTo(expected); } // -- orElse // DEV-Note: IntMap converts `other` to map @Override @Test public void shouldCaclEmptyOrElseSameOther() { Iterable other = of(42); assertThat(empty().orElse(other)).isEqualTo(other); } @Test public void shouldCaclEmptyOrElseSameSupplier() { Iterable other = of(42); Supplier> supplier = () -> other; assertThat(empty().orElse(supplier)).isEqualTo(other); } // -- map @Test public void shouldMapEmpty() { assertThat(emptyInt().map(Tuple2::_1)).isEqualTo(io.vavr.collection.Vector.empty()); } @Test public void shouldMapNonEmpty() { final Seq expected = io.vavr.collection.Vector.of(1, 2); final Seq actual = emptyInt().put(1, "1").put(2, "2").map(Tuple2::_1); assertThat(actual).isEqualTo(expected); } @Test public void shouldReturnEmptySetWhenAskedForTuple2SetOfAnEmptyMap() { assertThat(emptyMap().toSet()).isEqualTo(io.vavr.collection.HashSet.empty()); } @Test public void shouldReturnTuple2SetOfANonEmptyMap() { assertThat(emptyInt().put(1, "1").put(2, "2").toSet()).isEqualTo(io.vavr.collection.HashSet.of(Tuple.of(1, "1"), Tuple.of(2, "2"))); } @Test public void shouldReturnModifiedKeysMap() { final Map actual = emptyIntString().put(1, "1").put(2, "2").mapKeys(k -> k * 12).mapKeys(Integer::toHexString).mapKeys(String::toUpperCase); final Map expected = this. emptyMap().put("C", "1").put("18", "2"); assertThat(actual).isEqualTo(expected); } @Test public void shouldReturnModifiedKeysMapWithNonUniqueMapper() { final Map actual = emptyIntString() .put(1, "1").put(2, "2").put(3, "3") .mapKeys(k -> k * 118).mapKeys(Integer::toHexString).mapKeys(AbstractMapTest::md5).mapKeys(String::length); assertThat(actual).hasSize(1); assertThat(actual.values()).hasSize(1); //In different cases (based on items order) transformed map may contain different values assertThat(actual.values().head()).isIn("1", "2", "3"); } public static String md5(String src) { try { final MessageDigest md = MessageDigest.getInstance("MD5"); md.update(src.getBytes(StandardCharsets.UTF_8)); return toHexString(md.digest()); } catch (Exception e) { throw new IllegalStateException(e); } } /** * Returns a string in the hexadecimal format. * * @param bytes the converted bytes * @return the hexadecimal string representing the bytes data * @throws IllegalArgumentException if the byte array is null */ public static String toHexString(byte[] bytes) { if (bytes == null) { throw new IllegalArgumentException("byte array must not be null"); } final StringBuilder hex = new StringBuilder(bytes.length * 2); for (byte aByte : bytes) { hex.append(Character.forDigit((aByte & 0XF0) >> 4, 16)); hex.append(Character.forDigit((aByte & 0X0F), 16)); } return hex.toString(); } @Test public void shouldReturnModifiedKeysMapWithNonUniqueMapperAndMergedValues() { final Map actual = emptyIntString() .put(1, "1").put(2, "2").put(3, "3") .mapKeys(k -> k * 118).mapKeys(Integer::toHexString).mapKeys(AbstractMapTest::md5)//Unique key mappers .mapKeys(String::length, (v1, v2) -> io.vavr.collection.List.of(v1.split("#")).append(v2).sorted().mkString("#")); final Map expected = emptyIntString().put(32, "1#2#3"); assertThat(actual).isEqualTo(expected); } @Test public void shouldReturnModifiedValuesMap() { assertThat(emptyIntString().put(1, "1").put(2, "2").mapValues(Integer::parseInt)).isEqualTo(emptyInt().put(1, 1).put(2, 2)); } @Test public void shouldReturnListWithMappedValues() { assertThat(emptyIntInt().put(1, 1).put(2, 2).iterator((a, b) -> a + b).toList()).isEqualTo(io.vavr.collection.List.of(2, 4)); } // -- merge(Map) @Test public void shouldMerge() { final Map m1 = emptyIntInt().put(1, 1).put(2, 2); final Map m2 = emptyIntInt().put(1, 1).put(4, 4); final Map m3 = emptyIntInt().put(3, 3).put(4, 4); assertThat(m1.merge(m2)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(4, 4)); assertThat(m1.merge(m3)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4)); } @Test public void shouldReturnSameMapWhenMergeNonEmptyWithEmpty() { final Map map = mapOf(1, "a", 2, "b", 3, "c"); assertThat(map.merge(emptyMap())).isSameAs(map); } @Test public void shouldReturnSameMapWhenMergeEmptyWithNonEmpty() { final Map map = mapOf(1, "a", 2, "b", 3, "c"); if (map.isOrdered()) { assertThat(this. emptyMap().merge(map)).isEqualTo(map); } else { assertThat(this. emptyMap().merge(map)).isSameAs(map); } } // -- merge(Map, BiFunction) @Test public void shouldMergeCollisions() { final Map m1 = emptyIntInt().put(1, 1).put(2, 2); final Map m2 = emptyIntInt().put(1, 2).put(4, 4); final Map m3 = emptyIntInt().put(3, 3).put(4, 4); assertThat(emptyIntInt().merge(m2, Math::max)).isEqualTo(m2); assertThat(m2.merge(emptyIntInt(), Math::max)).isEqualTo(m2); assertThat(m1.merge(m2, Math::max)).isEqualTo(emptyIntInt().put(1, 2).put(2, 2).put(4, 4)); assertThat(m1.merge(m3, Math::max)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4)); } @Test public void shouldReturnSameMapWhenMergeNonEmptyWithEmptyUsingCollisionResolution() { final Map map = mapOf(1, 1, 2, 2, 3, 3); assertThat(map.merge(emptyMap(), Math::max)).isSameAs(map); } @Test public void shouldReturnSameMapWhenMergeEmptyWithNonEmptyUsingCollisionResolution() { final Map map = mapOf(1, 1, 2, 2, 3, 3); if (map.isOrdered()) { assertThat(this. emptyMap().merge(map, Math::max)).isEqualTo(map); } else { assertThat(this. emptyMap().merge(map, Math::max)).isSameAs(map); } } // -- equality @Test public void shouldIgnoreOrderOfEntriesWhenComparingForEquality() { final Map map1 = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c'); final Map map2 = emptyInt().put(3, 'c').put(2, 'b').put(1, 'a').remove(2).put(2, 'b'); assertThat(map1).isEqualTo(map2); } // -- put @Test public void shouldPutTuple() { assertThat(emptyIntInt().put(Tuple.of(1, 2))).isEqualTo(emptyIntInt().put(1, 2)); } @Test public void shouldPutNullKeyIntoMapThatContainsNullKey() { final Map map = mapOfNullKey(1, "a", null, "b", 2, "c"); assertThat(map.put(null, "!")).isEqualTo(mapOfNullKey(1, "a", null, "!", 2, "c")); } @Test public void shouldPutExistingKeyAndNonEqualValue() { final Map map = mapOf(new IntMod2(1), "a"); // we need to compare Strings because equals (intentionally) does not work for IntMod2 final String actual = map.put(new IntMod2(3), "b").toString(); final String expected = map.stringPrefix() + "((3, b))"; assertThat(actual).isEqualTo(expected); } @Test public void shouldPutExistingKeyAndEqualValue() { final Map map = mapOf(new IntMod2(1), "a"); // we need to compare Strings because equals (intentionally) does not work for IntMod2 final String actual = map.put(new IntMod2(3), "a").toString(); final String expected = map.stringPrefix() + "((3, a))"; assertThat(actual).isEqualTo(expected); } // -- remove @Test public void shouldRemoveKey() { final Map src = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c'); assertThat(src.remove(2)).isEqualTo(emptyInt().put(1, 'a').put(3, 'c')); assertThat(src.remove(33)).isSameAs(src); } @Test public void shouldRemoveFromMapThatContainsFirstEntryHavingNullKey() { final Map map = mapOfNullKey(null, "a", 1, "b", 2, "c"); assertThat(map.remove(1)).isEqualTo(mapOfNullKey(null, "a", 2, "c")); } // -- removeAll @Test public void shouldRemoveAllKeys() { final Map src = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c'); assertThat(src.removeAll(io.vavr.collection.List.of(1, 3))).isEqualTo(emptyInt().put(2, 'b')); assertThat(src.removeAll(io.vavr.collection.List.of(33))).isSameAs(src); assertThat(src.removeAll(io.vavr.collection.List.empty())).isSameAs(src); } @Test public void shouldReturnSameMapWhenNonEmptyRemoveAllEmpty() { final Map map = mapOf(1, "a", 2, "b", 3, "c"); assertThat(map.removeAll(io.vavr.collection.List.empty())).isSameAs(map); } @Test public void shouldReturnSameMapWhenEmptyRemoveAllNonEmpty() { final Map empty = emptyMap(); assertThat(empty.removeAll(io.vavr.collection.List.of(1, 2, 3))).isSameAs(empty); } // -- transform @Test public void shouldTransform() { final Map actual = emptyIntInt().put(1, 11).transform(map -> map.put(2, 22)); assertThat(actual).isEqualTo(emptyIntInt().put(1, 11).put(2, 22)); } // -- unzip @Test public void shouldUnzipIdentityNil() { assertThat(emptyMap().unzip()).isEqualTo(Tuple.of(Stream.empty(), Stream.empty())); } @Test public void shouldUnzipIdentityNonNil() { final Map map = emptyIntInt().put(0, 10).put(1, 11).put(2, 12); final Tuple actual = map.unzip(); final Tuple expected = Tuple.of(Stream.of(0, 1, 2), Stream.of(10, 11, 12)); assertThat(actual).isEqualTo(expected); } @Test public void shouldUnzipNil() { assertThat(emptyMap().unzip(x -> Tuple.of(x, x))).isEqualTo(Tuple.of(Stream.empty(), Stream.empty())); assertThat(emptyMap().unzip((k, v) -> Tuple.of(Tuple.of(k, v), Tuple.of(k, v)))) .isEqualTo(Tuple.of(Stream.empty(), Stream.empty())); } @Test public void shouldUnzipNonNil() { final Map map = emptyIntInt().put(0, 0).put(1, 1); final Tuple actual = map.unzip(entry -> Tuple.of(entry._1, entry._2 + 1)); final Tuple expected = Tuple.of(Stream.of(0, 1), Stream.of(1, 2)); assertThat(actual).isEqualTo(expected); } @Test public void shouldUnzip3Nil() { assertThat(emptyMap().unzip3(x -> Tuple.of(x, x, x))).isEqualTo(Tuple.of(Stream.empty(), Stream.empty(), Stream.empty())); assertThat(emptyMap().unzip3((k, v) -> Tuple.of(Tuple.of(k, v), Tuple.of(k, v), Tuple.of(k, v)))) .isEqualTo(Tuple.of(Stream.empty(), Stream.empty(), Stream.empty())); } @Test public void shouldUnzip3NonNil() { final Map map = emptyIntInt().put(0, 0).put(1, 1); final Tuple actual = map.unzip3(entry -> Tuple.of(entry._1, entry._2 + 1, entry._2 + 5)); final Tuple expected = Tuple.of(Stream.of(0, 1), Stream.of(1, 2), Stream.of(5, 6)); assertThat(actual).isEqualTo(expected); } // -- zip @Test public void shouldZipNils() { final Seq, Object>> actual = emptyInt().zip(io.vavr.collection.List.empty()); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipEmptyAndNonNil() { final Seq, Integer>> actual = emptyInt().zip(io.vavr.collection.List.of(1)); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipNonEmptyAndNil() { final Seq, Object>> actual = emptyIntInt().put(0, 1).zip(io.vavr.collection.List.empty()); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipNonNilsIfThisIsSmaller() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .zip(io.vavr.collection.List.of(5, 6, 7)); assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6))); } @Test public void shouldZipNonNilsIfThatIsSmaller() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .put(2, 2) .zip(io.vavr.collection.List.of(5, 6)); assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6))); } @Test public void shouldZipNonNilsOfSameSize() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .put(2, 2) .zip(io.vavr.collection.List.of(5, 6, 7)); assertThat(actual).isEqualTo( Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6), Tuple.of(Tuple.of(2, 2), 7))); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipWithThatIsNull() { emptyMap().zip(null); } // -- zipWithIndex @Test public void shouldZipNilWithIndex() { assertThat(emptyMap().zipWithIndex()).isEqualTo(Stream.empty()); } @Test public void shouldZipNonNilWithIndex() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .put(2, 2) .zipWithIndex(); assertThat(actual).isEqualTo( Stream.of(Tuple.of(Tuple.of(0, 0), 0), Tuple.of(Tuple.of(1, 1), 1), Tuple.of(Tuple.of(2, 2), 2))); } // -- zipAll @Test public void shouldZipAllNils() { final Seq, Object>> actual = emptyInt().zipAll(empty(), null, null); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipAllEmptyAndNonNil() { final Seq, Object>> actual = emptyInt().zipAll(io.vavr.collection.List.of(1), null, null); assertThat(actual).isEqualTo(Stream.of(Tuple.of(null, 1))); } @Test public void shouldZipAllNonEmptyAndNil() { final Seq, Object>> actual = emptyInt().put(0, 1).zipAll(empty(), null, null); assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 1), null))); } @Test public void shouldZipAllNonNilsIfThisIsSmaller() { final Seq, String>> actual = emptyIntInt() .put(1, 1) .put(2, 2) .zipAll(of("a", "b", "c"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(9, 10), "c")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThisIsMoreSmaller() { final Seq, String>> actual = emptyIntInt() .put(1, 1) .put(2, 2) .zipAll(of("a", "b", "c", "d"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(9, 10), "c"), Tuple.of(Tuple.of(9, 10), "d")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThatIsSmaller() { final Seq, String>> actual = emptyIntInt() .put(1, 1) .put(2, 2) .put(3, 3) .zipAll(this.of("a", "b"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "z")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThatIsMoreSmaller() { final Seq, String>> actual = emptyIntInt() .put(1, 1) .put(2, 2) .put(3, 3) .put(4, 4) .zipAll(of("a", "b"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "z"), Tuple.of(Tuple.of(4, 4), "z")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsOfSameSize() { final Seq, String>> actual = emptyIntInt() .put(1, 1) .put(2, 2) .put(3, 3) .zipAll(of("a", "b", "c"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "c")); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipAllWithThatIsNull() { emptyMap().zipAll(null, null, null); } // -- special cases @Override public void shouldComputeDistinctOfNonEmptyTraversable() { final Map testee = emptyInt().put(1, 1).put(2, 2).put(3, 3); assertThat(testee.distinct()).isEqualTo(testee); } @Override public void shouldReturnSomeTailWhenCallingTailOptionOnNonNil() { assertThat(of(1, 2, 3).tailOption().get()).isEqualTo(Option.some(of(2, 3)).get()); } @Override public void shouldPreserveSingletonInstanceOnDeserialization() { final Map obj = deserialize(serialize(emptyMap())); final boolean actual = obj == emptyMap(); assertThat(actual).isTrue(); } @Test public void shouldSerializeDeserializeNonEmptyMap() { final Object expected = of('a', 'b', 'c'); final Object actual = deserialize(serialize(expected)); assertThat(actual).isEqualTo(expected); } @Override public void shouldFoldRightNonNil() { final String actual = of('a', 'b', 'c').foldRight("", (x, xs) -> x + xs); final io.vavr.collection.List expected = io.vavr.collection.List.of('a', 'b', 'c').permutations().map(io.vavr.collection.List::mkString); assertThat(actual).isIn(expected); } // -- forEach @Test public void forEachByKeyValue() { final Map map = mapOf(1, 2).put(3, 4); final int[] result = { 0 }; map.forEach((k, v) -> { result[0] += k + v; }); assertThat(result[0]).isEqualTo(10); } @Test public void forEachByTuple() { final Map map = mapOf(1, 2).put(3, 4); final int[] result = { 0 }; map.forEach(t -> { result[0] += t._1 + t._2; }); assertThat(result[0]).isEqualTo(10); } // -- put with merge function @Test public void putWithWasntPresent() { final Map map = mapOf(1, 2) .put(2, 3, (x, y) -> x + y); assertThat(map).isEqualTo(emptyIntInt().put(1, 2).put(2, 3)); } @Test public void putWithWasPresent() { final Map map = mapOf(1, 2) .put(1, 3, (x, y) -> x + y); assertThat(map).isEqualTo(emptyIntInt().put(1, 5)); } @Test public void putWithTupleWasntPresent() { final Map map = mapOf(1, 2) .put(Tuple.of(2, 3), (x, y) -> x + y); assertThat(map).isEqualTo(emptyIntInt().put(1, 2).put(2, 3)); } @Test public void putWithTupleWasPresent() { final Map map = mapOf(1, 2) .put(Tuple.of(1, 3), (x, y) -> x + y); assertThat(map).isEqualTo(emptyIntInt().put(1, 5)); } @SuppressWarnings("unchecked") @Test public void shouldTabulateTheSeq() { final Function> f = i -> new Tuple2<>(i.longValue(), i.floatValue()); final Map map = mapTabulate(3, f); assertThat(map).isEqualTo(mapOfTuples(new Tuple2<>(0l, 0f), new Tuple2<>(1l, 1f), new Tuple2<>(2l, 2f))); } @SuppressWarnings("unchecked") @Test public void shouldTabulateTheSeqCallingTheFunctionInTheRightOrder() { final LinkedList ints = new LinkedList<>(asList(0, 0, 1, 1, 2, 2)); final Function> f = i -> new Tuple2<>(ints.remove().longValue(), ints.remove().floatValue()); final Map map = mapTabulate(3, f); assertThat(map).isEqualTo(mapOfTuples(new Tuple2<>(0l, 0f), new Tuple2<>(1l, 1f), new Tuple2<>(2l, 2f))); } @Test public void shouldTabulateTheSeqWith0Elements() { assertThat(mapTabulate(0, i -> new Tuple2<>(i, i))).isEqualTo(empty()); } @Test public void shouldTabulateTheSeqWith0ElementsWhenNIsNegative() { assertThat(mapTabulate(-1, i -> new Tuple2<>(i, i))).isEqualTo(empty()); } // -- fill(int, Supplier) @SuppressWarnings("unchecked") @Test public void shouldFillTheSeqCallingTheSupplierInTheRightOrder() { final LinkedList ints = new LinkedList<>(asList(0, 0, 1, 1, 2, 2)); final Supplier> s = () -> new Tuple2<>(ints.remove().longValue(), ints.remove().floatValue()); final Map actual = mapFill(3, s); assertThat(actual).isEqualTo(mapOfTuples(new Tuple2<>(0l, 0f), new Tuple2<>(1l, 1f), new Tuple2<>(2l, 2f))); } @Test public void shouldFillTheSeqWith0Elements() { assertThat(mapFill(0, () -> new Tuple2<>(1, 1))).isEqualTo(empty()); } @Test public void shouldReturnSingleMapAfterFillWithConstantKeys() { AtomicInteger value = new AtomicInteger(83); assertThat(mapFill(17, () -> Tuple.of(7, value.getAndIncrement()))) .hasSize(1) .isEqualTo(mapOf(7, value.decrementAndGet())); } @Test public void shouldFillTheSeqWith0ElementsWhenNIsNegative() { assertThat(mapFill(-1, () -> new Tuple2<>(1, 1))).isEqualTo(empty()); } @SuppressWarnings("unchecked") @Test public void mapOfTuplesShouldReturnTheSingletonEmpty() { if (!emptyMapShouldBeSingleton()) { return; } assertThat(mapOfTuples()).isSameAs(emptyMap()); } @SuppressWarnings("unchecked") @Test public void mapOfEntriesShouldReturnTheSingletonEmpty() { if (!emptyMapShouldBeSingleton()) { return; } assertThat(mapOfEntries()).isSameAs(emptyMap()); } @Test public void lift() { final Function1> lifted = mapOf("A", 1).lift(); assertThat(lifted.apply("A").get()).isEqualTo(1); assertThat(lifted.apply("a").isEmpty()).isTrue(); } // -- filter @Test public void shouldBiFilterWork() throws Exception { final Map src = mapTabulate(20, n -> Tuple.of(n, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Map dst = src.filter((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(2, "2").put(4, "4").put(6, "6").put(8, "8").put(16, "10").put(18, "12")); } @Test public void shouldKeyFilterWork() throws Exception { final Map src = mapTabulate(20, n -> Tuple.of(n, Integer.toHexString(n))); final Map dst = src.filterKeys(k -> k % 2 == 0); assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(2, "2").put(4, "4").put(6, "6").put(8, "8").put(10, "a").put(12, "c").put(14, "e").put(16, "10").put(18, "12")); } @Test public void shouldValueFilterWork() throws Exception { final Map src = mapTabulate(10, n -> Tuple.of(n, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Map dst = src.filterValues(v -> isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(1, "1").put(2, "2").put(3, "3").put(4, "4").put(5, "5").put(6, "6").put(7, "7").put(8, "8").put(9, "9")); } // -- reject @Test public void shouldBiRejectWork() throws Exception { final Map src = mapTabulate(20, n -> Tuple.of(n, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Map dst = src.reject((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(1, "1").put(3, "3").put(5, "5").put(7, "7").put(9, "9").put(10, "a").put(11, "b").put(12, "c").put(13, "d").put(14, "e").put(15, "f").put(17, "11").put(19, "13")); } @Test public void shouldKeyRejectWork() throws Exception { final Map src = mapTabulate(20, n -> Tuple.of(n, Integer.toHexString(n))); final Map dst = src.rejectKeys(k -> k % 2 == 0); assertThat(dst).isEqualTo(emptyIntString().put(1, "1").put(3, "3").put(5, "5").put(7, "7").put(9, "9").put(11, "b").put(13, "d").put(15, "f").put(17, "11").put(19, "13")); } @Test public void shouldValueRejectWork() throws Exception { final Map src = mapTabulate(15, n -> Tuple.of(n, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Map dst = src.rejectValues(v -> isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(10, "a").put(11, "b").put(12, "c").put(13, "d").put(14, "e")); } // -- remove by filter @SuppressWarnings("deprecation") @Test public void shouldBiRemoveWork() throws Exception { final Map src = mapTabulate(20, n -> Tuple.of(n, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Map dst = src.removeAll((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(1, "1").put(3, "3").put(5, "5").put(7, "7").put(9, "9").put(10, "a").put(11, "b").put(12, "c").put(13, "d").put(14, "e").put(15, "f").put(17, "11").put(19, "13")); } @SuppressWarnings("deprecation") @Test public void shouldKeyRemoveWork() throws Exception { final Map src = mapTabulate(20, n -> Tuple.of(n, Integer.toHexString(n))); final Map dst = src.removeKeys(k -> k % 2 == 0); assertThat(dst).isEqualTo(emptyIntString().put(1, "1").put(3, "3").put(5, "5").put(7, "7").put(9, "9").put(11, "b").put(13, "d").put(15, "f").put(17, "11").put(19, "13")); } @SuppressWarnings("deprecation") @Test public void shouldValueRemoveWork() throws Exception { final Map src = mapTabulate(20, n -> Tuple.of(n, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Map dst = src.removeValues(v -> isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(10, "a").put(11, "b").put(12, "c").put(13, "d").put(14, "e").put(15, "f")); } // -- computeIfAbsent @Test public void shouldComputeIfAbsent() { final Map map = emptyIntString().put(1, "v"); assertThat(map.computeIfAbsent(1, k -> "b")).isEqualTo(Tuple.of("v", map)); assertThat(map.computeIfAbsent(2, k -> "n")).isEqualTo(Tuple.of("n", emptyIntString().put(1, "v").put(2, "n"))); } // -- computeIfAbsent @Test public void shouldComputeIfPresent() { final Map map = emptyIntString().put(1, "v"); assertThat(map.computeIfPresent(1, (k, v) -> "b")).isEqualTo(Tuple.of(Option.of("b"), emptyIntString().put(1, "b"))); assertThat(map.computeIfPresent(2, (k, v) -> "n")).isEqualTo(Tuple.of(Option.none(), map)); } // -- get with nulls @Test public void shouldReturnOptionOfNullWhenAccessingKeysSetToNull() { final Map map = mapOf("1", null); assertThat(map.get("1")).isEqualTo(Option.some(null)); } @Test public void shouldReturnOptionOfKeyWhenAccessingPresentKeysInAMapWithNulls() { final Map map = mapOf("1", "a").put("2", null); assertThat(map.get("1")).isEqualTo(Option.of("a")); } @Test public void shouldReturnNoneWhenAccessingAbsentKeysInAMapWithNulls() { final Map map = mapOf("1", "a").put("2", null); assertThat(map.get("3")).isEqualTo(Option.none()); } @Test public void shouldReturnSameInstanceIfReplacingCurrentValueWithNonExistingKey() { final Map map = mapOf(1, "a", 2, "b"); final Map actual = map.replaceValue(3, "?"); assertThat(actual).isSameAs(map); } @Test public void shouldReplaceCurrentValueForExistingKey() { final Map map = mapOf(1, "a", 2, "b"); final Map actual = map.replaceValue(2, "c"); final Map expected = mapOf(1, "a", 2, "c"); assertThat(actual).isEqualTo(expected); } @Test public void shouldReplaceCurrentValueForExistingKeyAndEqualOldValue() { final Map map = mapOf(1, "a", 2, "b"); final Map actual = map.replace(2, "b", "c"); final Map expected = mapOf(1, "a", 2, "c"); assertThat(actual).isEqualTo(expected); } @Test public void shouldReturnSameInstanceForExistingKeyAndNonEqualOldValue() { final Map map = mapOf(1, "a", 2, "b"); final Map actual = map.replace(2, "d", "c"); assertThat(actual).isSameAs(map); } @Test public void shouldReturnSameInstanceIfReplacingCurrentValueWithOldValueWithNonExistingKey() { final Map map = mapOf(1, "a", 2, "b"); final Map actual = map.replace(3, "?", "!"); assertThat(actual).isSameAs(map); } @Test public void shouldReplaceAllValuesWithFunctionResult() { final Map map = mapOf(1, "a", 2, "b"); final Map actual = map.replaceAll((integer, s) -> s + integer); final Map expected = mapOf(1, "a1", 2, "b2"); assertThat(actual).isEqualTo(expected); } @Test public void shouldGetValueOfNullKeyWhenPutFirstHavingTwoEntries() { final Map map = mapOfNullKey(null, "a", 2, "b"); assertThat(map.get(null)).isEqualTo(Some("a")); } @Test public void shouldGetValueOfNullKeyWhenPutLastHavingTwoEntries() { final Map map = mapOfNullKey(1, "a", null, "b"); assertThat(map.get(null)).isEqualTo(Some("b")); } @Test public void shouldGetAPresentNullValueWhenPutFirstHavingTwoEntries() { final Map map = mapOf(1, null, 2, "b"); assertThat(map.get(1)).isEqualTo(Some(null)); } @Test public void shouldGetAPresentNullValueWhenPutLastHavingTwoEntries() { final Map map = mapOf(1, "a", 2, null); assertThat(map.get(2)).isEqualTo(Some(null)); } // -- getOrElse @Test public void shouldReturnDefaultValue() { final Map map = mapOf("1", "a").put("2", "b"); assertThat(map.getOrElse("3", "3")).isEqualTo("3"); } // -- spliterator @Test public void shouldHaveSizedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue(); } @Test public void shouldHaveDistinctSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.DISTINCT)).isTrue(); } @Test public void shouldReturnSizeWhenSpliterator() { assertThat(of(1, 2, 3).spliterator().getExactSizeIfKnown()).isEqualTo(3); } @Override @Test @SuppressWarnings("unchecked") public void shouldPartitionIntsInOddAndEvenHavingOddAndEvenNumbers() { assertThat(of(1, 2, 3, 4).partition(i -> i % 2 != 0)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0, 1), Tuple.of(2, 3)), mapOfTuples(Tuple.of(1, 2), Tuple.of(3, 4)))); } @Override @Test @SuppressWarnings("unchecked") public void shouldSpanNonNil() { assertThat(of(0, 1, 2, 3).span(i -> i < 2)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0, 0), Tuple.of(1, 1)), mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 3)))); } @Override @Test @SuppressWarnings("unchecked") public void shouldSpanAndNotTruncate() { assertThat(of(1, 1, 2, 2, 3, 3).span(x -> x % 2 == 1)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0,1), Tuple.of(1, 1)), mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 2), Tuple.of(4, 3), Tuple.of(5, 3)))); assertThat(of(1, 1, 2, 2, 4, 4).span(x -> x == 1)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0,1), Tuple.of(1, 1)), mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 2), Tuple.of(4, 4), Tuple.of(5, 4)))); } @Override @Test public void shouldNonNilGroupByIdentity() { final Map actual = of('a', 'b', 'c').groupBy(Function.identity()); final Map expected = io.vavr.collection.LinkedHashMap.empty().put('a', mapOf(0, 'a')).put('b', mapOf(1,'b')) .put('c', mapOf(2,'c')); assertThat(actual).isEqualTo(expected); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractMultimapTest.java000066400000000000000000001364621342074374400267360ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import org.assertj.core.api.IterableAssert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.stream.Collector; import static java.util.Arrays.asList; @RunWith(Parameterized.class) public abstract class AbstractMultimapTest extends AbstractTraversableTest { @Parameterized.Parameters public static Collection data() { return asList(new Object[][] { { Multimap.ContainerType.SEQ }, { Multimap.ContainerType.SET }, { Multimap.ContainerType.SORTED_SET } }); } @Parameterized.Parameter public Multimap.ContainerType containerType; @Override protected IterableAssert assertThat(Iterable actual) { return new IterableAssert(actual) { @Override public IterableAssert isEqualTo(Object obj) { @SuppressWarnings("unchecked") final Iterable expected = (Iterable) obj; final java.util.Map actualMap = countMap(actual); final java.util.Map expectedMap = countMap(expected); assertThat(actualMap.size()).isEqualTo(expectedMap.size()); actualMap.forEach((k, v) -> assertThat(v).isEqualTo(expectedMap.get(k))); return this; } private java.util.Map countMap(Iterable it) { final java.util.HashMap cnt = new java.util.HashMap<>(); it.forEach(i -> cnt.merge(i, 1, (v1, v2) -> v1 + v2)); return cnt; } }; } @Override protected Collector, IntMultimap> collector() { final Collector, ArrayList>, ? extends Multimap> mapCollector = mapCollector(); return new Collector, IntMultimap>() { @Override public Supplier> supplier() { return ArrayList::new; } @Override public BiConsumer, T> accumulator() { return ArrayList::add; } @Override public BinaryOperator> combiner() { return (left, right) -> fromTuples(mapCollector.combiner().apply(toTuples(left), toTuples(right))); } @Override public Function, IntMultimap> finisher() { return AbstractMultimapTest.this::ofAll; } @Override public java.util.Set characteristics() { return mapCollector.characteristics(); } private ArrayList> toTuples(java.util.List list) { final ArrayList> result = new ArrayList<>(); Stream.ofAll(list) .zipWithIndex() .map(tu -> Tuple.of(tu._2, tu._1)) .forEach(result::add); return result; } private ArrayList fromTuples(java.util.List> list) { final ArrayList result = new ArrayList<>(); Stream.ofAll(list) .map(tu -> tu._2) .forEach(result::add); return result; } }; } @Override protected IntMultimap empty() { return IntMultimap.of(emptyMap()); } @Override protected boolean emptyShouldBeSingleton() { return false; } private Multimap emptyInt() { return emptyMap(); } protected Multimap emptyIntInt() { return emptyMap(); } private Multimap emptyIntString() { return emptyMap(); } abstract protected String className(); abstract java.util.Map javaEmptyMap(); protected String containerName() { switch (containerType) { case SEQ: return "List"; case SET: return "HashSet"; case SORTED_SET: return "TreeSet"; default: throw new RuntimeException(); } } protected , T2> Multimap emptyMap() { return emptyMap(Comparators.naturalComparator()); } abstract protected , T2> Multimap emptyMap(Comparator comparator); abstract protected Collector, ArrayList>, ? extends Multimap> mapCollector(); @SuppressWarnings("unchecked") abstract protected , V> Multimap mapOfTuples(Tuple2... entries); @SuppressWarnings("unchecked") abstract protected , V> Multimap mapOfEntries(java.util.Map.Entry... entries); abstract protected , V> Multimap mapOfPairs(K k1, V v1, K k, V v2, K k3, V v3); abstract protected , V> Multimap mapOf(K key, V value); abstract protected , V> Multimap mapOf(java.util.Map map); abstract protected , V> Multimap mapOf(java.util.stream.Stream stream, Function keyMapper, Function valueMapper); abstract protected , V> Multimap mapOf(java.util.stream.Stream stream, Function> f); abstract protected , V> Multimap mapTabulate(int n, Function> f); abstract protected , V> Multimap mapFill(int n, Supplier> s); abstract protected , V> Multimap mapFill(int n, Tuple2 element); @Override protected boolean useIsEqualToInsteadOfIsSameAs() { return true; } @Override protected int getPeekNonNilPerformingAnAction() { return 1; } @Override protected IntMultimap of(T element) { Multimap map = emptyMap(); map = map.put(0, element); return IntMultimap.of(map); } @SuppressWarnings("unchecked") @Override protected IntMultimap of(T... elements) { Multimap map = emptyMap(); for (T element : elements) { map = map.put(map.size(), element); } return IntMultimap.of(map); } @Override protected IntMultimap ofAll(Iterable elements) { Multimap map = emptyMap(); int i = 0; for (T element : elements) { map = map.put(i++, element); } return IntMultimap.of(map); } @Override protected > IntMultimap ofJavaStream(java.util.stream.Stream javaStream) { return ofAll(io.vavr.collection.Iterator.ofAll(javaStream.iterator())); } @Override protected IntMultimap ofAll(boolean... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap ofAll(byte... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap ofAll(char... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap ofAll(double... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap ofAll(float... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap ofAll(int... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap ofAll(long... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap ofAll(short... elements) { return ofAll(io.vavr.collection.Iterator.ofAll(elements)); } @Override protected IntMultimap tabulate(int n, Function f) { Multimap map = emptyMap(); for (int i = 0; i < n; i++) { map = map.put(map.size(), f.apply(i)); } return IntMultimap.of(map); } @Override protected IntMultimap fill(int n, Supplier s) { return tabulate(n, anything -> s.get()); } // -- construction @Test public void shouldBeTheSame() { assertThat(mapOf(1, 2)).isEqualTo(emptyIntInt().put(1, 2)); } private static java.util.Map.Entry entry(String key, Integer value) { return new java.util.AbstractMap.SimpleEntry<>(key, value); } @SuppressWarnings("unchecked") @Test public void shouldConstructFromEntries() { final Multimap map = mapOfEntries(entry("1", 1), entry("2", 2), entry("3", 3)); assertThat(map).isEqualTo(this. emptyMap().put("1", 1).put("2", 2).put("3", 3)); } @Test public void shouldConstructFromPairs() { final Multimap map = mapOfPairs("1", 1, "2", 2, "3", 3); assertThat(map).isEqualTo(this. emptyMap().put("1", 1).put("2", 2).put("3", 3)); } @Test public void shouldConstructFromJavaStream() { final java.util.stream.Stream javaStream = java.util.stream.Stream.of(1, 2, 3); final Multimap map = mapOf(javaStream, String::valueOf, Function.identity()); assertThat(map).isEqualTo(this. emptyMap().put("1", 1).put("2", 2).put("3", 3)); } @Test public void shouldConstructFromJavaStreamEntries() { final java.util.stream.Stream javaStream = java.util.stream.Stream.of(1, 2, 3); final Multimap map = mapOf(javaStream, i -> Tuple.of(String.valueOf(i), i)); assertThat(map).isEqualTo(this. emptyMap().put("1", 1).put("2", 2).put("3", 3)); } @Test public void shouldConstructFromJavaMap() { final java.util.Map source = new java.util.HashMap<>(); source.put("1", 2); source.put("3", 4); final Multimap map = mapOf(source); assertThat(map).isEqualTo(this. emptyMap().put("1", 2).put("3", 4)); } // -- asPartialFunction @Test public void shouldApplyExistingKey() { assertThat(emptyIntInt().put(1, 2).asPartialFunction().apply(1)).isEqualTo(io.vavr.collection.HashSet.of(2)); } @Test(expected = NoSuchElementException.class) public void shouldApplyNonExistingKey() { emptyIntInt().put(1, 2).asPartialFunction().apply(3); } @Test public void shouldImplementPartialFunction() { PartialFunction> f = mapOf(1, "1").asPartialFunction(); assertThat(f.isDefinedAt(1)).isTrue(); assertThat(f.apply(1).contains("1")).isTrue(); assertThat(f.isDefinedAt(2)).isFalse(); } // -- asMap @Test public void shouldConvertToMap() { Multimap mm = emptyIntInt().put(1, 2).put(1, 3); assertThat(mm.asMap().get(1).get()).isEqualTo(HashSet.of(2, 3)); } // -- biMap @Test public void shouldBiMapEmpty() { assertThat(emptyInt().bimap(i -> i + 1, o -> o)).isEqualTo(io.vavr.collection.Vector.empty()); } @Test public void shouldBiMapNonEmpty() { final Seq> expected = Stream.of(Tuple.of(2, "1!"), Tuple.of(3, "2!")); final Seq> actual = emptyInt().put(1, "1").put(2, "2").bimap(i -> i + 1, s -> s + "!").toStream(); assertThat(actual).isEqualTo(expected); } // -- contains @Test public void shouldFindKey() { assertThat(emptyIntInt().put(1, 2).containsKey(1)).isTrue(); assertThat(emptyIntInt().put(1, 2).containsKey(2)).isFalse(); } @Test public void shouldFindValue() { assertThat(emptyIntInt().put(1, 2).containsValue(2)).isTrue(); assertThat(emptyIntInt().put(1, 2).containsValue(1)).isFalse(); } @Test public void shouldRecognizeNotContainedKeyValuePair() { final Multimap testee = mapOf("one", 1); assertThat(testee.contains(Tuple.of("one", 0))).isFalse(); } @Test public void shouldRecognizeContainedKeyValuePair() { final Multimap testee = mapOf("one", 1); assertThat(testee.contains(Tuple.of("one", 1))).isTrue(); } // -- distinct @Override public void shouldComputeDistinctOfNonEmptyTraversable() { final Multimap testee = this. emptyMap().put(1, 1).put(2, 2).put(3, 3); assertThat(testee.distinct()).isEqualTo(testee); } // -- equality @Test public void shouldObeyEqualityConstraints() { // sequential collections assertThat(emptyMap().equals(HashMultimap.withSeq().empty())).isTrue(); assertThat(mapOf(1, "a").equals(HashMultimap.withSeq().of(1, "a"))).isTrue(); assertThat(mapOfPairs(1, "a", 2, "b", 3, "c").equals(HashMultimap.withSeq().of(1, "a", 2, "b",3, "c"))).isTrue(); assertThat(mapOfPairs(1, "a", 2, "b", 3, "c").equals(HashMultimap.withSeq().of(3, "c", 2, "b",1, "a"))).isTrue(); // other classes assertThat(empty().equals(io.vavr.collection.List.empty())).isFalse(); assertThat(empty().equals(HashMap.empty())).isFalse(); assertThat(empty().equals(io.vavr.collection.HashSet.empty())).isFalse(); assertThat(empty().equals(LinkedHashMap.empty())).isFalse(); assertThat(empty().equals(io.vavr.collection.LinkedHashSet.empty())).isFalse(); assertThat(empty().equals(TreeMap.empty())).isFalse(); assertThat(empty().equals(TreeSet.empty())).isFalse(); } @Test public void shouldIgnoreOrderOfEntriesWhenComparingForEquality() { final Multimap map1 = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c'); final Multimap map2 = emptyInt().put(3, 'c').put(2, 'b').put(1, 'a').remove(2).put(2, 'b'); assertThat(map1).isEqualTo(map2); } @Test public void shouldHoldEqualsElements() { Multimap multimap = emptyMap(); multimap = multimap.put(1, "a").put(1, "b").put(1, "b"); if (containerType == Multimap.ContainerType.SEQ) { assertThat(multimap.toString()).isEqualTo(className() + "((1, a), (1, b), (1, b))"); } else { assertThat(multimap.toString()).isEqualTo(className() + "((1, a), (1, b))"); } } // -- filter @Test public void shouldBiFilterWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Multimap dst = src.filter((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(2, "2").put(4, "4").put(6, "6").put(6, "10").put(8, "8").put(8, "12")); } @Test public void shouldKeyFilterWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Multimap dst = src.filterKeys(k -> k % 2 == 0); assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(0, "a").put(2, "2").put(2, "c").put(4, "4").put(4, "e").put(6, "6").put(6, "10").put(8, "8").put(8, "12")); } @Test public void shouldValueFilterWork() throws Exception { final Multimap src = mapTabulate(10, n -> Tuple.of(n % 5, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Multimap dst = src.filterValues(v -> isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(0, "5").put(1, "1").put(1, "6").put(2, "2").put(2, "7").put(3, "3").put(3, "8").put(4, "4").put(4, "9")); } // -- reject @SuppressWarnings("deprecation") @Test public void shouldBiRejectWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Multimap dst = src.reject((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "a").put(1, "1").put(1, "b").put(2, "c").put(3, "3").put(3, "d").put(4, "e").put(5, "5").put(5, "f").put(7, "7").put(7, "11").put(9, "9").put(9, "13")); } @SuppressWarnings("deprecation") @Test public void shouldKeyRejectWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Multimap dst = src.rejectKeys(k -> k % 2 == 0); assertThat(dst).isEqualTo(emptyIntString().put(1, "1").put(1, "b").put(3, "3").put(3, "d").put(5, "5").put(5, "f").put(7, "7").put(7, "11").put(9, "9").put(9, "13")); } @SuppressWarnings("deprecation") @Test public void shouldValueRejectWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Multimap dst = src.rejectValues(v -> isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "a").put(1, "b").put(2, "c").put(3, "d").put(4, "e").put(5, "f")); } // -- flatMap @SuppressWarnings("unchecked") @Test public void shouldFlatMapUsingBiFunction() { final Multimap testee = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)); final Multimap actual = testee .flatMap((k, v) -> io.vavr.collection.List.of(Tuple.of(String.valueOf(k), String.valueOf(v)), Tuple.of(String.valueOf(k * 10), String.valueOf(v * 10)))); final Multimap expected = mapOfTuples(Tuple.of("1", "11"), Tuple.of("10", "110"), Tuple.of("2", "22"), Tuple.of("20", "220"), Tuple.of("3", "33"), Tuple.of("30", "330")); assertThat(actual).isEqualTo(expected); } // -- foldRight @Override public void shouldFoldRightNonNil() { final String actual = of('a', 'b', 'c').foldRight("", (x, xs) -> x + xs); final io.vavr.collection.List expected = io.vavr.collection.List.of('a', 'b', 'c').permutations().map(io.vavr.collection.List::mkString); assertThat(actual).isIn(expected); } // -- forEach @Test public void forEachByKeyValue() { final Multimap map = mapOf(1, 2).put(3, 4); final int[] result = { 0 }; map.forEach((k, v) -> result[0] += k + v); assertThat(result[0]).isEqualTo(10); } @Test public void forEachByTuple() { final Multimap map = mapOf(1, 2).put(3, 4); final int[] result = { 0 }; map.forEach(t -> result[0] += t._1 + t._2); assertThat(result[0]).isEqualTo(10); } // -- getOrElse @Test public void shouldReturnDefaultValue() { final Multimap map = mapOf("1", "a").put("2", "b"); assertThat(map.getOrElse("3", io.vavr.collection.List.of("3"))).isEqualTo(io.vavr.collection.List.of("3")); } // -- groupBy @Override @Test public void shouldNonNilGroupByIdentity() { final Map actual = of('a', 'b', 'c').groupBy(Function.identity()); final Map expected = LinkedHashMap.empty().put('a', mapOf(0, 'a')).put('b', mapOf(1,'b')) .put('c', mapOf(2,'c')); assertThat(actual).isEqualTo(expected); } // -- iterator @Test public void shouldReturnListWithMappedValues() { assertThat(emptyIntInt().put(1, 1).put(2, 2).iterator((a, b) -> a + b)).isEqualTo(io.vavr.collection.List.of(2, 4)); } // -- keySet @SuppressWarnings("unchecked") @Test public void shouldReturnsKeySet() { final Set actual = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)).keySet(); assertThat(actual).isEqualTo(io.vavr.collection.HashSet.of(1, 2, 3)); } // -- map @Test public void shouldMapEmpty() { assertThat(emptyInt().map(Tuple2::_1)).isEqualTo(io.vavr.collection.Vector.empty()); } @Test public void shouldMapNonEmpty() { final Seq expected = io.vavr.collection.Vector.of(1, 2); final Seq actual = emptyInt().put(1, "1").put(2, "2").map(Tuple2::_1); assertThat(actual).isEqualTo(expected); } @Test public void shouldMapComparableValues() { final Multimap map = this.emptyMap() .put(1, "1") .put(1, "2") .put(2, "3"); assertThat(map.map(v -> v)).isEqualTo(io.vavr.collection.List.of( Tuple.of(1, "1"), Tuple.of(1, "2"), Tuple.of(2, "3"))); } @Test public void shouldMapIncomparableValues() { final Multimap map = this.emptyMap(Comparator.comparing(Incomparable::getS)) .put(1, new Incomparable("1")) .put(1, new Incomparable("2")) .put(2, new Incomparable("3")); assertThat(map.map(v -> v)).isEqualTo(io.vavr.collection.List.of( Tuple.of(1, new Incomparable("1")), Tuple.of(1, new Incomparable("2")), Tuple.of(2, new Incomparable("3")))); } private final static class Incomparable { private String s; Incomparable(String s) { this.s = s; } public String getS() { return s; } @Override public boolean equals(Object o) { return o == this || (o instanceof Incomparable && Objects.equals(s, ((Incomparable) o).s)); } @Override public int hashCode() { return Objects.hashCode(s); } } // -- mapFill @SuppressWarnings("unchecked") @Test public void shouldFillTheSeqCallingTheSupplierInTheRightOrder() { final LinkedList ints = new LinkedList<>(asList(0, 0, 1, 1, 2, 2)); final Supplier> s = () -> new Tuple2<>(ints.remove().longValue(), ints.remove().floatValue()); final Multimap actual = mapFill(3, s); assertThat(actual).isEqualTo(mapOfTuples(new Tuple2<>(0L, 0f), new Tuple2<>(1L, 1f), new Tuple2<>(2L, 2f))); } @Test public void shouldFillTheSeqWith0Elements() { assertThat(mapFill(0, () -> new Tuple2<>(1, 1))).isEqualTo(empty()); } @Test public void shouldFillTheSeqWith0ElementsWhenNIsNegative() { assertThat(mapFill(-1, () -> new Tuple2<>(1, 1))).isEqualTo(empty()); } // -- fill(int, Supplier) @Test public void shouldReturnManyMapAfterFillWithConstantSupplier() { AtomicInteger value = new AtomicInteger(83); assertThat(mapFill(17, () -> Tuple.of(7, value.getAndIncrement()))) .hasSize(17); } // -- fill(int, T) @Test public void shouldReturnEmptyAfterFillWithZeroCount() { assertThat(mapFill(0, Tuple.of(7, 83))).isEqualTo(empty()); } @Test public void shouldReturnEmptyAfterFillWithNegativeCount() { assertThat(mapFill(-1, Tuple.of(7, 83))).isEqualTo(empty()); } @Test public void shouldReturnManyMapAfterFillWithConstant() { assertThat(mapFill(17, Tuple.of(7, 83))) .hasSize(containerType == Multimap.ContainerType.SEQ ? 17 : 1); } // -- mapTabulate @SuppressWarnings("unchecked") @Test public void shouldTabulateTheSeq() { final Function> f = i -> new Tuple2<>(i.longValue(), i.floatValue()); final Multimap map = mapTabulate(3, f); assertThat(map).isEqualTo(mapOfTuples(new Tuple2<>(0L, 0f), new Tuple2<>(1L, 1f), new Tuple2<>(2L, 2f))); } @SuppressWarnings("unchecked") @Test public void shouldTabulateTheSeqCallingTheFunctionInTheRightOrder() { final LinkedList ints = new LinkedList<>(asList(0, 0, 1, 1, 2, 2)); final Function> f = i -> new Tuple2<>(ints.remove().longValue(), ints.remove().floatValue()); final Multimap map = mapTabulate(3, f); assertThat(map).isEqualTo(mapOfTuples(new Tuple2<>(0L, 0f), new Tuple2<>(1L, 1f), new Tuple2<>(2L, 2f))); } @Test public void shouldTabulateTheSeqWith0Elements() { assertThat(mapTabulate(0, i -> new Tuple2<>(i, i))).isEqualTo(empty()); } @Test public void shouldTabulateTheSeqWith0ElementsWhenNIsNegative() { assertThat(mapTabulate(-1, i -> new Tuple2<>(i, i))).isEqualTo(empty()); } // -- mapValues @Test public void shouldReturnModifiedValuesMap() { assertThat(emptyIntString().put(1, "1").put(2, "2").mapValues(Integer::parseInt)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2)); } // -- merge @Test public void shouldMerge() { final Multimap m1 = emptyIntInt().put(1, 1).put(2, 2); final Multimap m2 = emptyIntInt().put(1, 1).put(4, 4); final Multimap m3 = emptyIntInt().put(3, 3).put(4, 4); assertThat(emptyIntInt().merge(m2)).isEqualTo(m2); assertThat(m2.merge(emptyIntInt())).isEqualTo(m2); if (containerType == Multimap.ContainerType.SEQ) { assertThat(m1.merge(m2)).isEqualTo(emptyIntInt().put(1, 1).put(1, 1).put(2, 2).put(4, 4)); assertThat(m1.merge(m3)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4)); } else { assertThat(m1.merge(m2)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(4, 4)); assertThat(m1.merge(m3)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4)); } } @SuppressWarnings("unchecked") @Test public void shouldMergeCollisions() { final Multimap m1 = emptyIntInt().put(1, 1).put(2, 2); final Multimap m2 = emptyIntInt().put(1, 2).put(4, 4); final Multimap m3 = emptyIntInt().put(3, 3).put(4, 4); assertThat(emptyIntInt().merge(m2, (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(m2); assertThat(m2.merge(emptyIntInt(), (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(m2); assertThat(m1.merge(m2, (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(emptyIntInt().put(1, 1).put(1, 2).put(2, 2).put(4, 4)); assertThat(m1.merge(m3, (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4)); } // -- orElse // DEV-Note: IntMultimap converts `other` to multimap @Override @Test public void shouldCaclEmptyOrElseSameOther() { Iterable other = of(42); assertThat(empty().orElse(other)).isEqualTo(other); } @Test public void shouldCaclEmptyOrElseSameSupplier() { Iterable other = of(42); Supplier> supplier = () -> other; assertThat(empty().orElse(supplier)).isEqualTo(other); } // -- partition @Override @Test @SuppressWarnings("unchecked") public void shouldPartitionIntsInOddAndEvenHavingOddAndEvenNumbers() { assertThat(of(1, 2, 3, 4).partition(i -> i % 2 != 0)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0, 1), Tuple.of(2, 3)), mapOfTuples(Tuple.of(1, 2), Tuple.of(3, 4)))); } // -- put @Test public void shouldPutTuple() { assertThat(emptyIntInt().put(Tuple.of(1, 2))).isEqualTo(emptyIntInt().put(1, 2)); } // -- remove @Test public void shouldRemoveKey() { final Multimap src = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c'); assertThat(src.remove(2)).isEqualTo(emptyInt().put(1, 'a').put(3, 'c')); assertThat(src.remove(33)).isSameAs(src); } // -- replace @Test public void shouldReplaceEntity() { final Multimap actual = emptyInt().put(1, "a").put(1, "b").replace(Tuple.of(1, "a"), Tuple.of(1, "c")); final Multimap expected = emptyInt().put(1, "c").put(1, "b"); assertThat(actual).isEqualTo(expected); } // -- removeAll @Test public void shouldRemoveAllKeys() { final Multimap src = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c'); assertThat(src.removeAll(io.vavr.collection.List.of(1, 3))).isEqualTo(emptyInt().put(2, 'b')); assertThat(src.removeAll(io.vavr.collection.List.of(33))).isSameAs(src); assertThat(src.removeAll(io.vavr.collection.List.empty())).isSameAs(src); } // -- remove by filter @SuppressWarnings("deprecation") @Test public void shouldBiRemoveWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Multimap dst = src.removeAll((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "a").put(1, "1").put(1, "b").put(2, "c").put(3, "3").put(3, "d").put(4, "e").put(5, "5").put(5, "f").put(7, "7").put(7, "11").put(9, "9").put(9, "13")); } @SuppressWarnings("deprecation") @Test public void shouldKeyRemoveWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Multimap dst = src.removeKeys(k -> k % 2 == 0); assertThat(dst).isEqualTo(emptyIntString().put(1, "1").put(1, "b").put(3, "3").put(3, "d").put(5, "5").put(5, "f").put(7, "7").put(7, "11").put(9, "9").put(9, "13")); } @SuppressWarnings("deprecation") @Test public void shouldValueRemoveWork() throws Exception { final Multimap src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n))); final Pattern isDigits = Pattern.compile("^\\d+$"); final Multimap dst = src.removeValues(v -> isDigits.matcher(v).matches()); assertThat(dst).isEqualTo(emptyIntString().put(0, "a").put(1, "b").put(2, "c").put(3, "d").put(4, "e").put(5, "f")); } // -- replaceValue @Test public void shouldReturnSameInstanceIfReplacingCurrentValueWithNonExistingKey() { final Multimap map = mapOf(1, "a").put(2, "b"); final Multimap actual = map.replaceValue(3, "?"); assertThat(actual).isSameAs(map); } @Test public void shouldReplaceCurrentValueForExistingKey() { final Multimap map = mapOf(1, "a").put(2, "b"); final Multimap actual = map.replaceValue(2, "c"); final Multimap expected = mapOf(1, "a").put(2, "c"); assertThat(actual).isEqualTo(expected); } @Test public void shouldReplaceValuesWithNewValueForExistingKey() { final Multimap map = mapOf(1, "a").put(2, "b").put(2, "c"); final Multimap actual = map.replaceValue(2, "c"); final Multimap expected = mapOf(1, "a").put(2, "c"); assertThat(actual).isEqualTo(expected); } // -- replace @Test public void shouldReplaceCurrentValueForExistingKeyAndEqualOldValue() { final Multimap map = mapOf(1, "a").put(2, "b"); final Multimap actual = map.replace(2, "b", "c"); final Multimap expected = mapOf(1, "a").put(2, "c"); assertThat(actual).isEqualTo(expected); } @Test public void shouldReplaceCurrentValueForKeyWithMultipleValuesAndEqualOldValue() { final Multimap map = mapOf(1, "a").put(2, "b").put(2, "d"); final Multimap actual = map.replace(2, "b", "c"); final Multimap expected = mapOf(1, "a").put(2, "c").put(2, "d"); assertThat(actual).isEqualTo(expected); } @Test public void shouldReturnSameInstanceForExistingKeyAndNonEqualOldValue() { final Multimap map = mapOf(1, "a").put(2, "b"); final Multimap actual = map.replace(2, "d", "c"); assertThat(actual).isSameAs(map); } @Test public void shouldReturnSameInstanceIfReplacingCurrentValueWithOldValueWithNonExistingKey() { final Multimap map = mapOf(1, "a").put(2, "b"); final Multimap actual = map.replace(3, "?", "!"); assertThat(actual).isSameAs(map); } // - replaceAll @Test public void shouldReplaceAllValuesWithFunctionResult() { final Multimap map = mapOf(1, "a").put(2, "b").put(2, "c"); final Multimap actual = map.replaceAll((integer, s) -> s + integer); final Multimap expected = mapOf(1, "a1").put(2, "b2").put(2, "c2"); assertThat(actual).isEqualTo(expected); } // -- span @Override @Test @SuppressWarnings("unchecked") public void shouldSpanNonNil() { assertThat(of(0, 1, 2, 3).span(i -> i < 2)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0, 0), Tuple.of(1, 1)), mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 3)))); } @Override @Test @SuppressWarnings("unchecked") public void shouldSpanAndNotTruncate() { assertThat(of(1, 1, 2, 2, 3, 3).span(x -> x % 2 == 1)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0,1), Tuple.of(1, 1)), mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 2), Tuple.of(4, 3), Tuple.of(5, 3)))); assertThat(of(1, 1, 2, 2, 4, 4).span(x -> x == 1)) .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0,1), Tuple.of(1, 1)), mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 2), Tuple.of(4, 4), Tuple.of(5, 4)))); } // -- spliterator @Test public void shouldHaveSizedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue(); } @Test public void shouldHaveDistinctSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.DISTINCT)).isTrue(); } @Test public void shouldReturnExactSizeIfKnownOfSpliterator() { assertThat(of(1, 2, 3).spliterator().getExactSizeIfKnown()).isEqualTo(3); } // -- tailOption @Override public void shouldReturnSomeTailWhenCallingTailOptionOnNonNil() { assertThat(of(1, 2, 3).tailOption().get()).isEqualTo(Option.some(of(2, 3)).get()); } // -- toJavaMap @Test public void shouldConvertToJavaMap() { final Multimap vavr = mapOfPairs("1", 1, "2", 2, "3", 3); final java.util.Map> java = javaEmptyMap(); java.put("1", javaListOf(1)); java.put("2", javaListOf(2)); java.put("3", javaListOf(3)); assertThat(vavr.toJavaMap()).isEqualTo(java); } private java.util.Collection javaListOf(Integer i) { final java.util.Collection list; switch (containerType) { case SEQ: list = new ArrayList<>(); break; case SET: list = new java.util.HashSet<>(); break; case SORTED_SET: list = new java.util.TreeSet<>(); break; default: throw new RuntimeException(); } list.add(i); return list; } // -- toSet @Test public void shouldReturnEmptySetWhenAskedForTuple2SetOfAnEmptyMap() { assertThat(emptyMap().toSet()).isEqualTo(io.vavr.collection.HashSet.empty()); } @Test public void shouldReturnTuple2SetOfANonEmptyMap() { assertThat(emptyInt().put(1, "1").put(2, "2").toSet()).isEqualTo(io.vavr.collection.HashSet.of(Tuple.of(1, "1"), Tuple.of(2, "2"))); } // -- toString @Test public void shouldMakeString() { assertThat(emptyMap().toString()).isEqualTo(className() + "()"); assertThat(emptyIntInt().put(1, 2).toString()).isEqualTo(className() + "(" + Tuple.of(1, 2) + ")"); } // -- transform @Test public void shouldTransform() { final Multimap actual = emptyIntInt().put(1, 11).transform(map -> map.put(2, 22)); assertThat(actual).isEqualTo(emptyIntInt().put(1, 11).put(2, 22)); } // -- unzip @Test public void shouldUnzipNil() { assertThat(emptyMap().unzip(x -> Tuple.of(x, x))).isEqualTo(Tuple.of(Stream.empty(), Stream.empty())); assertThat(emptyMap().unzip((k, v) -> Tuple.of(Tuple.of(k, v), Tuple.of(k, v)))) .isEqualTo(Tuple.of(Stream.empty(), Stream.empty())); } @Test public void shouldUnzipNonNil() { final Multimap map = emptyIntInt().put(0, 0).put(1, 1); final Tuple actual = map.unzip(entry -> Tuple.of(entry._1, entry._2 + 1)); final Tuple expected = Tuple.of(Stream.of(0, 1), Stream.of(1, 2)); assertThat(actual).isEqualTo(expected); } @Test public void shouldUnzip3Nil() { assertThat(emptyMap().unzip3(x -> Tuple.of(x, x, x))).isEqualTo(Tuple.of(Stream.empty(), Stream.empty(), Stream.empty())); assertThat(emptyMap().unzip3((k, v) -> Tuple.of(Tuple.of(k, v), Tuple.of(k, v), Tuple.of(k, v)))) .isEqualTo(Tuple.of(Stream.empty(), Stream.empty(), Stream.empty())); } @Test public void shouldUnzip3NonNil() { final Multimap map = emptyIntInt().put(0, 0).put(1, 1); final Tuple actual = map.unzip3(entry -> Tuple.of(entry._1, entry._2 + 1, entry._2 + 5)); final Tuple expected = Tuple.of(Stream.of(0, 1), Stream.of(1, 2), Stream.of(5, 6)); assertThat(actual).isEqualTo(expected); } // -- zip @Test public void shouldZipNils() { final Seq, Object>> actual = emptyIntInt().zip(io.vavr.collection.List.empty()); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipEmptyAndNonNil() { final Seq, Integer>> actual = emptyIntInt().zip(io.vavr.collection.List.of(1)); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipNonEmptyAndNil() { final Seq, Object>> actual = emptyIntInt().put(0, 1).zip(io.vavr.collection.List.empty()); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipNonNilsIfThisIsSmaller() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .zip(io.vavr.collection.List.of(5, 6, 7)); assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6))); } @Test public void shouldZipNonNilsIfThatIsSmaller() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .put(2, 2) .zip(io.vavr.collection.List.of(5, 6)); assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6))); } @Test public void shouldZipNonNilsOfSameSize() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .put(2, 2) .zip(io.vavr.collection.List.of(5, 6, 7)); assertThat(actual).isEqualTo( Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6), Tuple.of(Tuple.of(2, 2), 7))); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipWithThatIsNull() { emptyMap().zip(null); } // -- zipWithIndex @Test public void shouldZipNilWithIndex() { assertThat(emptyMap().zipWithIndex()).isEqualTo(Stream.empty()); } @Test public void shouldZipNonNilWithIndex() { final Seq, Integer>> actual = emptyIntInt() .put(0, 0) .put(1, 1) .put(2, 2) .zipWithIndex(); assertThat(actual).isEqualTo( Stream.of(Tuple.of(Tuple.of(0, 0), 0), Tuple.of(Tuple.of(1, 1), 1), Tuple.of(Tuple.of(2, 2), 2))); } // -- zipAll @Test public void shouldZipAllNils() { final Seq, Object>> actual = emptyIntInt().zipAll(empty(), null, null); assertThat(actual).isEqualTo(Stream.empty()); } @Test public void shouldZipAllEmptyAndNonNil() { final Seq, Object>> actual = emptyIntInt().zipAll(io.vavr.collection.List.of(1), null, null); assertThat(actual).isEqualTo(Stream.of(Tuple.of(null, 1))); } @Test public void shouldZipAllNonEmptyAndNil() { final Seq, Object>> actual = emptyIntInt().put(0, 1).zipAll(empty(), null, null); assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 1), null))); } @Test public void shouldZipAllNonNilsIfThisIsSmaller() { final Seq, String>> actual = this. emptyMap() .put(1, 1) .put(2, 2) .zipAll(of("a", "b", "c"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(9, 10), "c")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThisIsMoreSmaller() { final Seq, String>> actual = this. emptyMap() .put(1, 1) .put(2, 2) .zipAll(of("a", "b", "c", "d"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(9, 10), "c"), Tuple.of(Tuple.of(9, 10), "d")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThatIsSmaller() { final Seq, String>> actual = this. emptyMap() .put(1, 1) .put(2, 2) .put(3, 3) .zipAll(this.of("a", "b"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "z")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThatIsMoreSmaller() { final Seq, String>> actual = this. emptyMap() .put(1, 1) .put(2, 2) .put(3, 3) .put(4, 4) .zipAll(of("a", "b"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "z"), Tuple.of(Tuple.of(4, 4), "z")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsOfSameSize() { final Seq, String>> actual = this. emptyMap() .put(1, 1) .put(2, 2) .put(3, 3) .zipAll(of("a", "b", "c"), Tuple.of(9, 10), "z"); final Seq, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"), Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "c")); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipAllWithThatIsNull() { emptyMap().zipAll(null, null, null); } // -- disabled super tests @Override public void shouldPreserveSingletonInstanceOnDeserialization() { // The empty Multimap encapsulates a container type and map type and therefore cannot be a singleton } @Override @Test public void shouldCreateSeqOfSeqUsingCons() { // this Traversable test is not suited for Multimaps: // io.vavr.collection.List$Nil cannot be cast to java.lang.Comparable } @Override @Test public void shouldConvertToJavaArrayWithTypeHintPrimitiveVoid() { // this Value test is not suited for Multimaps: // java.lang.NullPointerException at io.vavr.collection.Comparators.lambda$naturalComparator } @Override @Test public void shouldCollectUsingMultimap() { // this Traversable test is not suited for Multimaps: // java.lang.ClassCastException: io.vavr.collection.List$Cons cannot be cast to java.lang.Comparable } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractSeqTest.java000066400000000000000000002234541342074374400256740ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.control.Option; import io.vavr.Tuple2; import org.junit.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Spliterator; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collector; import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * Tests all methods defined in {@link Seq}. */ public abstract class AbstractSeqTest extends AbstractTraversableRangeTest { // -- construction @Override abstract protected Collector, ? extends Seq> collector(); @Override abstract protected Seq empty(); @Override abstract protected Seq of(T element); @SuppressWarnings("unchecked") @Override abstract protected Seq of(T... elements); @Override abstract protected Seq ofAll(Iterable elements); @Override abstract protected Seq ofAll(boolean... elements); @Override abstract protected Seq ofAll(byte... elements); @Override abstract protected Seq ofAll(char... elements); @Override abstract protected Seq ofAll(double... elements); @Override abstract protected Seq ofAll(float... elements); @Override abstract protected Seq ofAll(int... elements); @Override abstract protected Seq ofAll(long... elements); @Override abstract protected Seq ofAll(short... elements); @Override abstract protected Seq range(char from, char toExclusive); @Override abstract protected Seq rangeBy(char from, char toExclusive, int step); @Override abstract protected Seq rangeBy(double from, double toExclusive, double step); @Override abstract protected Seq range(int from, int toExclusive); @Override abstract protected Seq rangeBy(int from, int toExclusive, int step); @Override abstract protected Seq range(long from, long toExclusive); @Override abstract protected Seq rangeBy(long from, long toExclusive, long step); @Override abstract protected Seq rangeClosed(char from, char toInclusive); @Override abstract protected Seq rangeClosedBy(char from, char toInclusive, int step); @Override abstract protected Seq rangeClosedBy(double from, double toInclusive, double step); @Override abstract protected Seq rangeClosed(int from, int toInclusive); @Override abstract protected Seq rangeClosedBy(int from, int toInclusive, int step); @Override abstract protected Seq rangeClosed(long from, long toInclusive); @Override abstract protected Seq rangeClosedBy(long from, long toInclusive, long step); abstract protected Seq> transpose(Seq> rows); abstract protected Traversable fill(int n, T element); // -- static narrow @Test public void shouldNarrowSeq() { final Seq doubles = of(1.0d); final Seq numbers = Seq.narrow(doubles); final int actual = numbers.append(new BigDecimal("2.0")).sum().intValue(); assertThat(actual).isEqualTo(3); } // -- fill(int, Supplier) @Test public void shouldReturnManyAfterFillWithConstantSupplier() { assertThat(fill(17, () -> 7)) .hasSize(17) .containsOnly(7); } // -- fill(int, T) @Test public void shouldReturnEmptyAfterFillWithZeroCount() { assertThat(fill(0, 7)).isEqualTo(empty()); } @Test public void shouldReturnEmptyAfterFillWithNegativeCount() { assertThat(fill(-1, 7)).isEqualTo(empty()); } @Test public void shouldReturnManyAfterFillWithConstant() { assertThat(fill(17, 7)) .hasSize(17) .containsOnly(7); } // -- append @Test public void shouldAppendElementToNil() { final Seq actual = this. empty().append(1); final Seq expected = of(1); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendNullElementToNil() { final Seq actual = this. empty().append(null); final Seq expected = this.of((Integer) null); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendElementToNonNil() { final Seq actual = of(1, 2).append(3); final Seq expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldMixAppendAndPrepend() { assertThat(of(1).append(2).prepend(0).prepend(-1).append(3).append(4)).isEqualTo(of(-1, 0, 1, 2, 3, 4)); } // -- appendAll @Test(expected = NullPointerException.class) public void shouldThrowOnAppendAllOfNull() { empty().appendAll(null); } @Test public void shouldAppendAllNilToNil() { final Seq actual = empty().appendAll(empty()); final Seq expected = empty(); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendAllNonNilToNil() { final Seq actual = this. empty().appendAll(of(1, 2, 3)); final Seq expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendAllNilToNonNil() { final Seq actual = of(1, 2, 3).appendAll(empty()); final Seq expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendAllNonNilToNonNil() { final Seq actual = of(1, 2, 3).appendAll(of(4, 5, 6)); final Seq expected = of(1, 2, 3, 4, 5, 6); assertThat(actual).isEqualTo(expected); } @Test public void shouldReturnSameSeqWhenEmptyAppendAllEmpty() { final Seq empty = empty(); assertThat(empty.appendAll(empty())).isSameAs(empty); } @Test public void shouldReturnSameSeqWhenEmptyAppendAllNonEmpty() { final Seq seq = of(1, 2, 3); assertThat(empty().appendAll(seq)).isSameAs(seq); } @Test public void shouldReturnSameSeqWhenNonEmptyAppendAllEmpty() { final Seq seq = of(1, 2, 3); if (seq.hasDefiniteSize()) { assertThat(seq.appendAll(empty())).isSameAs(seq); } else { assertThat(seq.appendAll(empty())).isEqualTo(seq); } } // -- asPartialFunction @Test public void shouldUseSeqAsPartialFunction() { assertThat(of(1, 2, 3).asPartialFunction().apply(1)).isEqualTo(2); } @Test public void shouldNotBeDefinedAtNegativeIndexWhenEmpty() { assertThat(empty().asPartialFunction().isDefinedAt(-1)).isFalse(); } @Test public void shouldNotBeDefinedAtNegativeIndexWhenNonEmpty() { assertThat(of(1).asPartialFunction().isDefinedAt(-1)).isFalse(); } @Test public void shouldNotBeDefinedAtIndex0WhenEmpty() { assertThat(empty().asPartialFunction().isDefinedAt(0)).isFalse(); } @Test public void shouldBeDefinedAtIndex0WhenNonEmpty() { assertThat(of(1).asPartialFunction().isDefinedAt(0)).isTrue(); } @Test public void shouldBeDefinedAtLastIndexWhenNonEmpty() { assertThat(of(1, 2, 3).asPartialFunction().isDefinedAt(2)).isTrue(); } @Test public void shouldNotBeDefinedAtIndexOutOfBoundsWhenNonEmpty() { assertThat(of(1, 2, 3).asPartialFunction().isDefinedAt(3)).isFalse(); } // -- combinations @Test public void shouldComputeCombinationsOfEmptyList() { assertThat(empty().combinations()).isEqualTo(of(empty())); } @SuppressWarnings("unchecked") @Test public void shouldComputeCombinationsOfNonEmptyList() { assertThat(of(1, 2, 3).combinations()) .isEqualTo(of(empty(), of(1), of(2), of(3), of(1, 2), of(1, 3), of(2, 3), of(1, 2, 3))); } // -- asJavaMutable* @Test public void shouldConvertAsJava() { final java.util.List list = of(1, 2, 3).asJavaMutable(); list.add(4); assertThat(list).isEqualTo(Arrays.asList(1, 2, 3, 4)); } @Test public void shouldConvertAsJavaWithConsumer() { final Seq seq = of(1, 2, 3).asJavaMutable(list -> { assertThat(list).isEqualTo(Arrays.asList(1, 2, 3)); list.add(4); }); assertThat(seq).isEqualTo(of(1, 2, 3, 4)); } @Test public void shouldConvertAsJavaAndRethrowException() { assertThatThrownBy(() -> of(1, 2, 3).asJavaMutable(list -> { throw new RuntimeException("test");})) .isInstanceOf(RuntimeException.class) .hasMessage("test"); } @Test public void shouldConvertAsJavaImmutable() { final java.util.List list = of(1, 2, 3).asJava(); assertThat(list).isEqualTo(Arrays.asList(1, 2, 3)); assertThatThrownBy(() -> list.add(4)).isInstanceOf(UnsupportedOperationException.class); } @Test public void shouldConvertAsJavaImmutableWithConsumer() { final Seq seq = of(1, 2, 3).asJava(list -> { assertThat(list).isEqualTo(Arrays.asList(1, 2, 3)); assertThatThrownBy(() -> list.add(4)).isInstanceOf(UnsupportedOperationException.class); }); assertThat(seq).isEqualTo(of(1, 2, 3)); } @Test public void shouldConvertAsJavaImmutableAndRethrowException() { assertThatThrownBy(() -> of(1, 2, 3).asJava(list -> { throw new RuntimeException("test");})) .isInstanceOf(RuntimeException.class) .hasMessage("test"); } // -- combinations(k) @Test public void shouldComputeKCombinationsOfEmptyList() { assertThat(empty().combinations(1)).isEmpty(); } @SuppressWarnings("unchecked") @Test public void shouldComputeKCombinationsOfNonEmptyList() { assertThat(of(1, 2, 3).combinations(2)).isEqualTo(of(of(1, 2), of(1, 3), of(2, 3))); } @Test public void shouldComputeKCombinationsOfNegativeK() { assertThat(of(1).combinations(-1)).isEqualTo(of(empty())); } // -- containsSlice @Test public void shouldRecognizeNilNotContainsSlice() { final boolean actual = empty().containsSlice(of(1, 2, 3)); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilDoesContainSlice() { final boolean actual = of(1, 2, 3, 4, 5).containsSlice(of(2, 3)); assertThat(actual).isTrue(); } @Test public void shouldRecognizeNonNilDoesNotContainSlice() { final boolean actual = of(1, 2, 3, 4, 5).containsSlice(of(2, 1, 4)); assertThat(actual).isFalse(); } // -- crossProduct() @Test public void shouldCalculateCrossProductOfNil() { final Iterator> actual = empty().crossProduct(); assertThat(actual).isEmpty(); } @SuppressWarnings("unchecked") @Test public void shouldCalculateCrossProductOfNonNil() { final List> actual = of(1, 2, 3).crossProduct().toList(); final List> expected = List.of(Tuple.of(1, 1), Tuple.of(1, 2), Tuple.of(1, 3), Tuple.of(2, 1), Tuple.of(2, 2), Tuple.of(2, 3), Tuple.of(3, 1), Tuple.of(3, 2), Tuple.of(3, 3)); assertThat(actual).isEqualTo(expected); } // -- crossProduct(int) @Test public void shouldCalculateCrossProductPower() { assertThat(of(1, 2).crossProduct(0).toList()).isEqualTo(List.of(empty())); assertThat(of(1, 2).crossProduct(1).toList()).isEqualTo(List.of(of(1), of(2))); assertThat(of(1, 2).crossProduct(2).toList()).isEqualTo(List.of(of(1, 1), of(1, 2), of(2, 1), of(2, 2))); } @Test public void shouldCrossProductPowerBeLazy() { assertThat(range(0, 10).crossProduct(100).take(1).get()).isEqualTo(tabulate(100, i -> 0)); } @Test public void shouldCrossProductOfNegativePowerBeEmpty() { assertThat(of(1, 2).crossProduct(-1).toList()).isEqualTo(List.empty()); } // -- crossProduct(Iterable) @Test public void shouldCalculateCrossProductOfNilAndNil() { final Iterator> actual = empty().crossProduct(empty()); assertThat(actual).isEmpty(); } @Test public void shouldCalculateCrossProductOfNilAndNonNil() { final Iterator> actual = empty().crossProduct(of(1, 2, 3)); assertThat(actual).isEmpty(); } @Test public void shouldCalculateCrossProductOfNonNilAndNil() { final Iterator> actual = of(1, 2, 3).crossProduct(empty()); assertThat(actual).isEmpty(); } @SuppressWarnings("unchecked") @Test public void shouldCalculateCrossProductOfNonNilAndNonNil() { final List> actual = of(1, 2, 3).crossProduct(of('a', 'b')).toList(); final List> expected = of(Tuple.of(1, 'a'), Tuple.of(1, 'b'), Tuple.of(2, 'a'), Tuple.of(2, 'b'), Tuple.of(3, 'a'), Tuple.of(3, 'b')).toList(); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowWhenCalculatingCrossProductAndThatIsNull() { empty().crossProduct(null); } // -- dropRightUntil @Test public void shouldDropRightUntilNoneOnNil() { assertThat(empty().dropRightUntil(ignored -> true)).isSameAs(empty()); } @Test public void shouldDropRightUntilNoneIfPredicateIsTrue() { final Seq values = of(1, 2, 3); assertThat(values.dropRightUntil(ignored -> true)).isEqualTo(values); } @Test public void shouldDropRightUntilAllIfPredicateIsFalse() { assertThat(of(1, 2, 3).dropRightUntil(ignored -> false)).isEqualTo(empty()); } @Test public void shouldDropRightUntilCorrect() { assertThat(of(1, 2, 3).dropRightUntil(i -> i <= 2)).isEqualTo(of(1, 2)); } // -- dropRightWhile @Test public void shouldDropRightWhileNoneOnNil() { assertThat(empty().dropRightWhile(ignored -> true)).isSameAs(empty()); } @Test public void shouldDropRightWhileNoneIfPredicateIsFalse() { final Seq values = of(1, 2, 3); assertThat(values.dropRightWhile(ignored -> false)).isEqualTo(values); } @Test public void shouldDropRightWhileAllIfPredicateIsTrue() { assertThat(of(1, 2, 3).dropRightWhile(ignored -> true)).isEqualTo(empty()); } @Test public void shouldDropRightWhileAccordingToPredicate() { assertThat(of(1, 2, 3).dropRightWhile(i -> i > 2)).isEqualTo(of(1, 2)); } @Test public void shouldDropRightWhileAndNotTruncate() { assertThat(of(1, 2, 3).dropRightWhile(i -> i % 2 == 1)).isEqualTo(of(1, 2)); } // -- get @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetWithNegativeIndexOnNil() { empty().get(-1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetWithNegativeIndexOnNonNil() { of(1).get(-1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetOnNil() { empty().get(0); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetWithTooBigIndexOnNonNil() { of(1).get(1); } @Test public void shouldGetFirstElement() { assertThat(of(1, 2, 3).get(0)).isEqualTo(1); } @Test public void shouldGetLastElement() { assertThat(of(1, 2, 3).get(2)).isEqualTo(3); } // -- indexOf @Test public void shouldNotFindIndexOfElementWhenSeqIsEmpty() { assertThat(empty().indexOf(1)).isEqualTo(-1); assertThat(empty().indexOfOption(1)).isEqualTo(Option.none()); } @Test public void shouldNotFindIndexOfElementWhenStartIsGreater() { assertThat(of(1, 2, 3, 4).indexOf(2, 2)).isEqualTo(-1); assertThat(of(1, 2, 3, 4).indexOfOption(2, 2)).isEqualTo(Option.none()); } @Test public void shouldFindIndexOfFirstElement() { assertThat(of(1, 2, 3).indexOf(1)).isEqualTo(0); assertThat(of(1, 2, 3).indexOfOption(1)).isEqualTo(Option.some(0)); } @Test public void shouldFindIndexOfInnerElement() { assertThat(of(1, 2, 3).indexOf(2)).isEqualTo(1); assertThat(of(1, 2, 3).indexOfOption(2)).isEqualTo(Option.some(1)); } @Test public void shouldFindIndexOfLastElement() { assertThat(of(1, 2, 3).indexOf(3)).isEqualTo(2); assertThat(of(1, 2, 3).indexOfOption(3)).isEqualTo(Option.some(2)); } // -- indexOfSlice @Test public void shouldNotFindIndexOfSliceWhenSeqIsEmpty() { assertThat(empty().indexOfSlice(of(2, 3))).isEqualTo(-1); assertThat(empty().indexOfSliceOption(of(2, 3))).isEqualTo(Option.none()); } @Test public void shouldNotFindIndexOfSliceWhenStartIsGreater() { assertThat(of(1, 2, 3, 4).indexOfSlice(of(2, 3), 2)).isEqualTo(-1); assertThat(of(1, 2, 3, 4).indexOfSliceOption(of(2, 3), 2)).isEqualTo(Option.none()); } @Test public void shouldFindIndexOfFirstSlice() { assertThat(of(1, 2, 3, 4).indexOfSlice(of(1, 2))).isEqualTo(0); assertThat(of(1, 2, 3, 4).indexOfSliceOption(of(1, 2))).isEqualTo(Option.some(0)); } @Test public void shouldFindIndexOfInnerSlice() { assertThat(of(1, 2, 3, 4).indexOfSlice(of(2, 3))).isEqualTo(1); assertThat(of(1, 2, 3, 4).indexOfSliceOption(of(2, 3))).isEqualTo(Option.some(1)); } @Test public void shouldFindIndexOfLastSlice() { assertThat(of(1, 2, 3).indexOfSlice(of(2, 3))).isEqualTo(1); assertThat(of(1, 2, 3).indexOfSliceOption(of(2, 3))).isEqualTo(Option.some(1)); } // -- lastIndexOf @Test public void shouldNotFindLastIndexOfElementWhenSeqIsEmpty() { assertThat(empty().lastIndexOf(1)).isEqualTo(-1); assertThat(empty().lastIndexOfOption(1)).isEqualTo(Option.none()); } @Test public void shouldNotFindLastIndexOfElementWhenEndIdLess() { assertThat(of(1, 2, 3, 4).lastIndexOf(3, 1)).isEqualTo(-1); assertThat(of(1, 2, 3, 4).lastIndexOfOption(3, 1)).isEqualTo(Option.none()); } @Test public void shouldFindLastIndexOfElement() { assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOf(1)).isEqualTo(3); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfOption(1)).isEqualTo(Option.some(3)); } @Test public void shouldFindLastIndexOfElementWithEnd() { assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOf(1, 1)).isEqualTo(0); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfOption(1, 1)).isEqualTo(Option.some(0)); } // -- lastIndexOfSlice @Test public void shouldNotFindLastIndexOfSliceWhenSeqIsEmpty() { assertThat(empty().lastIndexOfSlice(of(2, 3))).isEqualTo(-1); assertThat(empty().lastIndexOfSliceOption(of(2, 3))).isEqualTo(Option.none()); } @Test public void shouldNotFindLastIndexOfSliceWhenEndIdLess() { assertThat(of(1, 2, 3, 4, 5).lastIndexOfSlice(of(3, 4), 1)).isEqualTo(-1); assertThat(of(1, 2, 3, 4, 5).lastIndexOfSliceOption(of(3, 4), 1)).isEqualTo(Option.none()); } @Test public void shouldFindLastIndexOfSlice() { assertThat(of(1, 2, 3, 1, 2).lastIndexOfSlice(empty())).isEqualTo(5); assertThat(of(1, 2, 3, 1, 2).lastIndexOfSlice(of(2))).isEqualTo(4); assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSlice(of(2, 3))).isEqualTo(4); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(1, 2, 3))).isEqualTo(3); assertThat(of(1, 2, 3, 1, 2).lastIndexOfSliceOption(empty())).isEqualTo(Option.some(5)); assertThat(of(1, 2, 3, 1, 2).lastIndexOfSliceOption(of(2))).isEqualTo(Option.some(4)); assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSliceOption(of(2, 3))).isEqualTo(Option.some(4)); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(1, 2, 3))).isEqualTo(Option.some(3)); } @Test public void shouldFindLastIndexOfSliceWithEnd() { assertThat(empty().lastIndexOfSlice(empty(), -1)).isEqualTo(-1); assertThat(empty().lastIndexOfSlice(empty(), 0)).isEqualTo(0); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(empty(), -1)).isEqualTo(-1); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(empty(), 2)).isEqualTo(2); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(2), -1)).isEqualTo(-1); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(2), 2)).isEqualTo(1); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(2, 3), 2)).isEqualTo(1); assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSlice(of(2, 3), 2)).isEqualTo(1); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(1, 2, 3), 2)).isEqualTo(0); assertThat(empty().lastIndexOfSliceOption(empty(), -1)).isEqualTo(Option.none()); assertThat(empty().lastIndexOfSliceOption(empty(), 0)).isEqualTo(Option.some(0)); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(empty(), -1)).isEqualTo(Option.none()); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(empty(), 2)).isEqualTo(Option.some(2)); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(2), -1)).isEqualTo(Option.none()); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(2), 2)).isEqualTo(Option.some(1)); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(2, 3), 2)).isEqualTo(Option.some(1)); assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSliceOption(of(2, 3), 2)).isEqualTo(Option.some(1)); assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(1, 2, 3), 2)).isEqualTo(Option.some(0)); } // -- indexWhere @Test public void shouldCalculateIndexWhere() { assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 0)).isEqualTo(0); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 1)).isEqualTo(1); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 2)).isEqualTo(2); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 8)).isEqualTo(-1); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 0, 3)).isEqualTo(4); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 1, 3)).isEqualTo(5); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 2, 3)).isEqualTo(6); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 8, 3)).isEqualTo(-1); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 0)).isEqualTo(Option.some(0)); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 1)).isEqualTo(Option.some(1)); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 2)).isEqualTo(Option.some(2)); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 8)).isEqualTo(Option.none()); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 0, 3)).isEqualTo(Option.some(4)); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 1, 3)).isEqualTo(Option.some(5)); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 2, 3)).isEqualTo(Option.some(6)); assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 8, 3)).isEqualTo(Option.none()); } @Test(expected = NullPointerException.class) public void shouldFailIndexWhereNullPredicate() { of(1).indexWhere(null); } @Test(expected = NullPointerException.class) public void shouldFailIndexWhereNullPredicateFrom() { of(1).indexWhere(null, 0); } // -- lastIndexWhere @Test public void shouldCalculateLastIndexWhere() { assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 0)).isEqualTo(4); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 1)).isEqualTo(5); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 2)).isEqualTo(6); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 8)).isEqualTo(-1); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 0, 3)).isEqualTo(0); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 1, 3)).isEqualTo(1); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 2, 3)).isEqualTo(2); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 8, 3)).isEqualTo(-1); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 0)).isEqualTo(Option.some(4)); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 1)).isEqualTo(Option.some(5)); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 2)).isEqualTo(Option.some(6)); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 8)).isEqualTo(Option.none()); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 0, 3)).isEqualTo(Option.some(0)); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 1, 3)).isEqualTo(Option.some(1)); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 2, 3)).isEqualTo(Option.some(2)); assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 8, 3)).isEqualTo(Option.none()); } @Test(expected = NullPointerException.class) public void shouldFailLastIndexWhereNullPredicate() { of(1).lastIndexWhere(null); } @Test(expected = NullPointerException.class) public void shouldFailLastIndexWhereNullPredicateFrom() { of(1).lastIndexWhere(null, 0); } // -- endsWith @Test public void shouldTestEndsWith() { assertThat(empty().endsWith(empty())).isTrue(); assertThat(empty().endsWith(of(1))).isFalse(); assertThat(of(1, 2, 3, 4).endsWith(empty())).isTrue(); assertThat(of(1, 2, 3, 4).endsWith(of(4))).isTrue(); assertThat(of(1, 2, 3, 4).endsWith(of(3, 4))).isTrue(); assertThat(of(1, 2, 3, 4).endsWith(of(1, 2, 3, 4))).isTrue(); assertThat(of(1, 2, 3, 4).endsWith(of(0, 1, 2, 3, 4))).isFalse(); assertThat(of(1, 2, 3, 4).endsWith(of(2, 3, 5))).isFalse(); } // -- equality @Test public void shouldObeyEqualityConstraints() { // sequential collections assertThat(empty().equals(List.empty())).isTrue(); assertThat(of(1).equals(List.of(1))).isTrue(); assertThat(of(1, 2, 3).equals(List.of(1, 2, 3))).isTrue(); assertThat(of(1, 2, 3).equals(List.of(3, 2, 1))).isFalse(); // other classes assertThat(empty().equals(HashMap.empty())).isFalse(); assertThat(empty().equals(HashMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(HashSet.empty())).isFalse(); assertThat(empty().equals(LinkedHashMap.empty())).isFalse(); assertThat(empty().equals(LinkedHashMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(LinkedHashSet.empty())).isFalse(); assertThat(empty().equals(TreeMap.empty())).isFalse(); assertThat(empty().equals(TreeMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(TreeSet.empty())).isFalse(); } // -- insert @Test public void shouldInsertIntoNil() { final Seq actual = this. empty().insert(0, 1); final Seq expected = of(1); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertInFrontOfElement() { final Seq actual = of(4).insert(0, 1); final Seq expected = of(1, 4); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertBehindOfElement() { final Seq actual = of(4).insert(1, 5); final Seq expected = of(4, 5); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertIntoSeq() { final Seq actual = of(1, 2, 3).insert(2, 4); final Seq expected = of(1, 2, 4, 3); assertThat(actual).isEqualTo(expected); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNonNilWithNegativeIndex() { of(1).insert(-1, null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNilWithNegativeIndex() { empty().insert(-1, null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnInsertWhenExceedingUpperBound() { empty().insert(1, null); } // -- insertAll @Test public void shouldInsertAllIntoNil() { final Seq actual = this. empty().insertAll(0, of(1, 2, 3)); final Seq expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertAllInFrontOfElement() { final Seq actual = of(4).insertAll(0, of(1, 2, 3)); final Seq expected = of(1, 2, 3, 4); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertAllBehindOfElement() { final Seq actual = of(4).insertAll(1, of(1, 2, 3)); final Seq expected = of(4, 1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertAllIntoSeq() { final Seq actual = of(1, 2, 3).insertAll(2, of(4, 5)); final Seq expected = of(1, 2, 4, 5, 3); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowOnInsertAllWithNil() { empty().insertAll(0, null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNonNilAllWithNegativeIndex() { of(1).insertAll(-1, empty()); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNilAllWithNegativeIndex() { empty().insertAll(-1, empty()); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnInsertAllWhenExceedingUpperBound() { empty().insertAll(1, empty()); } @Test public void shouldReturnSameSeqWhenEmptyInsertAllEmpty() { final Seq empty = empty(); assertThat(empty.insertAll(0, empty())).isSameAs(empty); } @Test public void shouldReturnSameSeqWhenEmptyInsertAllNonEmpty() { final Seq seq = of(1, 2, 3); assertThat(empty().insertAll(0, seq)).isSameAs(seq); } @Test public void shouldReturnSameSeqWhenNonEmptyInsertAllEmpty() { final Seq seq = of(1, 2, 3); assertThat(seq.insertAll(0, empty())).isSameAs(seq); } // -- intersperse @Test public void shouldIntersperseNil() { assertThat(this. empty().intersperse(',')).isEmpty(); } @Test public void shouldIntersperseSingleton() { assertThat(of('a').intersperse(',')).isEqualTo(of('a')); } @Test public void shouldIntersperseMultipleElements() { assertThat(of('a', 'b').intersperse(',')).isEqualTo(of('a', ',', 'b')); } // -- isSequential() @Test public void shouldReturnTrueWhenIsSequentialCalled() { assertThat(of(1, 2, 3).isSequential()).isTrue(); } // -- iterator(int) @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenNilIteratorStartingAtIndex() { empty().iterator(1); } @Test public void shouldIterateFirstElementOfNonNilStartingAtIndex() { assertThat(of(1, 2, 3).iterator(1).next()).isEqualTo(2); } @Test public void shouldFullyIterateNonNilStartingAtIndex() { int actual = -1; for (Iterator iter = of(1, 2, 3).iterator(1); iter.hasNext(); ) { actual = iter.next(); } assertThat(actual).isEqualTo(3); } // -- padTo @Test public void shouldPadEmptyToEmpty() { assertThat(empty().padTo(0, 1)).isSameAs(empty()); } @Test public void shouldPadEmptyToNonEmpty() { assertThat(empty().padTo(2, 1)).isEqualTo(of(1, 1)); } @Test public void shouldPadNonEmptyZeroLen() { final Seq seq = of(1); assertThat(seq.padTo(0, 2)).isSameAs(seq); } @Test public void shouldPadNonEmpty() { assertThat(of(1).padTo(2, 1)).isEqualTo(of(1, 1)); assertThat(of(1).padTo(2, 2)).isEqualTo(of(1, 2)); assertThat(of(1).padTo(3, 2)).isEqualTo(of(1, 2, 2)); } // -- leftPadTo @Test public void shouldLeftPadEmptyToEmpty() { assertThat(empty().leftPadTo(0, 1)).isSameAs(empty()); } @Test public void shouldLeftPadEmptyToNonEmpty() { assertThat(empty().leftPadTo(2, 1)).isEqualTo(of(1, 1)); } @Test public void shouldLeftPadNonEmptyZeroLen() { final Seq seq = of(1); assertThat(seq.leftPadTo(0, 2)).isSameAs(seq); } @Test public void shouldLeftPadNonEmpty() { assertThat(of(1).leftPadTo(2, 1)).isEqualTo(of(1, 1)); assertThat(of(1).leftPadTo(2, 2)).isEqualTo(of(2, 1)); assertThat(of(1).leftPadTo(3, 2)).isEqualTo(of(2, 2, 1)); } // -- patch @Test public void shouldPatchEmptyByEmpty() { assertThat(empty().patch(0, empty(), 0)).isEmpty(); assertThat(empty().patch(-1, empty(), -1)).isEmpty(); assertThat(empty().patch(-1, empty(), 1)).isEmpty(); assertThat(empty().patch(1, empty(), -1)).isEmpty(); assertThat(empty().patch(1, empty(), 1)).isEmpty(); } @Test public void shouldPatchEmptyByNonEmpty() { final Seq s = of('1', '2', '3'); assertThat(empty().patch(0, s, 0)).isEqualTo(s); assertThat(empty().patch(-1, s, -1)).isEqualTo(s); assertThat(empty().patch(-1, s, 1)).isEqualTo(s); assertThat(empty().patch(1, s, -1)).isEqualTo(s); assertThat(empty().patch(1, s, 1)).isEqualTo(s); } @Test public void shouldPatchNonEmptyByEmpty() { final Seq s = of('1', '2', '3'); assertThat(s.patch(-1, empty(), -1)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(-1, empty(), 0)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(-1, empty(), 1)).isEqualTo(of('2', '3')); assertThat(s.patch(-1, empty(), 3)).isEmpty(); assertThat(s.patch(0, empty(), -1)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(0, empty(), 0)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(0, empty(), 1)).isEqualTo(of('2', '3')); assertThat(s.patch(0, empty(), 3)).isEmpty(); assertThat(s.patch(1, empty(), -1)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(1, empty(), 0)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(1, empty(), 1)).isEqualTo(of('1', '3')); assertThat(s.patch(1, empty(), 3)).isEqualTo(of('1')); assertThat(s.patch(4, empty(), -1)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(4, empty(), 0)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(4, empty(), 1)).isEqualTo(of('1', '2', '3')); assertThat(s.patch(4, empty(), 3)).isEqualTo(of('1', '2', '3')); } @Test public void shouldPatchNonEmptyByNonEmpty() { final Seq s = of('1', '2', '3'); final Seq d = of('4', '5', '6'); assertThat(s.patch(-1, d, -1)).isEqualTo(of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(-1, d, 0)).isEqualTo(of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(-1, d, 1)).isEqualTo(of('4', '5', '6', '2', '3')); assertThat(s.patch(-1, d, 3)).isEqualTo(of('4', '5', '6')); assertThat(s.patch(0, d, -1)).isEqualTo(of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(0, d, 0)).isEqualTo(of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(0, d, 1)).isEqualTo(of('4', '5', '6', '2', '3')); assertThat(s.patch(0, d, 3)).isEqualTo(of('4', '5', '6')); assertThat(s.patch(1, d, -1)).isEqualTo(of('1', '4', '5', '6', '2', '3')); assertThat(s.patch(1, d, 0)).isEqualTo(of('1', '4', '5', '6', '2', '3')); assertThat(s.patch(1, d, 1)).isEqualTo(of('1', '4', '5', '6', '3')); assertThat(s.patch(1, d, 3)).isEqualTo(of('1', '4', '5', '6')); assertThat(s.patch(4, d, -1)).isEqualTo(of('1', '2', '3', '4', '5', '6')); assertThat(s.patch(4, d, 0)).isEqualTo(of('1', '2', '3', '4', '5', '6')); assertThat(s.patch(4, d, 1)).isEqualTo(of('1', '2', '3', '4', '5', '6')); assertThat(s.patch(4, d, 3)).isEqualTo(of('1', '2', '3', '4', '5', '6')); } // -- permutations @Test public void shouldComputePermutationsOfEmptySeq() { assertThat(empty().permutations()).isEmpty(); } @Test public void shouldComputePermutationsOfSingleton() { assertThat(of(1).permutations()).isEqualTo(of(of(1))); } @SuppressWarnings("unchecked") @Test public void shouldComputePermutationsOfRepeatedElements() { assertThat(of(1, 1).permutations()).isEqualTo(of(of(1, 1))); assertThat(of(1, 2, 2).permutations()).isEqualTo(of(of(1, 2, 2), of(2, 1, 2), of(2, 2, 1))); } @SuppressWarnings("unchecked") @Test public void shouldComputePermutationsOfNonEmptySeq() { assertThat(of(1, 2, 3).permutations()) .isEqualTo(of(of(1, 2, 3), of(1, 3, 2), of(2, 1, 3), of(2, 3, 1), of(3, 1, 2), of(3, 2, 1))); } // -- map @Test public void shouldMapTransformedSeq() { final Function mapper = o -> o + 1; assertThat(this. empty().map(mapper)).isEmpty(); assertThat(of(3, 1, 4, 1, 5).map(mapper)).isEqualTo(of(4, 2, 5, 2, 6)); assertThat(of(3, 1, 4, 1, 5, 9, 2).sorted().distinct().drop(1).init().remove(5).map(mapper).tail()).isEqualTo(of(4, 5)); } // -- prefixLength @Test public void shouldCalculatePrefixLength() { assertThat(of(1, 3, 5, 6).prefixLength(i -> (i & 1) > 0)).isEqualTo(3); assertThat(of(1, 3, 5).prefixLength(i -> (i & 1) > 0)).isEqualTo(3); assertThat(of(2).prefixLength(i -> (i & 1) > 0)).isEqualTo(0); assertThat(empty().prefixLength(i -> true)).isEqualTo(0); } @Test(expected = NullPointerException.class) public void shouldThrowPrefixLengthNullPredicate() { of(1).prefixLength(null); } // -- segmentLength @Test public void shouldCalculateSegmentLength() { assertThat(of(1, 3, 5, 6).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(2); assertThat(of(1, 3, 5).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(2); assertThat(of(2, 2).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(0); assertThat(of(2).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(0); assertThat(empty().segmentLength(i -> true, 1)).isEqualTo(0); } @Test(expected = NullPointerException.class) public void shouldThrowSegmentLengthNullPredicate() { of(1).segmentLength(null, 0); } // -- prepend @Test public void shouldPrependElementToNil() { final Seq actual = this. empty().prepend(1); final Seq expected = of(1); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependElementToNonNil() { final Seq actual = of(2, 3).prepend(1); final Seq expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } // -- prependAll @Test(expected = NullPointerException.class) public void shouldThrowOnPrependAllOfNull() { empty().prependAll(null); } @Test public void shouldPrependAllNilToNil() { final Seq actual = this. empty().prependAll(empty()); final Seq expected = empty(); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependAllNilToNonNil() { final Seq actual = of(1, 2, 3).prependAll(empty()); final Seq expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependAllNonNilToNil() { final Seq actual = this. empty().prependAll(of(1, 2, 3)); final Seq expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependAllNonNilToNonNil() { final Seq expected = range(0, 100); final Seq actualFirstPartLarger = range(90, 100).prependAll(range(0, 90)); assertThat(actualFirstPartLarger).isEqualTo(expected); final Seq actualSecondPartLarger = range(10, 100).prependAll(range(0, 10)); assertThat(actualSecondPartLarger).isEqualTo(expected); } @Test public void shouldReturnSameSeqWhenEmptyPrependAllEmpty() { final Seq empty = empty(); assertThat(empty.prependAll(empty())).isSameAs(empty); } @Test public void shouldReturnSameSeqWhenEmptyPrependAllNonEmpty() { final Seq seq = of(1, 2, 3); assertThat(empty().prependAll(seq)).isSameAs(seq); } @Test public void shouldReturnSameSeqWhenNonEmptyPrependAllEmpty() { final Seq seq = of(1, 2, 3); assertThat(seq.prependAll(empty())).isSameAs(seq); } // -- remove @Test public void shouldRemoveElementFromNil() { assertThat(empty().remove(null)).isEmpty(); } @Test public void shouldRemoveFirstElement() { assertThat(of(1, 2, 3).remove(1)).isEqualTo(of(2, 3)); } @Test public void shouldRemoveLastElement() { assertThat(of(1, 2, 3).remove(3)).isEqualTo(of(1, 2)); } @Test public void shouldRemoveInnerElement() { assertThat(of(1, 2, 3).remove(2)).isEqualTo(of(1, 3)); } @Test public void shouldNotRemoveDuplicateElement() { assertThat(of(1, 2, 3, 1, 2).remove(1).remove(3)).isEqualTo(of(2, 1, 2)); } @Test public void shouldRemoveNonExistingElement() { final Seq t = of(1, 2, 3); assertThat(t.remove(4)).isSameAs(t); } // -- removeFirst(Predicate) @Test public void shouldRemoveFirstElementByPredicateFromNil() { assertThat(empty().removeFirst(v -> true)).isEmpty(); } @Test public void shouldRemoveFirstElementByPredicateBegin() { assertThat(of(1, 2, 3).removeFirst(v -> v == 1)).isEqualTo(of(2, 3)); } @Test public void shouldRemoveFirstElementByPredicateBeginM() { assertThat(of(1, 2, 1, 3).removeFirst(v -> v == 1)).isEqualTo(of(2, 1, 3)); } @Test public void shouldRemoveFirstElementByPredicateEnd() { assertThat(of(1, 2, 3).removeFirst(v -> v == 3)).isEqualTo(of(1, 2)); } @Test public void shouldRemoveFirstElementByPredicateInner() { assertThat(of(1, 2, 3, 4, 5).removeFirst(v -> v == 3)).isEqualTo(of(1, 2, 4, 5)); } @Test public void shouldRemoveFirstElementByPredicateInnerM() { assertThat(of(1, 2, 3, 2, 5).removeFirst(v -> v == 2)).isEqualTo(of(1, 3, 2, 5)); } @Test public void shouldRemoveFirstElementByPredicateNonExisting() { final Seq t = of(1, 2, 3); assertThat(t.removeFirst(v -> v == 4)).isSameAs(t); } // -- removeLast(Predicate) @Test public void shouldRemoveLastElementByPredicateFromNil() { assertThat(empty().removeLast(v -> true)).isEmpty(); } @Test public void shouldRemoveLastElementByPredicateBegin() { assertThat(of(1, 2, 3).removeLast(v -> v == 1)).isEqualTo(of(2, 3)); } @Test public void shouldRemoveLastElementByPredicateEnd() { assertThat(of(1, 2, 3).removeLast(v -> v == 3)).isEqualTo(of(1, 2)); } @Test public void shouldRemoveLastElementByPredicateEndM() { assertThat(of(1, 3, 2, 3).removeLast(v -> v == 3)).isEqualTo(of(1, 3, 2)); } @Test public void shouldRemoveLastElementByPredicateInner() { assertThat(of(1, 2, 3, 4, 5).removeLast(v -> v == 3)).isEqualTo(of(1, 2, 4, 5)); } @Test public void shouldRemoveLastElementByPredicateInnerM() { assertThat(of(1, 2, 3, 2, 5).removeLast(v -> v == 2)).isEqualTo(of(1, 2, 3, 5)); } @Test public void shouldRemoveLastElementByPredicateNonExisting() { final Seq t = of(1, 2, 3); assertThat(t.removeLast(v -> v == 4)).isSameAs(t); } // -- removeAll(Iterable) @Test public void shouldRemoveAllElementsFromNil() { assertThat(empty().removeAll(of(1, 2, 3))).isEmpty(); } @Test public void shouldRemoveAllExistingElementsFromNonNil() { assertThat(of(1, 2, 3, 1, 2, 3).removeAll(of(1, 2))).isEqualTo(of(3, 3)); } @Test public void shouldNotRemoveAllNonExistingElementsFromNonNil() { final Seq t = of(1, 2, 3); assertThat(t.removeAll(of(4, 5))).isSameAs(t); } @Test public void shouldReturnSameSeqWhenNonEmptyRemoveAllEmpty() { final Seq seq = of(1, 2, 3); assertThat(seq.removeAll(empty())).isSameAs(seq); } @Test public void shouldReturnSameSeqWhenEmptyRemoveAllNonEmpty() { final Seq empty = empty(); assertThat(empty.removeAll(of(1, 2, 3))).isSameAs(empty); } // -- removeAll(Predicate) @SuppressWarnings("deprecation") @Test public void shouldRemoveExistingElements() { final Seq seq = of(1, 2, 3); assertThat(seq.removeAll(i -> i == 1)).isEqualTo(of(2, 3)); assertThat(seq.removeAll(i -> i == 2)).isEqualTo(of(1, 3)); assertThat(seq.removeAll(i -> i == 3)).isEqualTo(of(1, 2)); assertThat(seq.removeAll(ignore -> true)).isEmpty(); assertThat(seq.removeAll(ignore -> false)).isSameAs(seq); } @SuppressWarnings("deprecation") @Test public void shouldRemoveNonExistingElements() { assertThat(this. empty().removeAll(i -> i == 0)).isSameAs(empty()); assertThat(of(1, 2, 3).removeAll(i -> i != 0)).isSameAs(empty()); } @SuppressWarnings("deprecation") @Test public void shouldRemoveAllElementsByPredicateFromNil() { assertThat(empty().removeAll(o -> true)).isEmpty(); } @SuppressWarnings("deprecation") @Test public void shouldRemoveAllExistingElements() { assertThat(of(1, 2, 3, 4, 5, 6).removeAll(ignored -> true)).isEmpty(); } @SuppressWarnings("deprecation") @Test public void shouldRemoveAllMatchedElementsFromNonNil() { assertThat(of(1, 2, 3, 4, 5, 6).removeAll(i -> i % 2 == 0)).isEqualTo(of(1, 3, 5)); } @SuppressWarnings("deprecation") @Test public void shouldNotRemoveAllNonMatchedElementsFromNonNil() { final Seq t = of(1, 2, 3); final Predicate isTooBig = i -> i >= 4; assertThat(t.removeAll(isTooBig)).isSameAs(t); } // -- removeAll(Object) @Test public void shouldRemoveAllObjectsFromNil() { assertThat(empty().removeAll(1)).isEmpty(); } @Test public void shouldRemoveAllExistingObjectsFromNonNil() { assertThat(of(1, 2, 3, 1, 2, 3).removeAll(1)).isEqualTo(of(2, 3, 2, 3)); } @Test public void shouldNotRemoveAllNonObjectsElementsFromNonNil() { final Seq seq = of(1, 2, 3); assertThat(seq.removeAll(4)).isSameAs(seq); } @Test public void shouldRemoveAllNullsFromNonEmpty() { final Seq seq = of(1, null, 2, null, 3); assertThat(seq.removeAll((Integer) null)).isEqualTo(of(1, 2, 3)); } // -- removeAt(index) @Test(expected = IndexOutOfBoundsException.class) public void shouldRemoveIndexAtNil() { assertThat(empty().removeAt(1)).isEmpty(); } @Test public void shouldRemoveIndexAtNonNil() { assertThat(of(1, 2, 3).removeAt(1)).isEqualTo(of(1, 3)); } @Test public void shouldRemoveIndexAtBegin() { assertThat(of(1, 2, 3).removeAt(0)).isEqualTo(of(2, 3)); } @Test public void shouldRemoveIndexAtEnd() { assertThat(of(1, 2, 3).removeAt(2)).isEqualTo(of(1, 2)); } @Test public void shouldRemoveMultipleTimes() { assertThat(of(3, 1, 4, 1, 5, 9, 2).removeAt(0).removeAt(0).removeAt(4).removeAt(3).removeAt(1)).isEqualTo(of(4, 5)); } @Test(expected = IndexOutOfBoundsException.class) public void shouldRemoveIndexOutOfBoundsLeft() { assertThat(of(1, 2, 3).removeAt(-1)).isEqualTo(of(1, 2, 3)); } @Test(expected = IndexOutOfBoundsException.class) public void shouldRemoveIndexOutOfBoundsRight() { assertThat(of(1, 2, 3).removeAt(5)).isEqualTo(of(1, 2, 3)); } // -- reverse @Test public void shouldReverseNil() { assertThat(empty().reverse()).isEmpty(); } @Test public void shouldReverseNonNil() { assertThat(of(1, 2, 3).reverse()).isEqualTo(of(3, 2, 1)); } // -- reverseIterator @Test public void shouldCreateReverseIteratorOfEmpty() { assertThat(ofAll(empty()).reverseIterator()).isEmpty(); } @Test public void shouldCreateReverseIteratorOfSingle() { assertThat(ofAll(this.of("a")).reverseIterator().toList()).isEqualTo(Iterator.of("a").toList()); } @Test public void shouldCreateReverseIteratorOfNonEmpty() { assertThat(ofAll(of("a", "b", "c")).reverseIterator().toList()).isEqualTo(Iterator.of("c", "b", "a").toList()); } // -- todo rotateLeft @Test public void shouldRotateLeftOnEmpty() { assertThat(empty().rotateLeft(1)).isSameAs(empty()); } @Test public void shouldRotateLeftOnSingle() { Seq seq = of(1); assertThat(seq.rotateLeft(1)).isSameAs(seq); } @Test public void shouldRotateLeftForZero() { Seq seq = of(1, 2, 3, 4, 5); assertThat(seq.rotateLeft(0)).isSameAs(seq); } @Test public void shouldRotateLeftForNegativeLessThatLen() { assertThat(of(1, 2, 3, 4, 5).rotateLeft(-2)).isEqualTo(of(4, 5, 1, 2, 3)); } @Test public void shouldRotateLeftForPositiveLessThatLen() { assertThat(of(1, 2, 3, 4, 5).rotateLeft(2)).isEqualTo(of(3, 4, 5, 1, 2)); } @Test public void shouldRotateLeftForPositiveGreaterThatLen() { assertThat(of(1, 2, 3, 4, 5).rotateLeft(5 + 2)).isEqualTo(of(3, 4, 5, 1, 2)); } @Test public void shouldRotateLeftForPositiveModuloLen() { Seq seq = of(1, 2, 3, 4, 5); assertThat(seq.rotateLeft(seq.length() * 3)).isSameAs(seq); } // -- rotateRight @Test public void shouldRotateRightOnEmpty() { assertThat(empty().rotateRight(1)).isSameAs(empty()); } @Test public void shouldRotateRightOnSingle() { Seq seq = of(1); assertThat(seq.rotateRight(1)).isSameAs(seq); } @Test public void shouldRotateRightForZero() { Seq seq = of(1, 2, 3, 4, 5); assertThat(seq.rotateRight(0)).isSameAs(seq); } @Test public void shouldRotateRightForNegativeLessThatLen() { assertThat(of(1, 2, 3, 4, 5).rotateRight(-2)).isEqualTo(of(3, 4, 5, 1, 2)); } @Test public void shouldRotateRightForPositiveLessThatLen() { assertThat(of(1, 2, 3, 4, 5).rotateRight(2)).isEqualTo(of(4, 5, 1, 2, 3)); } @Test public void shouldRotateRightForPositiveGreaterThatLen() { assertThat(of(1, 2, 3, 4, 5).rotateRight(5 + 2)).isEqualTo(of(4, 5, 1, 2, 3)); } @Test public void shouldRotateRightForPositiveModuloLen() { Seq seq = of(1, 2, 3, 4, 5); assertThat(seq.rotateRight(seq.length() * 3)).isSameAs(seq); } // -- shuffle @Test public void shouldShuffleEmpty() { assertThat(empty().shuffle().isEmpty()); } @Test public void shouldShuffleHaveSameLength() { assertThat(of(1, 2, 3).shuffle().size()).isEqualTo(of(1, 2, 3).size()); } @Test public void shouldShuffleHaveSameElements() { final Seq shuffled = of(1, 2, 3).shuffle(); assertThat(shuffled.indexOf(1)).isNotEqualTo(-1); assertThat(shuffled.indexOf(2)).isNotEqualTo(-1); assertThat(shuffled.indexOf(3)).isNotEqualTo(-1); assertThat(shuffled.indexOf(4)).isEqualTo(-1); } // -- takeRightUntil @Test public void shouldTakeRightUntilNoneOnNil() { assertThat(empty().takeRightUntil(x -> true)).isEqualTo(empty()); } @Test public void shouldTakeRightUntilAllOnFalseCondition() { assertThat(of(1, 2, 3).takeRightUntil(x -> false)).isEqualTo(of(1, 2, 3)); } @Test public void shouldTakeRightUntilAllOnTrueCondition() { assertThat(of(1, 2, 3).takeRightUntil(x -> true)).isEqualTo(empty()); } @Test public void shouldTakeRightUntilAsExpected() { assertThat(of(2, 3, 4, 6).takeRightUntil(x -> x % 2 != 0)).isEqualTo(of(4, 6)); } // -- takeRightWhile @Test public void shouldTakeRightWhileNoneOnNil() { assertThat(empty().takeRightWhile(x -> true)).isEqualTo(empty()); } @Test public void shouldTakeRightWhileAllOnFalseCondition() { assertThat(of(1, 2, 3).takeRightWhile(x -> false)).isEqualTo(empty()); } @Test public void shouldTakeRightWhileAllOnTrueCondition() { assertThat(of(1, 2, 3).takeRightWhile(x -> true)).isEqualTo(of(1, 2, 3)); } @Test public void shouldTakeRightWhileAsExpected() { assertThat(of(2, 3, 4, 6).takeRightWhile(x -> x % 2 == 0)).isEqualTo(of(4, 6)); } // -- update @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdatedWithNegativeIndexOnNil() { empty().update(-1, (Integer) null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdatedWithNegativeIndexOnNonNil() { of(1).update(-1, 2); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdatedOnNil() { empty().update(0, (Integer) null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdatedWithIndexExceedingByOneOnNonNil() { of(1).update(1, 2); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdatedWithIndexExceedingByTwoOnNonNil() { of(1).update(2, 2); } @Test public void shouldUpdateFirstElement() { assertThat(of(1, 2, 3).update(0, 4)).isEqualTo(of(4, 2, 3)); } @Test public void shouldUpdateLastElement() { assertThat(of(1, 2, 3).update(2, 4)).isEqualTo(of(1, 2, 4)); } // -- higher order update @Test public void shouldUpdateViaFunction() throws Exception { final Seq actual = ofAll("hello".toCharArray()).update(0, Character::toUpperCase); final Seq expected = ofAll("Hello".toCharArray()); assertThat(actual).isEqualTo(expected); } // -- slice(beginIndex, endIndex) @Test public void shouldReturnNilWhenSliceFrom0To0OnNil() { final Seq actual = this. empty().slice(0, 0); assertThat(actual).isEmpty(); } @Test public void shouldReturnNilWhenSliceFrom0To0OnNonNil() { final Seq actual = of(1).slice(0, 0); assertThat(actual).isEmpty(); } @Test public void shouldReturnSeqWithFirstElementWhenSliceFrom0To1OnNonNil() { final Seq actual = of(1).slice(0, 1); assertThat(actual).isEqualTo(of(1)); } @Test public void shouldReturnNilWhenSliceFrom1To1OnNonNil() { final Seq actual = of(1).slice(1, 1); assertThat(actual).isEmpty(); } @Test public void shouldReturnSliceWhenIndicesAreWithinRange() { final Seq actual = of(1, 2, 3).slice(1, 3); assertThat(actual).isEqualTo(of(2, 3)); } @Test public void shouldReturnNilOnSliceWhenIndicesBothAreUpperBound() { final Seq actual = of(1, 2, 3).slice(3, 3); assertThat(actual).isEmpty(); } @Test public void shouldComputeSliceOnNonNilWhenBeginIndexIsGreaterThanEndIndex() { assertThat(of(1, 2, 3).slice(1, 0)).isEmpty(); } @Test public void shouldComputeSliceOnNilWhenBeginIndexIsGreaterThanEndIndex() { assertThat(empty().slice(1, 0)).isEmpty(); } @Test public void shouldComputeSliceOnNonNilWhenBeginIndexExceedsLowerBound() { assertThat(of(1, 2, 3).slice(-1, 2)).isEqualTo(of(1, 2)); } @Test public void shouldComputeSliceOnNilWhenBeginIndexExceedsLowerBound() { assertThat(empty().slice(-1, 2)).isEmpty(); } @Test public void shouldThrowWhenSlice2OnNil() { assertThat(empty().slice(0, 1)).isEmpty(); } @Test public void shouldComputeSliceWhenEndIndexExceedsUpperBound() { assertThat(of(1, 2, 3).slice(1, 4)).isEqualTo(of(2, 3)); } @Test public void shouldComputeSliceWhenBeginIndexIsGreaterThanEndIndex() { assertThat(of(1, 2, 3).slice(2, 1)).isEmpty(); } @Test public void shouldComputeSliceWhenBeginIndexAndEndIndexAreBothOutOfBounds() { assertThat(of(1, 2, 3).slice(-10, 10)).isEqualTo(of(1, 2, 3)); } // -- sorted() @Test public void shouldSortNil() { assertThat(empty().sorted()).isEmpty(); } @Test public void shouldSortNonNil() { assertThat(of(3, 4, 1, 2).sorted()).isEqualTo(of(1, 2, 3, 4)); } // -- sorted(Comparator) @Test public void shouldSortNilUsingComparator() { assertThat(this. empty().sorted((i, j) -> j - i)).isEmpty(); } @Test public void shouldSortNonNilUsingComparator() { assertThat(of(3, 4, 1, 2).sorted((i, j) -> j - i)).isEqualTo(of(4, 3, 2, 1)); } // -- sortBy(Function) @Test public void shouldSortByNilUsingFunction() { assertThat(this. empty().sortBy(String::length)).isEmpty(); } @Test public void shouldSortByNonNilUsingFunction() { final Seq testee = of("aaa", "b", "cc"); final Seq actual = testee.sortBy(String::length); final Seq expected = of("b", "cc", "aaa"); assertThat(actual).isEqualTo(expected); } @SuppressWarnings("unchecked") @Test public void shouldSortByFunctionWhenElementsAreInfiniteStreams() { final Stream stream1 = Stream.continually(1); final Stream stream2 = Stream.continually(2); final Seq> testee = of(stream2, stream1); final Seq> actual = testee.sortBy(Stream::head); final Seq> expected = of(stream1, stream2); assertThat(actual).isEqualTo(expected); } // -- sortBy(Comparator, Function) @Test public void shouldSortByNilUsingComparatorAndFunction() { assertThat(this. empty().sortBy(String::length)).isEmpty(); } @Test public void shouldSortByNonNilUsingComparatorAndFunction() { final Seq testee = of("aaa", "b", "cc"); final Seq actual = testee.sortBy((i1, i2) -> i2 - i1, String::length); final Seq expected = of("aaa", "cc", "b"); assertThat(actual).isEqualTo(expected); } // -- splitAt(index) @Test public void shouldSplitAtNil() { assertThat(empty().splitAt(1)).isEqualTo(Tuple.of(empty(), empty())); } @Test public void shouldSplitAtNonNil() { assertThat(of(1, 2, 3).splitAt(1)).isEqualTo(Tuple.of(of(1), of(2, 3))); } @Test public void shouldSplitAtBegin() { assertThat(of(1, 2, 3).splitAt(0)).isEqualTo(Tuple.of(empty(), of(1, 2, 3))); } @Test public void shouldSplitAtEnd() { assertThat(of(1, 2, 3).splitAt(3)).isEqualTo(Tuple.of(of(1, 2, 3), empty())); } @Test public void shouldSplitAtOutOfBounds() { assertThat(of(1, 2, 3).splitAt(5)).isEqualTo(Tuple.of(of(1, 2, 3), empty())); assertThat(of(1, 2, 3).splitAt(-1)).isEqualTo(Tuple.of(empty(), of(1, 2, 3))); } // -- splitAt(predicate) @Test public void shouldSplitPredicateAtNil() { assertThat(empty().splitAt(e -> true)).isEqualTo(Tuple.of(empty(), empty())); } @Test public void shouldSplitPredicateAtNonNil() { assertThat(of(1, 2, 3).splitAt(e -> e == 2)).isEqualTo(Tuple.of(of(1), of(2, 3))); } @Test public void shouldSplitAtPredicateBegin() { assertThat(of(1, 2, 3).splitAt(e -> e == 1)).isEqualTo(Tuple.of(empty(), of(1, 2, 3))); } @Test public void shouldSplitAtPredicateEnd() { assertThat(of(1, 2, 3).splitAt(e -> e == 3)).isEqualTo(Tuple.of(of(1, 2), of(3))); } @Test public void shouldSplitAtPredicateNotFound() { assertThat(of(1, 2, 3).splitAt(e -> e == 5)).isEqualTo(Tuple.of(of(1, 2, 3), empty())); } // -- splitAtInclusive(predicate) @Test public void shouldSplitInclusivePredicateAtNil() { assertThat(empty().splitAtInclusive(e -> true)).isEqualTo(Tuple.of(empty(), empty())); } @Test public void shouldSplitInclusivePredicateAtNonNil() { assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 2)).isEqualTo(Tuple.of(of(1, 2), of(3))); } @Test public void shouldSplitAtInclusivePredicateBegin() { assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 1)).isEqualTo(Tuple.of(of(1), of(2, 3))); } @Test public void shouldSplitAtInclusivePredicateEnd() { assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 3)).isEqualTo(Tuple.of(of(1, 2, 3), empty())); } @Test public void shouldSplitAtInclusivePredicateNotFound() { assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 5)).isEqualTo(Tuple.of(of(1, 2, 3), empty())); } // -- spliterator @Test public void shouldNotHaveSortedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SORTED)).isFalse(); } @Test public void shouldHaveOrderedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.ORDERED)).isTrue(); } @Test public void shouldNotHaveDistinctSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.DISTINCT)).isFalse(); } // -- startsWith @Test public void shouldStartsNilOfNilCalculate() { assertThat(empty().startsWith(empty())).isTrue(); } @Test public void shouldStartsNilOfNonNilCalculate() { assertThat(empty().startsWith(of(1))).isFalse(); } @Test public void shouldStartsNilOfNilWithOffsetCalculate() { assertThat(empty().startsWith(empty(), 1)).isTrue(); } @Test public void shouldStartsNilOfNonNilWithOffsetCalculate() { assertThat(empty().startsWith(of(1), 1)).isFalse(); } @Test public void shouldStartsNonNilOfNilCalculate() { assertThat(of(1, 2, 3).startsWith(empty())).isTrue(); } @Test public void shouldStartsNonNilOfNonNilCalculate() { assertThat(of(1, 2, 3).startsWith(of(1, 2))).isTrue(); assertThat(of(1, 2, 3).startsWith(of(1, 2, 3))).isTrue(); assertThat(of(1, 2, 3).startsWith(of(1, 2, 3, 4))).isFalse(); assertThat(of(1, 2, 3).startsWith(of(1, 3))).isFalse(); } @Test public void shouldStartsNonNilOfNilWithOffsetCalculate() { assertThat(of(1, 2, 3).startsWith(empty(), 1)).isTrue(); } @Test public void shouldNotStartsNonNilOfNonNilWithNegativeOffsetCalculate() { assertThat(of(1, 2, 3).startsWith(of(1), -1)).isFalse(); } @Test public void shouldNotStartsNonNilOfNonNilWithOffsetEqualLengthCalculate() { assertThat(of(1, 2, 3).startsWith(of(3), 3)).isFalse(); } @Test public void shouldNotStartsNonNilOfNonNilWithOffsetEndCalculate() { assertThat(of(1, 2, 3).startsWith(of(3), 2)).isTrue(); } @Test public void shouldStartsNonNilOfNonNilWithOffsetAtStartCalculate() { assertThat(of(1, 2, 3).startsWith(of(1), 0)).isTrue(); } @Test public void shouldStartsNonNilOfNonNilWithOffsetCalculate1() { assertThat(of(1, 2, 3).startsWith(of(2, 3), 1)).isTrue(); } @Test public void shouldStartsNonNilOfNonNilWithOffsetCalculate2() { assertThat(of(1, 2, 3).startsWith(of(2, 3, 4), 1)).isFalse(); } @Test public void shouldStartsNonNilOfNonNilWithOffsetCalculate3() { assertThat(of(1, 2, 3).startsWith(of(2, 4), 1)).isFalse(); } // -- subSequence(beginIndex) @Test public void shouldReturnNilWhenSubSequenceFrom0OnNil() { final Seq actual = this. empty().subSequence(0); assertThat(actual).isEmpty(); } @Test public void shouldReturnIdentityWhenSubSequenceFrom0OnNonNil() { final Seq actual = of(1).subSequence(0); assertThat(actual).isEqualTo(of(1)); } @Test public void shouldReturnNilWhenSubSequenceFrom1OnSeqOf1() { final Seq actual = of(1).subSequence(1); assertThat(actual).isEmpty(); } @Test public void shouldReturnSubSequenceWhenIndexIsWithinRange() { final Seq actual = of(1, 2, 3).subSequence(1); assertThat(actual).isEqualTo(of(2, 3)); } @Test public void shouldReturnNilWhenSubSequenceBeginningWithSize() { final Seq actual = of(1, 2, 3).subSequence(3); assertThat(actual).isEmpty(); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequenceOnNil() { empty().subSequence(1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequenceWithOutOfLowerBound() { of(1, 2, 3).subSequence(-1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequenceWithOutOfUpperBound() { of(1, 2, 3).subSequence(4); } @Test public void shouldReturnSameInstanceIfSubSequenceStartsAtZero() { final Seq seq = of(1, 2, 3); assertThat(seq.subSequence(0)).isSameAs(seq); } // -- subSequence(beginIndex, endIndex) @Test public void shouldReturnNilWhenSubSequenceFrom0To0OnNil() { final Seq actual = this. empty().subSequence(0, 0); assertThat(actual).isEmpty(); } @Test public void shouldReturnNilWhenSubSequenceFrom0To0OnNonNil() { final Seq actual = of(1).subSequence(0, 0); assertThat(actual).isEmpty(); } @Test public void shouldReturnSeqWithFirstElementWhenSubSequenceFrom0To1OnNonNil() { final Seq actual = of(1).subSequence(0, 1); assertThat(actual).isEqualTo(of(1)); } @Test public void shouldReturnNilWhenSubSequenceFrom1To1OnNonNil() { final Seq actual = of(1).subSequence(1, 1); assertThat(actual).isEmpty(); } @Test public void shouldReturnSubSequenceWhenIndicesAreWithinRange() { final Seq actual = of(1, 2, 3).subSequence(1, 3); assertThat(actual).isEqualTo(of(2, 3)); } @Test public void shouldReturnNilWhenOnSubSequenceIndicesBothAreUpperBound() { final Seq actual = of(1, 2, 3).subSequence(3, 3); assertThat(actual).isEmpty(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnSubSequenceOnNonNilWhenBeginIndexIsGreaterThanEndIndex() { of(1, 2, 3).subSequence(1, 0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnSubSequenceOnNilWhenBeginIndexIsGreaterThanEndIndex() { empty().subSequence(1, 0); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnSubSequenceOnNonNilWhenBeginIndexExceedsLowerBound() { of(1, 2, 3).subSequence(-1, 2); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnSubSequenceOnNilWhenBeginIndexExceedsLowerBound() { empty().subSequence(-1, 2); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequence2OnNil() { empty().subSequence(0, 1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnSubSequenceWhenEndIndexExceedsUpperBound() { of(1, 2, 3).subSequence(1, 4).mkString(); // force computation of last element, e.g. because Stream is lazy } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnSubSequenceWhenBeginIndexIsGreaterThanEndIndex() { of(1, 2, 3).subSequence(2, 1).mkString(); // force computation of last element, e.g. because Stream is lazy } @Test public void shouldReturnSameInstanceIfSubSequenceStartsAtZeroAndEndsAtLastElement() { final Seq seq = of(1, 2, 3); assertThat(seq.subSequence(0, 3)).isSameAs(seq); } // -- search(element) @Test public void shouldSearchIndexForPresentElements() { assertThat(of(1, 2, 3, 4, 5, 6).search(3)).isEqualTo(2); } @Test public void shouldSearchNegatedInsertionPointMinusOneForAbsentElements() { assertThat(empty().search(42)).isEqualTo(-1); assertThat(of(10, 20, 30).search(25)).isEqualTo(-3); } // -- search(element,comparator) @Test public void shouldSearchIndexForPresentElementsUsingComparator() { assertThat(of(1, 2, 3, 4, 5, 6).search(3, Integer::compareTo)).isEqualTo(2); } @Test public void shouldSearchNegatedInsertionPointMinusOneForAbsentElementsUsingComparator() { assertThat(this. empty().search(42, Integer::compareTo)).isEqualTo(-1); assertThat(of(10, 20, 30).search(25, Integer::compareTo)).isEqualTo(-3); } // -- transpose() @Test public void shouldTransposeIfEmpty() { final Seq> actual = empty(); assertThat(transpose(actual)).isSameAs(actual); } @Test public void shouldTransposeIfIs1x0() { final Seq> actual = of(empty()); assertThat(transpose(actual)).isSameAs(actual); } @Test public void shouldTransposeIfIs1x1() { final Seq> actual = of(of(1)); assertThat(transpose(actual)).isSameAs(actual); } @Test public void shouldTransposeIfSingleValued() { final Seq> actual = of(of(0)); final Seq> expected = of(of(0)); assertThat(transpose(actual)).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldTransposeIfMultiValuedColumn() { final Seq> actual = of(of(0, 1, 2)); final Seq> expected = of(of(0), of(1), of(2)); assertThat(transpose(actual)).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldTransposeIfMultiValuedRow() { final Seq> actual = of(of(0), of(1), of(2)); final Seq> expected = of(of(0, 1, 2)); assertThat(transpose(actual)).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldTransposeIfMultiValuedIfSymmetric() { final Seq> actual = of( of(1, 2, 3), of(4, 5, 6), of(7, 8, 9)); final Seq> expected = of( of(1, 4, 7), of(2, 5, 8), of(3, 6, 9)); assertThat(transpose(actual)).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldTransposeIfMultiValuedWithMoreColumnsThanRows() { final Seq> actual = of( of(1, 2, 3), of(4, 5, 6)); final Seq> expected = of( of(1, 4), of(2, 5), of(3, 6)); assertThat(transpose(actual)).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldTransposeIfMultiValuedWithMoreRowsThanColumns() { final Seq> actual = of( of(1, 2), of(3, 4), of(5, 6)); final Seq> expected = of( of(1, 3, 5), of(2, 4, 6)); assertThat(transpose(actual)).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldBeEqualIfTransposedTwice() { final Seq> actual = of( of(1, 2, 3), of(4, 5, 6)); final Seq> transposed = transpose(actual); assertThat(transpose(transposed)).isEqualTo(actual); } @Test(expected = IllegalArgumentException.class) @SuppressWarnings("unchecked") public void shouldNotTransposeForMissingOrEmptyValues() { final Seq> actual = of( of(), of(0, 1), of(2, 3, 4, 5), of(), of(6, 7, 8)); transpose(actual); } // -- IndexedSeq special cases @Test public void shouldTestIndexedSeqStartsWithNonIndexedSeq() { assertThat(of(1, 3, 4).startsWith(Stream.of(1, 3))).isTrue(); assertThat(of(1, 2, 3, 4).startsWith(Stream.of(1, 2, 4))).isFalse(); assertThat(of(1, 2).startsWith(Stream.of(1, 2, 4))).isFalse(); } @Test public void shouldTestIndexedSeqEndsWithNonIndexedSeq() { assertThat(of(1, 3, 4).endsWith(Stream.of(3, 4))).isTrue(); assertThat(of(1, 2, 3, 4).endsWith(Stream.of(2, 3, 5))).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractSetTest.java000066400000000000000000000175361342074374400257010ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import org.junit.Test; import java.math.BigDecimal; import java.util.Spliterator; public abstract class AbstractSetTest extends AbstractTraversableRangeTest { @Override abstract protected Set empty(); abstract protected Set emptyWithNull(); @Override abstract protected Set of(T element); @SuppressWarnings("unchecked") @Override abstract protected Set of(T... elements); // -- static narrow @Test public void shouldNarrowSet() { final Set doubles = of(1.0d); final Set numbers = Set.narrow(doubles); final int actual = numbers.add(new BigDecimal("2.0")).sum().intValue(); assertThat(actual).isEqualTo(3); } // -- fill(int, Supplier) @Test public void shouldReturnSingleAfterFillWithConstant() { assertThat(fill(17, () -> 7)) .hasSize(1) .isEqualTo(of(7)); } // -- add @Test public void shouldAddNullAndNonNull() { assertThat(emptyWithNull().add(null).add(1)).contains(null, 1); } @Test public void shouldAddNonNullAndNull() { assertThat(emptyWithNull().add(1).add(null)).contains(null, 1); } @Test public void shouldNotAddAnExistingElementTwice() { final Set set = of(new IntMod2(2)); assertThat(set.add(new IntMod2(4))).isSameAs(set); } // -- addAll @Test public void shouldAddAllOfIterable() { assertThat(of(1, 2, 3).addAll(of(2, 3, 4))).isEqualTo(of(1, 2, 3, 4)); } @Test public void shouldReturnSameSetWhenAddAllEmptyToNonEmpty() { final Set set = of(1, 2, 3); assertThat(set.addAll(empty())).isSameAs(set); } @Test public void shouldReturnSameSetWhenAddAllNonEmptyToEmpty() { final Set set = of(1, 2, 3); if (set.isOrdered()) { assertThat(empty().addAll(set)).isEqualTo(set); } else { assertThat(empty().addAll(set)).isSameAs(set); } } @Test public void shouldReturnSameSetWhenAddAllContainedElements() { final Set set = of(1, 2, 3); assertThat(set.addAll(of(1, 2, 3))).isSameAs(set); } // -- diff @Test public void shouldCalculateDifference() { assertThat(of(1, 2, 3).diff(of(2))).isEqualTo(of(1, 3)); assertThat(of(1, 2, 3).diff(of(5))).isEqualTo(of(1, 2, 3)); assertThat(of(1, 2, 3).diff(of(1, 2, 3))).isEqualTo(empty()); } @Test public void shouldReturnSameSetWhenEmptyDiffNonEmpty() { final Set empty = empty(); assertThat(empty.diff(of(1, 2))).isSameAs(empty); } @Test public void shouldReturnSameSetWhenNonEmptyDiffEmpty() { final Set set = of(1, 2); assertThat(set.diff(empty())).isSameAs(set); } // -- equality @Test public void shouldObeyEqualityConstraints() { // sequential collections assertThat(empty().equals(HashSet.empty())).isTrue(); assertThat(of(1).equals(HashSet.of(1))).isTrue(); assertThat(of(1, 2, 3).equals(HashSet.of(1, 2, 3))).isTrue(); assertThat(of(1, 2, 3).equals(HashSet.of(3, 2, 1))).isTrue(); // other classes assertThat(empty().equals(List.empty())).isFalse(); assertThat(empty().equals(HashMap.empty())).isFalse(); assertThat(empty().equals(HashMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(LinkedHashMap.empty())).isFalse(); assertThat(empty().equals(LinkedHashMultimap.withSeq().empty())).isFalse(); assertThat(empty().equals(TreeMap.empty())).isFalse(); assertThat(empty().equals(TreeMultimap.withSeq().empty())).isFalse(); } // -- intersect @Test public void shouldCalculateIntersect() { assertThat(of(1, 2, 3).intersect(of(2))).isEqualTo(of(2)); assertThat(of(1, 2, 3).intersect(of(5))).isEqualTo(empty()); assertThat(of(1, 2, 3).intersect(of(1, 2, 3))).isEqualTo(of(1, 2, 3)); } @Test public void shouldReturnSameSetWhenEmptyIntersectNonEmpty() { final Set empty = empty(); assertThat(empty.intersect(of(1, 2))).isSameAs(empty); } @Test public void shouldReturnSameSetWhenNonEmptyIntersectEmpty() { final Set set = of(1, 2); final Set empty = empty(); if (set.isOrdered()) { assertThat(set.intersect(empty)).isEqualTo(empty); } else { assertThat(set.intersect(empty)).isSameAs(empty); } } // -- map @Test public void shouldMapDistinctElementsToOneElement() { assertThat(of(1, 2, 3).map(i -> 0)).isEqualTo(of(0)); } // -- remove @Test public void shouldRemoveElement() { assertThat(of(1, 2, 3).remove(2)).isEqualTo(of(1, 3)); assertThat(of(1, 2, 3).remove(5)).isEqualTo(of(1, 2, 3)); assertThat(empty().remove(5)).isEqualTo(empty()); } // -- removeAll @Test public void shouldRemoveAllElements() { assertThat(of(1, 2, 3).removeAll(of(2))).isEqualTo(of(1, 3)); assertThat(of(1, 2, 3).removeAll(of(5))).isEqualTo(of(1, 2, 3)); } @Test public void shouldReturnSameSetWhenNonEmptyRemoveAllEmpty() { final Set set = of(1, 2, 3); assertThat(set.removeAll(empty())).isSameAs(set); } @Test public void shouldReturnSameSetWhenEmptyRemoveAllNonEmpty() { final Set empty = empty(); assertThat(empty.removeAll(of(1, 2, 3))).isSameAs(empty); } // -- union @Test public void shouldCalculateUnion() { assertThat(of(1, 2, 3).union(of(2))).isEqualTo(of(1, 2, 3)); assertThat(of(1, 2, 3).union(of(5))).isEqualTo(of(1, 2, 3, 5)); assertThat(of(1, 2, 3).union(of(1, 2, 3))).isEqualTo(of(1, 2, 3)); } @Test public void shouldReturnSameSetWhenEmptyUnionNonEmpty() { final Set set = of(1, 2); if (set.isOrdered()) { assertThat(empty().union(set)).isEqualTo(set); } else { assertThat(empty().union(set)).isSameAs(set); } } @Test public void shouldReturnSameSetWhenNonEmptyUnionEmpty() { final Set set = of(1, 2); assertThat(set.union(empty())).isSameAs(set); } // disabled tests @Override @Test public void shouldBeAwareOfExistingNonUniqueElement() { // sets have only distinct elements } @Override @Test public void shouldReplaceFirstOccurrenceOfNonNilUsingCurrNewWhenMultipleOccurrencesExist() { // sets have only distinct elements } // -- spliterator @Test public void shouldHaveSizedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue(); } @Test public void shouldHaveDistinctSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.DISTINCT)).isTrue(); } @Test public void shouldReturnSizeWhenSpliterator() { assertThat(of(1, 2, 3).spliterator().getExactSizeIfKnown()).isEqualTo(3); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractSortedMapTest.java000066400000000000000000000040741342074374400270350ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import org.junit.Test; import java.math.BigDecimal; import java.util.Spliterator; public abstract class AbstractSortedMapTest extends AbstractMapTest { @Override abstract protected , V> SortedMap mapOf(K k1, V v1); // -- isOrdered @Test public void shouldReturnOrdered() { final Map actual = mapOf(1, "1", 1, "2"); assertThat(actual.isOrdered()).isTrue(); } // -- narrow @Test public void shouldNarrowMap() { final SortedMap int2doubleMap = mapOf(1, 1.0d); final SortedMap number2numberMap = SortedMap.narrow(int2doubleMap); final int actual = number2numberMap.put(2, new BigDecimal("2.0")).values().sum().intValue(); assertThat(actual).isEqualTo(3); } // -- spliterator @Test public void shouldHaveSortedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SORTED)).isTrue(); } @Test public void shouldHaveOrderedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.ORDERED)).isTrue(); } // -- isSequential() @Test public void shouldReturnFalseWhenIsSequentialCalled() { assertThat(of(1, 2, 3).isSequential()).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractSortedSetTest.java000066400000000000000000000124741342074374400270560ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import org.assertj.core.api.Assertions; import org.junit.Ignore; import org.junit.Test; import java.math.BigDecimal; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Spliterator; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.reverseOrder; import static io.vavr.TestComparators.toStringComparator; import static org.assertj.core.api.Assertions.assertThatThrownBy; public abstract class AbstractSortedSetTest extends AbstractSetTest { @Override abstract protected SortedSet empty(); @Override abstract protected SortedSet emptyWithNull(); @Override abstract protected SortedSet of(T element); abstract protected SortedSet of(Comparator comparator, T element); @SuppressWarnings("unchecked") abstract protected SortedSet of(Comparator comparator, T... elements); // -- static narrow @Test public void shouldNarrowSortedSet() { final SortedSet doubles = of(toStringComparator(), 1.0d); final SortedSet numbers = SortedSet.narrow(doubles); final int actual = numbers.add(new BigDecimal("2.0")).sum().intValue(); assertThat(actual).isEqualTo(3); } @Test public void shouldReturnComparator() { assertThat(of(1).comparator()).isNotNull(); } @Override @Test public void shouldPreserveSingletonInstanceOnDeserialization() { // not possible, because the empty instance stores information about the underlying comparator } @Override @Test public void shouldScanWithNonComparable() { // makes no sense because sorted sets contain ordered elements } @Override @Test public void shouldNarrowSet() { // makes no sense because disjoint types share not the same ordering } @Override @Test public void shouldNarrowTraversable() { // makes no sense because disjoint types share not the same ordering } // -- head @Test public void shouldReturnHeadOfNonEmptyHavingNaturalOrder() { assertThat(of(naturalOrder(), 1, 2, 3, 4).head()).isEqualTo(1); } @Test public void shouldReturnHeadOfNonEmptyHavingReversedOrder() { assertThat(of(reverseOrder(), 1, 2, 3, 4).head()).isEqualTo(4); } // -- init @Test public void shouldReturnInitOfNonEmptyHavingNaturalOrder() { assertThat(of(naturalOrder(), 1, 2, 3, 4).init()).isEqualTo(of(naturalOrder(), 1, 2, 3)); } @Test public void shouldReturnInitOfNonEmptyHavingReversedOrder() { assertThat(of(reverseOrder(), 1, 2, 3, 4).init()).isEqualTo(of(naturalOrder(), 2, 3, 4)); } // -- last @Test public void shouldReturnLastOfNonEmptyHavingNaturalOrder() { assertThat(of(naturalOrder(), 1, 2, 3, 4).last()).isEqualTo(4); } @Test public void shouldReturnLastOfNonEmptyHavingReversedOrder() { assertThat(of(reverseOrder(), 1, 2, 3, 4).last()).isEqualTo(1); } // -- tail @Test public void shouldReturnTailOfNonEmptyHavingNaturalOrder() { assertThat(of(naturalOrder(), 1, 2, 3, 4).tail()).isEqualTo(of(naturalOrder(), 2, 3, 4)); } @Test public void shouldReturnTailOfNonEmptyHavingReversedOrder() { assertThat(of(reverseOrder(), 1, 2, 3, 4).tail()).isEqualTo(of(naturalOrder(), 1, 2, 3)); } // -- equals @Test public void shouldBeEqualWhenHavingSameElementsAndDifferentOrder() { final SortedSet set1 = of(naturalOrder(), 1, 2, 3); final SortedSet set2 = of(reverseOrder(), 3, 2, 1); assertThat(set1).isEqualTo(set2); } // -- toSortedSet @Override @Test(expected = ClassCastException.class) @Ignore("SortedSet in test always created with working comparator, and because method toSortedSet() return same object will never throw ClassCastException") public void shouldThrowOnConvertToSortedSetWithoutComparatorOnNonComparable() { super.shouldThrowOnConvertToSortedSetWithoutComparatorOnNonComparable(); } // -- spliterator @Test public void shouldHaveSortedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SORTED)).isTrue(); } @Test public void shouldHaveOrderedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.ORDERED)).isTrue(); } // -- isSequential() @Test public void shouldReturnFalseWhenIsSequentialCalled() { assertThat(of(1, 2, 3).isSequential()).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractTraversableRangeTest.java000066400000000000000000000641221342074374400303660ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import org.junit.Test; public abstract class AbstractTraversableRangeTest extends AbstractTraversableTest { abstract protected Traversable range(char from, char toExclusive); abstract protected Traversable rangeBy(char from, char toExclusive, int step); abstract protected Traversable rangeBy(double from, double toExclusive, double step); abstract protected Traversable range(int from, int toExclusive); abstract protected Traversable rangeBy(int from, int toExclusive, int step); abstract protected Traversable range(long from, long toExclusive); abstract protected Traversable rangeBy(long from, long toExclusive, long step); abstract protected Traversable rangeClosed(char from, char toInclusive); abstract protected Traversable rangeClosedBy(char from, char toInclusive, int step); abstract protected Traversable rangeClosedBy(double from, double toInclusive, double step); abstract protected Traversable rangeClosed(int from, int toInclusive); abstract protected Traversable rangeClosedBy(int from, int toInclusive, int step); abstract protected Traversable rangeClosed(long from, long toInclusive); abstract protected Traversable rangeClosedBy(long from, long toInclusive, long step); // ------------------------------------------------------------------------ // static range, rangeBy, rangeClosed, rangeCloseBy tests // // Basically there are the following tests scenarios: // // * step == 0 // * from == to, step < 0 // * from == to, step > 0 // * from < to, step < 0 // * from < to, step > 0 // * from > to, step < 0 // * from > to, step > 0 // // Additionally we have to test these special cases // (where MIN/MAX may also be NEGATIVE_INFINITY, POSITIVE_INFINITY): // // * from = MAX, to = MAX, step < 0 // * from = MAX, to = MAX, step > 0 // * from = MIN, to = MIN, step < 0 // * from = MIN, to = MIN, step > 0 // * from = MAX - x, to = MAX, step > 0, 0 < x < step // * from = MAX - step, to = MAX, step > 0 // * from = MAX - x, to = MAX, step > 0, x > step // * from = MIN, to = MIN - x, step < 0, 0 > x > step // * from = MIN, to = MIN - step, step < 0 // * from = MIN, to = MIN - x, step < 0, x < step // // All of these scenarios are multiplied with // // * the inclusive and exclusive case // * the with and without step case // // ------------------------------------------------------------------------ // -- static rangeClosed() @Test public void shouldCreateRangeClosedWhereFromIsGreaterThanTo() { assertThat(rangeClosed('b', 'a')).isEmpty(); assertThat(rangeClosed(1, 0)).isEmpty(); assertThat(rangeClosed(1L, 0L)).isEmpty(); } @Test public void shouldCreateRangeClosedWhereFromEqualsTo() { assertThat(rangeClosed('a', 'a')).isEqualTo(of('a')); assertThat(rangeClosed(0, 0)).isEqualTo(of(0)); assertThat(rangeClosed(0L, 0L)).isEqualTo(of(0L)); } @Test public void shouldCreateRangeClosedWhereFromIsLessThanTo() { assertThat(rangeClosed('a', 'c')).isEqualTo(of('a', 'b', 'c')); assertThat(rangeClosed(1, 3)).isEqualTo(of(1, 2, 3)); assertThat(rangeClosed(1L, 3L)).isEqualTo(of(1L, 2L, 3L)); } @Test public void shouldCreateRangeClosedWhereFromAndToEqualMIN_VALUE() { assertThat(rangeClosed(Character.MIN_VALUE, Character.MIN_VALUE)).isEqualTo(of(Character.MIN_VALUE)); assertThat(rangeClosed(Integer.MIN_VALUE, Integer.MIN_VALUE)).isEqualTo(of(Integer.MIN_VALUE)); assertThat(rangeClosed(Long.MIN_VALUE, Long.MIN_VALUE)).isEqualTo(of(Long.MIN_VALUE)); } @Test public void shouldCreateRangeClosedWhereFromAndToEqualMAX_VALUE() { assertThat(rangeClosed(Character.MAX_VALUE, Character.MAX_VALUE)).isEqualTo(of(Character.MAX_VALUE)); assertThat(rangeClosed(Integer.MAX_VALUE, Integer.MAX_VALUE)).isEqualTo(of(Integer.MAX_VALUE)); assertThat(rangeClosed(Long.MAX_VALUE, Long.MAX_VALUE)).isEqualTo(of(Long.MAX_VALUE)); } // -- static rangeClosedBy() @Test public void shouldCreateRangeClosedByWhereFromIsGreaterThanToAndStepWrongDirection() { // char assertThat(rangeClosedBy('b', 'a', 1)).isEmpty(); assertThat(rangeClosedBy('b', 'a', 3)).isEmpty(); assertThat(rangeClosedBy('a', 'b', -1)).isEmpty(); assertThat(rangeClosedBy('a', 'b', -3)).isEmpty(); // double assertThat(rangeClosedBy(1.0, 0.0, 1.0)).isEmpty(); assertThat(rangeClosedBy(1.0, 0.0, 3.0)).isEmpty(); assertThat(rangeClosedBy(0.0, 1.0, -1.0)).isEmpty(); assertThat(rangeClosedBy(0.0, 1.0, -3.0)).isEmpty(); // int assertThat(rangeClosedBy(1, 0, 1)).isEmpty(); assertThat(rangeClosedBy(1, 0, 3)).isEmpty(); assertThat(rangeClosedBy(0, 1, -1)).isEmpty(); assertThat(rangeClosedBy(0, 1, -3)).isEmpty(); // long assertThat(rangeClosedBy(1L, 0L, 1L)).isEmpty(); assertThat(rangeClosedBy(1L, 0L, 3L)).isEmpty(); assertThat(rangeClosedBy(0L, 1L, -1L)).isEmpty(); assertThat(rangeClosedBy(0L, 1L, -3L)).isEmpty(); } @Test public void shouldCreateRangeClosedByWhereFromEqualsTo() { // char assertThat(rangeClosedBy('a', 'a', 1)).isEqualTo(of('a')); assertThat(rangeClosedBy('a', 'a', 3)).isEqualTo(of('a')); assertThat(rangeClosedBy('a', 'a', -1)).isEqualTo(of('a')); assertThat(rangeClosedBy('a', 'a', -3)).isEqualTo(of('a')); // double assertThat(rangeClosedBy(0.0, 0.0, 1.0)).isEqualTo(of(0.0)); assertThat(rangeClosedBy(0.0, 0.0, 3.0)).isEqualTo(of(0.0)); assertThat(rangeClosedBy(0.0, 0.0, -1.0)).isEqualTo(of(0.0)); assertThat(rangeClosedBy(0.0, 0.0, -3.0)).isEqualTo(of(0.0)); // int assertThat(rangeClosedBy(0, 0, 1)).isEqualTo(of(0)); assertThat(rangeClosedBy(0, 0, 3)).isEqualTo(of(0)); assertThat(rangeClosedBy(0, 0, -1)).isEqualTo(of(0)); assertThat(rangeClosedBy(0, 0, -3)).isEqualTo(of(0)); // long assertThat(rangeClosedBy(0L, 0L, 1L)).isEqualTo(of(0L)); assertThat(rangeClosedBy(0L, 0L, 3L)).isEqualTo(of(0L)); assertThat(rangeClosedBy(0L, 0L, -1L)).isEqualTo(of(0L)); assertThat(rangeClosedBy(0L, 0L, -3L)).isEqualTo(of(0L)); } @Test public void shouldCreateRangeClosedByWhereFromIsLessThanToAndStepCorrectDirection() { // char assertThat(rangeClosedBy('a', 'c', 1)).isEqualTo(of('a', 'b', 'c')); assertThat(rangeClosedBy('a', 'e', 2)).isEqualTo(of('a', 'c', 'e')); assertThat(rangeClosedBy('a', 'f', 2)).isEqualTo(of('a', 'c', 'e')); assertThat(rangeClosedBy((char) (Character.MAX_VALUE - 2), Character.MAX_VALUE, 3)).isEqualTo(of((char) (Character.MAX_VALUE - 2))); assertThat(rangeClosedBy((char) (Character.MAX_VALUE - 3), Character.MAX_VALUE, 3)).isEqualTo(of((char) (Character.MAX_VALUE - 3), Character.MAX_VALUE)); assertThat(rangeClosedBy('c', 'a', -1)).isEqualTo(of('c', 'b', 'a')); assertThat(rangeClosedBy('e', 'a', -2)).isEqualTo(of('e', 'c', 'a')); assertThat(rangeClosedBy('e', (char) ('a' - 1), -2)).isEqualTo(of('e', 'c', 'a')); assertThat(rangeClosedBy((char) (Character.MIN_VALUE + 2), Character.MIN_VALUE, -3)).isEqualTo(of((char) (Character.MIN_VALUE + 2))); assertThat(rangeClosedBy((char) (Character.MIN_VALUE + 3), Character.MIN_VALUE, -3)).isEqualTo(of((char) (Character.MIN_VALUE + 3), Character.MIN_VALUE)); // double assertThat(rangeClosedBy(1.0, 3.0, 1.0)).isEqualTo(of(1.0, 2.0, 3.0)); assertThat(rangeClosedBy(1.0, 5.0, 2.0)).isEqualTo(of(1.0, 3.0, 5.0)); assertThat(rangeClosedBy(1.0, 6.0, 2.0)).isEqualTo(of(1.0, 3.0, 5.0)); assertThat(rangeClosedBy(Double.MAX_VALUE - 2.0E307, Double.MAX_VALUE, 3.0E307)).isEqualTo(of(Double.MAX_VALUE - 2.0E307)); assertThat(rangeClosedBy(3.0, 1.0, -1.0)).isEqualTo(of(3.0, 2.0, 1.0)); assertThat(rangeClosedBy(5.0, 1.0, -2.0)).isEqualTo(of(5.0, 3.0, 1.0)); assertThat(rangeClosedBy(5.0, 0.0, -2.0)).isEqualTo(of(5.0, 3.0, 1.0)); assertThat(rangeClosedBy(-Double.MAX_VALUE + 2.0E307, -Double.MAX_VALUE, -3.0E307)).isEqualTo(of(-Double.MAX_VALUE + 2.0E307)); // int assertThat(rangeClosedBy(1, 3, 1)).isEqualTo(of(1, 2, 3)); assertThat(rangeClosedBy(1, 5, 2)).isEqualTo(of(1, 3, 5)); assertThat(rangeClosedBy(1, 6, 2)).isEqualTo(of(1, 3, 5)); assertThat(rangeClosedBy(Integer.MAX_VALUE - 2, Integer.MAX_VALUE, 3)).isEqualTo(of(Integer.MAX_VALUE - 2)); assertThat(rangeClosedBy(Integer.MAX_VALUE - 3, Integer.MAX_VALUE, 3)).isEqualTo(of(Integer.MAX_VALUE - 3, Integer.MAX_VALUE)); assertThat(rangeClosedBy(3, 1, -1)).isEqualTo(of(3, 2, 1)); assertThat(rangeClosedBy(5, 1, -2)).isEqualTo(of(5, 3, 1)); assertThat(rangeClosedBy(5, 0, -2)).isEqualTo(of(5, 3, 1)); assertThat(rangeClosedBy(Integer.MIN_VALUE + 2, Integer.MIN_VALUE, -3)).isEqualTo(of(Integer.MIN_VALUE + 2)); assertThat(rangeClosedBy(Integer.MIN_VALUE + 3, Integer.MIN_VALUE, -3)).isEqualTo(of(Integer.MIN_VALUE + 3, Integer.MIN_VALUE)); // long assertThat(rangeClosedBy(1L, 3L, 1)).isEqualTo(of(1L, 2L, 3L)); assertThat(rangeClosedBy(1L, 5L, 2)).isEqualTo(of(1L, 3L, 5L)); assertThat(rangeClosedBy(1L, 6L, 2)).isEqualTo(of(1L, 3L, 5L)); assertThat(rangeClosedBy(Long.MAX_VALUE - 2, Long.MAX_VALUE, 3)).isEqualTo(of(Long.MAX_VALUE - 2)); assertThat(rangeClosedBy(Long.MAX_VALUE - 3, Long.MAX_VALUE, 3)).isEqualTo(of(Long.MAX_VALUE - 3, Long.MAX_VALUE)); assertThat(rangeClosedBy(3L, 1L, -1)).isEqualTo(of(3L, 2L, 1L)); assertThat(rangeClosedBy(5L, 1L, -2)).isEqualTo(of(5L, 3L, 1L)); assertThat(rangeClosedBy(5L, 0L, -2)).isEqualTo(of(5L, 3L, 1L)); assertThat(rangeClosedBy(Long.MIN_VALUE + 2, Long.MIN_VALUE, -3)).isEqualTo(of(Long.MIN_VALUE + 2)); assertThat(rangeClosedBy(Long.MIN_VALUE + 3, Long.MIN_VALUE, -3)).isEqualTo(of(Long.MIN_VALUE + 3, Long.MIN_VALUE)); } @Test public void shouldCreateRangeClosedByWhereFromAndToEqualMIN_VALUE() { // char assertThat(rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, 1)).isEqualTo(of(Character.MIN_VALUE)); assertThat(rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, 3)).isEqualTo(of(Character.MIN_VALUE)); assertThat(rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, -1)).isEqualTo(of(Character.MIN_VALUE)); assertThat(rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, -3)).isEqualTo(of(Character.MIN_VALUE)); // double assertThat(rangeClosedBy(-Double.MAX_VALUE, -Double.MAX_VALUE, 1)).isEqualTo(of(-Double.MAX_VALUE)); assertThat(rangeClosedBy(-Double.MAX_VALUE, -Double.MAX_VALUE, 3)).isEqualTo(of(-Double.MAX_VALUE)); assertThat(rangeClosedBy(-Double.MAX_VALUE, -Double.MAX_VALUE, -1)).isEqualTo(of(-Double.MAX_VALUE)); assertThat(rangeClosedBy(-Double.MAX_VALUE, -Double.MAX_VALUE, -3)).isEqualTo(of(-Double.MAX_VALUE)); // int assertThat(rangeClosedBy(Integer.MIN_VALUE, Integer.MIN_VALUE, 1)).isEqualTo(of(Integer.MIN_VALUE)); assertThat(rangeClosedBy(Integer.MIN_VALUE, Integer.MIN_VALUE, 3)).isEqualTo(of(Integer.MIN_VALUE)); assertThat(rangeClosedBy(Integer.MIN_VALUE, Integer.MIN_VALUE, -1)).isEqualTo(of(Integer.MIN_VALUE)); assertThat(rangeClosedBy(Integer.MIN_VALUE, Integer.MIN_VALUE, -3)).isEqualTo(of(Integer.MIN_VALUE)); // long assertThat(rangeClosedBy(Long.MIN_VALUE, Long.MIN_VALUE, 1)).isEqualTo(of(Long.MIN_VALUE)); assertThat(rangeClosedBy(Long.MIN_VALUE, Long.MIN_VALUE, 3)).isEqualTo(of(Long.MIN_VALUE)); assertThat(rangeClosedBy(Long.MIN_VALUE, Long.MIN_VALUE, -1)).isEqualTo(of(Long.MIN_VALUE)); assertThat(rangeClosedBy(Long.MIN_VALUE, Long.MIN_VALUE, -3)).isEqualTo(of(Long.MIN_VALUE)); } @Test public void shouldCreateRangeClosedByWhereFromAndToEqualMAX_VALUE() { // char assertThat(rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, 1)).isEqualTo(of(Character.MAX_VALUE)); assertThat(rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, 3)).isEqualTo(of(Character.MAX_VALUE)); assertThat(rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, -1)).isEqualTo(of(Character.MAX_VALUE)); assertThat(rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, -3)).isEqualTo(of(Character.MAX_VALUE)); // double assertThat(rangeClosedBy(Double.MAX_VALUE, Double.MAX_VALUE, 1)).isEqualTo(of(Double.MAX_VALUE)); assertThat(rangeClosedBy(Double.MAX_VALUE, Double.MAX_VALUE, 3)).isEqualTo(of(Double.MAX_VALUE)); assertThat(rangeClosedBy(Double.MAX_VALUE, Double.MAX_VALUE, -1)).isEqualTo(of(Double.MAX_VALUE)); assertThat(rangeClosedBy(Double.MAX_VALUE, Double.MAX_VALUE, -3)).isEqualTo(of(Double.MAX_VALUE)); // int assertThat(rangeClosedBy(Integer.MAX_VALUE, Integer.MAX_VALUE, 1)).isEqualTo(of(Integer.MAX_VALUE)); assertThat(rangeClosedBy(Integer.MAX_VALUE, Integer.MAX_VALUE, 3)).isEqualTo(of(Integer.MAX_VALUE)); assertThat(rangeClosedBy(Integer.MAX_VALUE, Integer.MAX_VALUE, -1)).isEqualTo(of(Integer.MAX_VALUE)); assertThat(rangeClosedBy(Integer.MAX_VALUE, Integer.MAX_VALUE, -3)).isEqualTo(of(Integer.MAX_VALUE)); // long assertThat(rangeClosedBy(Long.MAX_VALUE, Long.MAX_VALUE, 1)).isEqualTo(of(Long.MAX_VALUE)); assertThat(rangeClosedBy(Long.MAX_VALUE, Long.MAX_VALUE, 3)).isEqualTo(of(Long.MAX_VALUE)); assertThat(rangeClosedBy(Long.MAX_VALUE, Long.MAX_VALUE, -1)).isEqualTo(of(Long.MAX_VALUE)); assertThat(rangeClosedBy(Long.MAX_VALUE, Long.MAX_VALUE, -3)).isEqualTo(of(Long.MAX_VALUE)); } // -- static range() @Test public void shouldCreateRangeWhereFromIsGreaterThanTo() { assertThat(range('b', 'a').isEmpty()); assertThat(range(1, 0)).isEmpty(); assertThat(range(1L, 0L)).isEmpty(); } @Test public void shouldCreateRangeWhereFromEqualsTo() { assertThat(range('a', 'a')).isEmpty(); assertThat(range(0, 0)).isEmpty(); assertThat(range(0L, 0L)).isEmpty(); } @Test public void shouldCreateRangeWhereFromIsLessThanTo() { assertThat(range('a', 'c')).isEqualTo(of('a', 'b')); assertThat(range(1, 3)).isEqualTo(of(1, 2)); assertThat(range(1L, 3L)).isEqualTo(of(1L, 2L)); } @Test public void shouldCreateRangeWhereFromAndToEqualMIN_VALUE() { assertThat(range(Character.MIN_VALUE, Character.MIN_VALUE)).isEmpty(); assertThat(range(Integer.MIN_VALUE, Integer.MIN_VALUE)).isEmpty(); assertThat(range(Long.MIN_VALUE, Long.MIN_VALUE)).isEmpty(); } @Test public void shouldCreateRangeWhereFromAndToEqualMAX_VALUE() { assertThat(range(Character.MAX_VALUE, Character.MAX_VALUE)).isEmpty(); assertThat(range(Integer.MAX_VALUE, Integer.MAX_VALUE)).isEmpty(); assertThat(range(Long.MAX_VALUE, Long.MAX_VALUE)).isEmpty(); } // -- static rangeBy() @Test public void shouldCreateRangeByWhereFromIsGreaterThanToAndStepWrongDirection() { // char assertThat(rangeBy('b', 'a', 1)).isEmpty(); assertThat(rangeBy('b', 'a', 3)).isEmpty(); assertThat(rangeBy('a', 'b', -1)).isEmpty(); assertThat(rangeBy('a', 'b', -3)).isEmpty(); // double assertThat(rangeBy(1.0, 0.0, 1.0)).isEmpty(); assertThat(rangeBy(1.0, 0.0, 3.0)).isEmpty(); assertThat(rangeBy(0.0, 1.0, -1.0)).isEmpty(); assertThat(rangeBy(0.0, 1.0, -3.0)).isEmpty(); // int assertThat(rangeBy(1, 0, 1)).isEmpty(); assertThat(rangeBy(1, 0, 3)).isEmpty(); assertThat(rangeBy(0, 1, -1)).isEmpty(); assertThat(rangeBy(0, 1, -3)).isEmpty(); // long assertThat(rangeBy(1L, 0L, 1L)).isEmpty(); assertThat(rangeBy(1L, 0L, 3L)).isEmpty(); assertThat(rangeBy(0L, 1L, -1L)).isEmpty(); assertThat(rangeBy(0L, 1L, -3L)).isEmpty(); } @Test public void shouldCreateRangeByWithBigStep() { // step * (from - toExclusive) < 0 because of overflow // int assertThat(rangeBy(3_721, 2_000_000, 3_721)).isNotEmpty(); // long assertThat(rangeBy(3_221_000L, 200_000_000_000L, 154_221_000L)).isNotEmpty(); } @Test public void shouldCreateRangeByWhereFromEqualsTo() { // char assertThat(rangeBy('a', 'a', 1)).isEmpty(); assertThat(rangeBy('a', 'a', 3)).isEmpty(); assertThat(rangeBy('a', 'a', -1)).isEmpty(); assertThat(rangeBy('a', 'a', -3)).isEmpty(); // double assertThat(rangeBy(0.0, 0.0, 1.0)).isEmpty(); assertThat(rangeBy(0.0, 0.0, 3.0)).isEmpty(); assertThat(rangeBy(0.0, 0.0, -1.0)).isEmpty(); assertThat(rangeBy(0.0, 0.0, -3.0)).isEmpty(); // int assertThat(rangeBy(0, 0, 1)).isEmpty(); assertThat(rangeBy(0, 0, 3)).isEmpty(); assertThat(rangeBy(0, 0, -1)).isEmpty(); assertThat(rangeBy(0, 0, -3)).isEmpty(); // long assertThat(rangeBy(0L, 0L, 1L)).isEmpty(); assertThat(rangeBy(0L, 0L, 3L)).isEmpty(); assertThat(rangeBy(0L, 0L, -1L)).isEmpty(); assertThat(rangeBy(0L, 0L, -3L)).isEmpty(); } @Test public void shouldCreateRangeByWhereFromIsLessThanToAndStepCorrectDirection() { // char assertThat(rangeBy('a', 'c', 1)).isEqualTo(of('a', 'b')); assertThat(rangeBy('a', 'd', 2)).isEqualTo(of('a', 'c')); assertThat(rangeBy('c', 'a', -1)).isEqualTo(of('c', 'b')); assertThat(rangeBy('d', 'a', -2)).isEqualTo(of('d', 'b')); assertThat(rangeBy((char) (Character.MAX_VALUE - 3), Character.MAX_VALUE, 3)).isEqualTo(of((char) (Character.MAX_VALUE - 3))); assertThat(rangeBy((char) (Character.MAX_VALUE - 4), Character.MAX_VALUE, 3)).isEqualTo(of((char) (Character.MAX_VALUE - 4), (char) (Character.MAX_VALUE - 1))); assertThat(rangeBy((char) (Character.MIN_VALUE + 3), Character.MIN_VALUE, -3)).isEqualTo(of((char) (Character.MIN_VALUE + 3))); assertThat(rangeBy((char) (Character.MIN_VALUE + 4), Character.MIN_VALUE, -3)).isEqualTo(of((char) (Character.MIN_VALUE + 4), (char) (Character.MIN_VALUE + 1))); // double assertThat(rangeBy(1.0, 3.0, 1.0)).isEqualTo(of(1.0, 2.0)); assertThat(rangeBy(1.0, 4.0, 2.0)).isEqualTo(of(1.0, 3.0)); assertThat(rangeBy(3.0, 1.0, -1.0)).isEqualTo(of(3.0, 2.0)); assertThat(rangeBy(4.0, 1.0, -2.0)).isEqualTo(of(4.0, 2.0)); assertThat(rangeBy(Double.MAX_VALUE - 3.0E307, Double.MAX_VALUE, 3.0E307)).isEqualTo(of(Double.MAX_VALUE - 3.0E307)); assertThat(rangeBy(-Double.MAX_VALUE + 3.0E307, -Double.MAX_VALUE, -3.0E307)).isEqualTo(of(-Double.MAX_VALUE + 3.0E307)); // int assertThat(rangeBy(1, 3, 1)).isEqualTo(of(1, 2)); assertThat(rangeBy(1, 4, 2)).isEqualTo(of(1, 3)); assertThat(rangeBy(3, 1, -1)).isEqualTo(of(3, 2)); assertThat(rangeBy(4, 1, -2)).isEqualTo(of(4, 2)); assertThat(rangeBy(Integer.MAX_VALUE - 3, Integer.MAX_VALUE, 3)).isEqualTo(of(Integer.MAX_VALUE - 3)); assertThat(rangeBy(Integer.MAX_VALUE - 4, Integer.MAX_VALUE, 3)).isEqualTo(of(Integer.MAX_VALUE - 4, Integer.MAX_VALUE - 1)); assertThat(rangeBy(Integer.MIN_VALUE + 3, Integer.MIN_VALUE, -3)).isEqualTo(of(Integer.MIN_VALUE + 3)); assertThat(rangeBy(Integer.MIN_VALUE + 4, Integer.MIN_VALUE, -3)).isEqualTo(of(Integer.MIN_VALUE + 4, Integer.MIN_VALUE + 1)); // long assertThat(rangeBy(1L, 3L, 1L)).isEqualTo(of(1L, 2L)); assertThat(rangeBy(1L, 4L, 2L)).isEqualTo(of(1L, 3L)); assertThat(rangeBy(3L, 1L, -1L)).isEqualTo(of(3L, 2L)); assertThat(rangeBy(4L, 1L, -2L)).isEqualTo(of(4L, 2L)); assertThat(rangeBy(Long.MAX_VALUE - 3, Long.MAX_VALUE, 3)).isEqualTo(of(Long.MAX_VALUE - 3)); assertThat(rangeBy(Long.MAX_VALUE - 4, Long.MAX_VALUE, 3)).isEqualTo(of(Long.MAX_VALUE - 4, Long.MAX_VALUE - 1)); assertThat(rangeBy(Long.MIN_VALUE + 3, Long.MIN_VALUE, -3)).isEqualTo(of(Long.MIN_VALUE + 3)); assertThat(rangeBy(Long.MIN_VALUE + 4, Long.MIN_VALUE, -3)).isEqualTo(of(Long.MIN_VALUE + 4, Long.MIN_VALUE + 1)); } @Test public void shouldCreateRangeByWhereFromAndToEqualMIN_VALUE() { // char assertThat(rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, 1)).isEmpty(); assertThat(rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, 3)).isEmpty(); assertThat(rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, -1)).isEmpty(); assertThat(rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, -3)).isEmpty(); // double assertThat(rangeBy(-Double.MAX_VALUE, -Double.MAX_VALUE, 1.0)).isEmpty(); assertThat(rangeBy(-Double.MAX_VALUE, -Double.MAX_VALUE, 3.0)).isEmpty(); assertThat(rangeBy(-Double.MAX_VALUE, -Double.MAX_VALUE, -1.0)).isEmpty(); assertThat(rangeBy(-Double.MAX_VALUE, -Double.MAX_VALUE, -3.0)).isEmpty(); // int assertThat(rangeBy(Integer.MIN_VALUE, Integer.MIN_VALUE, 1)).isEmpty(); assertThat(rangeBy(Integer.MIN_VALUE, Integer.MIN_VALUE, 3)).isEmpty(); assertThat(rangeBy(Integer.MIN_VALUE, Integer.MIN_VALUE, -1)).isEmpty(); assertThat(rangeBy(Integer.MIN_VALUE, Integer.MIN_VALUE, -3)).isEmpty(); // long assertThat(rangeBy(Long.MIN_VALUE, Long.MIN_VALUE, 1L)).isEmpty(); assertThat(rangeBy(Long.MIN_VALUE, Long.MIN_VALUE, 3L)).isEmpty(); assertThat(rangeBy(Long.MIN_VALUE, Long.MIN_VALUE, -1L)).isEmpty(); assertThat(rangeBy(Long.MIN_VALUE, Long.MIN_VALUE, -3L)).isEmpty(); } @Test public void shouldCreateRangeByWhereFromAndToEqualMAX_VALUE() { // char assertThat(rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, 1)).isEmpty(); assertThat(rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, 3)).isEmpty(); assertThat(rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, -1)).isEmpty(); assertThat(rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, -3)).isEmpty(); // double assertThat(rangeBy(Double.MAX_VALUE, Double.MAX_VALUE, 1.0)).isEmpty(); assertThat(rangeBy(Double.MAX_VALUE, Double.MAX_VALUE, 3.0)).isEmpty(); assertThat(rangeBy(Double.MAX_VALUE, Double.MAX_VALUE, -1.0)).isEmpty(); assertThat(rangeBy(Double.MAX_VALUE, Double.MAX_VALUE, -3.0)).isEmpty(); // int assertThat(rangeBy(Integer.MAX_VALUE, Integer.MAX_VALUE, 1)).isEmpty(); assertThat(rangeBy(Integer.MAX_VALUE, Integer.MAX_VALUE, 3)).isEmpty(); assertThat(rangeBy(Integer.MAX_VALUE, Integer.MAX_VALUE, -1)).isEmpty(); assertThat(rangeBy(Integer.MAX_VALUE, Integer.MAX_VALUE, -3)).isEmpty(); // long assertThat(rangeBy(Long.MAX_VALUE, Long.MAX_VALUE, 1L)).isEmpty(); assertThat(rangeBy(Long.MAX_VALUE, Long.MAX_VALUE, 3L)).isEmpty(); assertThat(rangeBy(Long.MAX_VALUE, Long.MAX_VALUE, -1L)).isEmpty(); assertThat(rangeBy(Long.MAX_VALUE, Long.MAX_VALUE, -3L)).isEmpty(); } // step == 0 @Test(expected = IllegalArgumentException.class) public void shouldProhibitCharRangeByStepZero() { rangeBy('a', 'b', 0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeByStepZero() { rangeBy(0.0, 1.0, 0.0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitIntRangeByStepZero() { rangeBy(0, 1, 0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitLongRangeByStepZero() { rangeBy(0L, 1L, 0L); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitCharRangeClosedByStepZero() { rangeClosedBy('a', 'b', 0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeClosedByStepZero() { rangeClosedBy(0.0, 1.0, 0.0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitIntRangeClosedByStepZero() { rangeClosedBy(0, 1, 0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitLongRangeClosedByStepZero() { rangeClosedBy(0L, 1L, 0L); } // double special cases @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeClosedByToEqualsNaN() { rangeClosedBy(0.0, Double.NaN, 1.0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeClosedByFromEqualNaN() { rangeClosedBy(Double.NaN, 0.0, 1.0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeClosedByStepEqualNaN() { rangeClosedBy(0.0, 10.0, Double.NaN); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeByToEqualsNaN() { rangeBy(0.0, Double.NaN, 1.0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeByFromEqualNaN() { rangeBy(Double.NaN, 0.0, 1.0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitDoubleRangeByStepEqualNaN() { rangeBy(0.0, 10.0, Double.NaN); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/AbstractTraversableTest.java000066400000000000000000002654711342074374400274230ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import org.junit.Test; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; import static io.vavr.API.*; import static io.vavr.OutputTester.*; import static java.lang.System.lineSeparator; import static java.util.Arrays.asList; import static java.util.Comparator.comparingInt; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; import static org.assertj.core.api.Assertions.within; public abstract class AbstractTraversableTest extends AbstractValueTest { protected final boolean isTraversableAgain() { return empty().isTraversableAgain(); } protected final boolean isOrdered() { return empty().isOrdered(); } protected abstract Collector, ? extends Traversable> collector(); @Override protected abstract Traversable empty(); protected boolean emptyShouldBeSingleton() { return true; } @Override protected abstract Traversable of(T element); @SuppressWarnings("unchecked") @Override protected abstract Traversable of(T... elements); protected abstract Traversable ofAll(Iterable elements); protected abstract > Traversable ofJavaStream(java.util.stream.Stream javaStream); protected abstract Traversable ofAll(boolean... elements); protected abstract Traversable ofAll(byte... elements); protected abstract Traversable ofAll(char... elements); protected abstract Traversable ofAll(double... elements); protected abstract Traversable ofAll(float... elements); protected abstract Traversable ofAll(int... elements); protected abstract Traversable ofAll(long... elements); protected abstract Traversable ofAll(short... elements); protected abstract Traversable tabulate(int n, Function f); protected abstract Traversable fill(int n, Supplier s); // -- static empty() @Test public void shouldCreateNil() { final Traversable actual = empty(); assertThat(actual.length()).isEqualTo(0); } // -- static narrow() @Test public void shouldNarrowTraversable() { final Traversable doubles = of(1.0d); final Traversable numbers = Traversable.narrow(doubles); final boolean actual = numbers.contains(new BigDecimal("2.0")); assertThat(actual).isFalse(); } // -- static of() @Test public void shouldCreateSeqOfSeqUsingCons() { final List> actual = of(List.empty()).toList(); assertThat(actual).isEqualTo(List.of(List.empty())); } // -- static of(T...) @Test public void shouldCreateInstanceOfElements() { final List actual = of(1, 2).toList(); assertThat(actual).isEqualTo(List.of(1, 2)); } // -- static of(Iterable) @Test public void shouldCreateListOfIterable() { final java.util.List arrayList = asList(1, 2); final List actual = ofAll(arrayList).toList(); assertThat(actual).isEqualTo(List.of(1, 2)); } // -- static ofAll(java.util.stream.Stream) @Test public void shouldCreateStreamFromEmptyJavaUtilStream() { final java.util.stream.Stream javaStream = java.util.stream.Stream.empty(); assertThat(ofJavaStream(javaStream)).isEqualTo(empty()); } @Test public void shouldCreateStreamFromNonEmptyJavaUtilStream() { final java.util.stream.Stream javaStream = java.util.stream.Stream.of(1, 2, 3); assertThat(ofJavaStream(javaStream)).isEqualTo(of(1, 2, 3)); } // -- static of() @Test public void shouldCreateListOfPrimitiveBooleanArray() { final Traversable actual = ofAll(true, false); final Traversable expected = of(true, false); assertThat(actual).isEqualTo(expected); } @Test public void shouldCreateListOfPrimitiveByteArray() { final Traversable actual = ofAll((byte) 1, (byte) 2, (byte) 3); final Traversable expected = of((byte) 1, (byte) 2, (byte) 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldCreateListOfPrimitiveCharArray() { final Traversable actual = ofAll('a', 'b', 'c'); final Traversable expected = of('a', 'b', 'c'); assertThat(actual).isEqualTo(expected); } @Test public void shouldCreateListOfPrimitiveDoubleArray() { final Traversable actual = ofAll(1d, 2d, 3d); final Traversable expected = of(1d, 2d, 3d); assertThat(actual).isEqualTo(expected); } @Test public void shouldCreateListOfPrimitiveFloatArray() { final Traversable actual = ofAll(1f, 2f, 3f); final Traversable expected = of(1f, 2f, 3f); assertThat(actual).isEqualTo(expected); } @Test public void shouldCreateListOfPrimitiveIntArray() { final Traversable actual = ofAll(1, 2, 3); final Traversable expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldCreateListOfPrimitiveLongArray() { final Traversable actual = ofAll(1L, 2L, 3L); final Traversable expected = of(1L, 2L, 3L); assertThat(actual).isEqualTo(expected); } @Test public void shouldCreateListOfPrimitiveShortArray() { final Traversable actual = ofAll((short) 1, (short) 2, (short) 3); final Traversable expected = of((short) 1, (short) 2, (short) 3); assertThat(actual).isEqualTo(expected); } // -- average @Test public void shouldReturnNoneWhenComputingAverageOfNil() { assertThat(empty().average()).isEqualTo(Option.none()); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenComputingAverageOfStrings() { of("1", "2", "3").average(); } @Test public void shouldComputeAverageOfByte() { assertThat(of((byte) 1, (byte) 2).average().get()).isEqualTo(1.5); } @Test public void shouldComputeAverageOfDouble() { assertThat(of(.1, .2, .3).average().get()).isEqualTo(.2, within(10e-17)); } @Test public void shouldComputeAverageOfFloat() { assertThat(of(.1f, .2f, .3f).average().get()).isEqualTo(.2, within(10e-9)); } @Test public void shouldComputeAverageOfInt() { assertThat(of(1, 2, 3).average().get()).isEqualTo(2); } @Test public void shouldComputeAverageOfLong() { assertThat(of(1L, 2L, 3L).average().get()).isEqualTo(2); } @Test public void shouldComputeAverageOfShort() { assertThat(of((short) 1, (short) 2, (short) 3).average().get()).isEqualTo(2); } @Test public void shouldComputeAverageOfBigInteger() { assertThat(of(BigInteger.ZERO, BigInteger.ONE).average().get()).isEqualTo(.5); } @Test public void shouldComputeAverageOfBigDecimal() { assertThat(of(BigDecimal.ZERO, BigDecimal.ONE).average().get()).isEqualTo(.5); } @Test public void shouldComputeAverageAndCompensateErrors() { // Kahan's summation algorithm (used by DoubleStream.average()) returns 0.0 (false) // Neumaier's modification of Kahan's algorithm returns 0.75 (correct) assertThat(of(1.0, +10e100, 2.0, -10e100).average().get()).isEqualTo(0.75); } @Test public void shouldCalculateAverageOfDoublesContainingNaN() { assertThat(of(1.0, Double.NaN, 2.0).average().get()).isEqualTo(Double.NaN); } @Test public void shouldCalculateAverageOfFloatsContainingNaN() { assertThat(of(1.0f, Float.NaN, 2.0f).average().get()).isEqualTo(Float.NaN); } @Test public void shouldCalculateAverageOfDoubleAndFloat() { assertThat(this. of(1.0, 1.0f).average().get()).isEqualTo(1.0); } @Test public void shouldCalculateAverageOfDoublePositiveAndNegativeInfinity() { assertThat(of(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY).average().get()).isEqualTo(Double.NaN); } @Test public void shouldCalculateAverageOfFloatPositiveAndNegativeInfinity() { assertThat(of(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY).average().get()).isEqualTo(Float.NaN); } // -- collect @Test public void shouldThrowOnCollectWhenPartialFunctionIsNull() { assertThatThrownBy(() -> empty().collect((PartialFunction) null)) .isExactlyInstanceOf(NullPointerException.class) .hasMessage("partialFunction is null"); } @Test public void shouldCollectUsingPartialFunction() { final PartialFunction pf = new PartialFunction() { private static final long serialVersionUID = 1L; @Override public String apply(Integer i) { return String.valueOf(i); } @Override public boolean isDefinedAt(Integer i) { return i % 2 == 1; } }; final Traversable actual = of(1, 2, 3).collect(pf); assertThat(actual).isEqualTo(of("1", "3")); } @Test public void shouldCollectUsingCase() { final Traversable actual = of(1, 2, 3).collect( Case($(i -> i % 2 == 1), String::valueOf) ); assertThat(actual).isEqualTo(of("1", "3")); } @Test public void shouldCollectUsingMap() { final Map map = Map(1, "one", 3, "three"); final Traversable actual = of(1, 2, 3, 4).collect(map.asPartialFunction()); assertThat(actual).isEqualTo(of("one", "three")); } @SuppressWarnings("unchecked") @Test public void shouldCollectUsingMultimap() { if (!isOrdered()) { final Multimap map = HashMultimap.withSeq().of(1, "one", 1, "un", 3, "three", 3, "trois"); final Traversable> actual = of(1, 2, 3, 4).collect(map.asPartialFunction()); assertThat(actual).isEqualTo(of(List("one", "un"), List("three", "trois"))); } } @Test public void shouldCollectUsingSeq() { final Seq map = List("one", "two", "three", "four"); final Traversable actual = of(0, 2).collect(map.asPartialFunction()); assertThat(actual).isEqualTo(of("one", "three")); } // -- contains @Test public void shouldRecognizeNilContainsNoElement() { final boolean actual = empty().contains(null); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilDoesNotContainElement() { final boolean actual = of(1, 2, 3).contains(0); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilDoesContainElement() { final boolean actual = of(1, 2, 3).contains(2); assertThat(actual).isTrue(); } // -- containsAll @Test public void shouldHandleDuplicates() { final boolean actual = of(1, 2, 3, 2, 3, 1).containsAll(of(1, 2, 2)); assertThat(actual).isTrue(); } @Test public void shouldRecognizeNilNotContainsAllElements() { final boolean actual = empty().containsAll(of(1, 2, 3)); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilNotContainsAllOverlappingElements() { final boolean actual = of(1, 2, 3).containsAll(of(2, 3, 4)); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilContainsAllOnSelf() { final boolean actual = of(1, 2, 3).containsAll(of(1, 2, 3)); assertThat(actual).isTrue(); } // -- count @Test public void shouldCountWhenIsEmpty() { assertThat(empty().count(ignored -> true)).isEqualTo(0); } @Test public void shouldCountWhenNoneSatisfiesThePredicate() { assertThat(of(1, 2, 3).count(ignored -> false)).isEqualTo(0); } @Test public void shouldCountWhenAllSatisfyThePredicate() { assertThat(of(1, 2, 3).count(ignored -> true)).isEqualTo(3); } @Test public void shouldCountWhenSomeSatisfyThePredicate() { assertThat(of(1, 2, 3).count(i -> i % 2 == 0)).isEqualTo(1); } // -- distinct @Test public void shouldComputeDistinctOfEmptyTraversable() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().distinct()).isEqualTo(empty()); } else { assertThat(empty().distinct()).isSameAs(empty()); } } @Test public void shouldComputeDistinctOfNonEmptyTraversable() { final Traversable testee = of(1, 1, 2, 2, 3, 3); final Traversable actual = testee.distinct(); final Traversable expected = of(1, 2, 3); assertThat(actual).isEqualTo(expected); if (testee.isDistinct()) { assertThat(actual).isSameAs(testee); } } // -- distinctBy(Comparator) @Test public void shouldComputeDistinctByOfEmptyTraversableUsingComparator() { final Comparator comparator = comparingInt(i -> i); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(this. empty().distinctBy(comparator)).isEqualTo(empty()); } else { assertThat(this. empty().distinctBy(comparator)).isSameAs(empty()); } } @Test public void shouldComputeDistinctByOfNonEmptyTraversableUsingComparator() { final Comparator comparator = comparingInt(s -> (s.charAt(1))); final Traversable distinct = of("1a", "2a", "3a", "3b", "4b", "5c").distinctBy(comparator).map(s -> s.substring(1)); assertThat(distinct).isEqualTo(of("a", "b", "c")); } @Test public void shouldReturnSameInstanceWhenDistinctByComparatorEmptyTraversable() { final Traversable empty = empty(); assertThat(empty.distinctBy(Comparators.naturalComparator())).isSameAs(empty); } // -- distinctBy(Function) @Test public void shouldComputeDistinctByOfEmptyTraversableUsingKeyExtractor() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().distinctBy(Function.identity())).isEqualTo(empty()); } else { assertThat(empty().distinctBy(Function.identity())).isSameAs(empty()); } } @Test public void shouldComputeDistinctByOfNonEmptyTraversableUsingKeyExtractor() { final Function function = c -> c.charAt(1); final Traversable distinct = of("1a", "2a", "3a", "3b", "4b", "5c").distinctBy(function).map(s -> s.substring(1)); assertThat(distinct).isEqualTo(of("a", "b", "c")); } @Test public void shouldReturnSameInstanceWhenDistinctByFunctionEmptyTraversable() { final Traversable empty = empty(); assertThat(empty.distinctBy(Function.identity())).isSameAs(empty); } // -- drop @Test public void shouldDropNoneOnNil() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().drop(1)).isEqualTo(empty()); } else { assertThat(empty().drop(1)).isSameAs(empty()); } } @Test public void shouldDropNoneIfCountIsNegative() { assertThat(of(1, 2, 3).drop(-1)).isEqualTo(of(1, 2, 3)); } @Test public void shouldDropAsExpectedIfCountIsLessThanSize() { assertThat(of(1, 2, 3).drop(2)).isEqualTo(of(3)); } @Test public void shouldDropAllIfCountExceedsSize() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).drop(4)).isEqualTo(empty()); } else { assertThat(of(1, 2, 3).drop(4)).isSameAs(empty()); } } @Test public void shouldReturnSameInstanceWhenDropZeroCount() { final Traversable t = of(1, 2, 3); assertThat(t.drop(0)).isSameAs(t); } @Test public void shouldReturnSameInstanceWhenDropNegativeCount() { final Traversable t = of(1, 2, 3); assertThat(t.drop(-1)).isSameAs(t); } @Test public void shouldReturnSameInstanceWhenEmptyDropOne() { final Traversable empty = empty(); assertThat(empty.drop(1)).isSameAs(empty); } // -- dropRight @Test public void shouldDropRightNoneOnNil() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().dropRight(1)).isEqualTo(empty()); } else { assertThat(empty().dropRight(1)).isSameAs(empty()); } } @Test public void shouldDropRightNoneIfCountIsNegative() { assertThat(of(1, 2, 3).dropRight(-1)).isEqualTo(of(1, 2, 3)); } @Test public void shouldDropRightAsExpectedIfCountIsLessThanSize() { assertThat(of(1, 2, 3).dropRight(2)).isEqualTo(of(1)); } @Test public void shouldDropRightAllIfCountExceedsSize() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).dropRight(4)).isEqualTo(empty()); } else { assertThat(of(1, 2, 3).dropRight(4)).isSameAs(empty()); } } @Test public void shouldReturnSameInstanceWhenDropRightZeroCount() { final Traversable t = of(1, 2, 3); assertThat(t.dropRight(0)).isSameAs(t); } @Test public void shouldReturnSameInstanceWhenDropRightNegativeCount() { final Traversable t = of(1, 2, 3); assertThat(t.dropRight(-1)).isSameAs(t); } @Test public void shouldReturnSameInstanceWhenEmptyDropRightOne() { final Traversable empty = empty(); assertThat(empty.dropRight(1)).isSameAs(empty); } // -- dropUntil @Test public void shouldDropUntilNoneOnNil() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().dropUntil(ignored -> true)).isEqualTo(empty()); } else { assertThat(empty().dropUntil(ignored -> true)).isSameAs(empty()); } } @Test public void shouldDropUntilNoneIfPredicateIsTrue() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).dropUntil(ignored -> true)).isEqualTo(of(1, 2, 3)); } else { final Traversable t = of(1, 2, 3); assertThat(t.dropUntil(ignored -> true)).isSameAs(t); } } @Test public void shouldDropUntilAllIfPredicateIsFalse() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).dropUntil(ignored -> false)).isEqualTo(empty()); } else { assertThat(of(1, 2, 3).dropUntil(ignored -> false)).isSameAs(empty()); } } @Test public void shouldDropUntilCorrect() { assertThat(of(1, 2, 3).dropUntil(i -> i >= 2)).isEqualTo(of(2, 3)); } @Test public void shouldReturnSameInstanceWhenEmptyDropUntil() { final Traversable empty = empty(); assertThat(empty.dropUntil(ignored -> true)).isSameAs(empty); } // -- dropWhile @Test public void shouldDropWhileNoneOnNil() { final Traversable empty = empty(); final Traversable actual = empty.dropWhile(ignored -> true); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(actual).isEqualTo(empty); } else { assertThat(actual).isSameAs(empty); } } @Test public void shouldDropWhileNoneIfPredicateIsFalse() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).dropWhile(ignored -> false)).isEqualTo(of(1, 2, 3)); } else { final Traversable t = of(1, 2, 3); assertThat(t.dropWhile(ignored -> false)).isSameAs(t); } } @Test public void shouldDropWhileAllIfPredicateIsTrue() { final Traversable actual = of(1, 2, 3).dropWhile(ignored -> true); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(actual).isEqualTo(empty()); } else { assertThat(actual).isSameAs(empty()); } } @Test public void shouldDropWhileAccordingToPredicate() { assertThat(of(1, 2, 3).dropWhile(i -> i < 2)).isEqualTo(of(2, 3)); } @Test public void shouldDropWhileAndNotTruncate() { assertThat(of(1, 2, 3).dropWhile(i -> i % 2 == 1)).isEqualTo(of(2, 3)); } @Test public void shouldReturnSameInstanceWhenEmptyDropWhile() { final Traversable empty = empty(); assertThat(empty.dropWhile(ignored -> true)).isSameAs(empty); } // -- existsUnique @Test public void shouldBeAwareOfExistingUniqueElement() { assertThat(of(1, 2).existsUnique(i -> i == 1)).isTrue(); } @Test public void shouldBeAwareOfNonExistingUniqueElement() { assertThat(this. empty().existsUnique(i -> i == 1)).isFalse(); } @Test public void shouldBeAwareOfExistingNonUniqueElement() { assertThat(of(1, 1, 2).existsUnique(i -> i == 1)).isFalse(); } // -- filter @Test public void shouldFilterExistingElements() { assertThat(of(1, 2, 3).filter(i -> i == 1)).isEqualTo(of(1)); assertThat(of(1, 2, 3).filter(i -> i == 2)).isEqualTo(of(2)); assertThat(of(1, 2, 3).filter(i -> i == 3)).isEqualTo(of(3)); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).filter(ignore -> true)).isEqualTo(of(1, 2, 3)); } else { final Traversable t = of(1, 2, 3); assertThat(t.filter(ignore -> true)).isSameAs(t); } } @Test public void shouldFilterNonExistingElements() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(this. empty().filter(i -> i == 0)).isEqualTo(empty()); assertThat(of(1, 2, 3).filter(i -> i == 0)).isEqualTo(empty()); } else { assertThat(this. empty().filter(i -> i == 0)).isSameAs(empty()); assertThat(of(1, 2, 3).filter(i -> i == 0)).isSameAs(empty()); } } @Test public void shouldReturnSameInstanceWhenFilteringEmptyTraversable() { final Traversable empty = empty(); assertThat(empty.filter(v -> true)).isSameAs(empty); } // -- reject @Test public void shouldRejectExistingElements() { assertThat(of(1, 2, 3).reject(i -> i == 1)).isEqualTo(of(2, 3)); assertThat(of(1, 2, 3).reject(i -> i == 2)).isEqualTo(of(1, 3)); assertThat(of(1, 2, 3).reject(i -> i == 3)).isEqualTo(of(1, 2)); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).reject(ignore -> false)).isEqualTo(of(1, 2, 3)); } else { final Traversable t = of(1, 2, 3); assertThat(t.reject(ignore -> false)).isSameAs(t); } } @Test public void shouldRejectNonExistingElements() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(this. empty().reject(i -> i == 0)).isEqualTo(empty()); assertThat(of(1, 2, 3).reject(i -> i > 0)).isEqualTo(empty()); } else { assertThat(this. empty().reject(i -> i == 0)).isSameAs(empty()); assertThat(of(1, 2, 3).reject(i -> i > 0)).isSameAs(empty()); } } @Test public void shouldReturnSameInstanceWhenRejectingEmptyTraversable() { final Traversable empty = empty(); assertThat(empty.reject(v -> true)).isSameAs(empty); } // -- find @Test public void shouldFindFirstOfNil() { assertThat(empty().find(ignored -> true)).isEqualTo(Option.none()); } @Test public void shouldFindFirstOfNonNil() { assertThat(of(1, 2, 3, 4).find(i -> i % 2 == 0)).isEqualTo(Option.of(2)); } // -- findLast @Test public void shouldFindLastOfNil() { assertThat(empty().findLast(ignored -> true)).isEqualTo(Option.none()); } @Test public void shouldFindLastOfNonNil() { assertThat(of(1, 2, 3, 4).findLast(i -> i % 2 == 0)).isEqualTo(Option.of(4)); } // -- flatMap @Test public void shouldFlatMapEmpty() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().flatMap(v -> of(v, 0))).isEqualTo(empty()); } else { assertThat(empty().flatMap(v -> of(v, 0))).isSameAs(empty()); } } @Test public void shouldFlatMapNonEmpty() { assertThat(of(1, 2, 3).flatMap(v -> of(v, 0))).isEqualTo(of(1, 0, 2, 0, 3, 0)); } // -- fold @Test public void shouldFoldNil() { assertThat(this. empty().fold("", (a, b) -> a + b)).isEqualTo(""); } @Test(expected = NullPointerException.class) public void shouldThrowWhenFoldNullOperator() { this. empty().fold(null, null); } @Test public void shouldFoldSingleElement() { assertThat(of(1).fold(0, (a, b) -> a + b)).isEqualTo(1); } @Test public void shouldFoldMultipleElements() { assertThat(of(1, 2, 3).fold(0, (a, b) -> a + b)).isEqualTo(6); } // -- foldLeft @Test public void shouldFoldLeftNil() { assertThat(this. empty().foldLeft("", (xs, x) -> xs + x)).isEqualTo(""); } @Test(expected = NullPointerException.class) public void shouldThrowWhenFoldLeftNullOperator() { this. empty().foldLeft(null, null); } @Test public void shouldFoldLeftNonNil() { assertThat(of("a", "b", "c").foldLeft("!", (xs, x) -> xs + x)).isEqualTo("!abc"); } // -- foldRight @Test public void shouldFoldRightNil() { assertThat(this. empty().foldRight("", (x, xs) -> x + xs)).isEqualTo(""); } @Test(expected = NullPointerException.class) public void shouldThrowWhenFoldRightNullOperator() { this. empty().foldRight(null, null); } @Test public void shouldFoldRightNonNil() { assertThat(of("a", "b", "c").foldRight("!", (x, xs) -> x + xs)).isEqualTo("abc!"); } // -- forEachWithIndex @Test public void shouldConsumeNoElementWithIndexWhenEmpty() { final boolean[] actual = { false }; final boolean[] expected = { false }; empty().forEachWithIndex((chr, index) -> actual[0] = true); assertThat(actual).isEqualTo(expected); } @Test public void shouldConsumeEachElementWithIndexWhenNonEmpty() { final java.util.List> actual = new java.util.ArrayList<>(); final java.util.List> expected = Arrays.asList(Tuple.of('a', 0), Tuple.of('b', 1), Tuple.of('c', 2)); ofAll('a', 'b', 'c').forEachWithIndex((chr, index) -> actual.add(Tuple.of(chr, index))); assertThat(actual).isEqualTo(expected); } // -- groupBy @Test public void shouldNilGroupBy() { assertThat(empty().groupBy(Function.identity())).isEqualTo(LinkedHashMap.empty()); } @Test public void shouldNonNilGroupByIdentity() { final Map actual = of('a', 'b', 'c').groupBy(Function.identity()); final Map expected = LinkedHashMap.empty().put('a', of('a')).put('b', of('b')).put('c', of('c')); assertThat(actual).isEqualTo(expected); } @Test public void shouldNonNilGroupByEqual() { final Map actual = of('a', 'b', 'c').groupBy(c -> 1); final Map expected = LinkedHashMap.empty().put(1, of('a', 'b', 'c')); assertThat(actual).isEqualTo(expected); } // -- arrangeBy @Test public void shouldNilArrangeBy() { assertThat(empty().arrangeBy(Function.identity())).isEqualTo(Option.of(LinkedHashMap.empty())); } @Test public void shouldNonNilArrangeByIdentity() { final Option> actual = of('a', 'b', 'c').arrangeBy(Function.identity()); final Option> expected = Option.of(LinkedHashMap.empty().put('a', 'a').put('b', 'b').put('c', 'c')); assertThat(actual).isEqualTo(expected); } @Test public void shouldNonNilArrangeByEqual() { final Option> actual = of('a', 'b', 'c').arrangeBy(c -> 1); final Option> expected = Option.none(); assertThat(actual).isEqualTo(expected); } // -- grouped @Test public void shouldGroupedNil() { assertThat(empty().grouped(1).isEmpty()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenGroupedWithSizeZero() { empty().grouped(0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenGroupedWithNegativeSize() { empty().grouped(-1); } @Test public void shouldGroupedTraversableWithEqualSizedBlocks() { final List> actual = of(1, 2, 3, 4).grouped(2).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2), io.vavr.collection.Vector.of(3, 4)); assertThat(actual).isEqualTo(expected); } @Test public void shouldGroupedTraversableWithRemainder() { final List> actual = of(1, 2, 3, 4, 5).grouped(2).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2), io.vavr.collection.Vector.of(3, 4), io.vavr.collection.Vector.of(5)); assertThat(actual).isEqualTo(expected); } @Test public void shouldGroupedWhenTraversableLengthIsSmallerThanBlockSize() { final List> actual = of(1, 2, 3, 4).grouped(5).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2, 3, 4)); assertThat(actual).isEqualTo(expected); } // -- hasDefiniteSize @Test public void shouldReturnSomethingOnHasDefiniteSize() { empty().hasDefiniteSize(); } // -- head @Test(expected = NoSuchElementException.class) public void shouldThrowWhenHeadOnNil() { empty().head(); } @Test public void shouldReturnHeadOfNonNil() { assertThat(of(1, 2, 3).head()).isEqualTo(1); } // -- headOption @Test public void shouldReturnNoneWhenCallingHeadOptionOnNil() { assertThat(empty().headOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeHeadWhenCallingHeadOptionOnNonNil() { assertThat(of(1, 2, 3).headOption()).isEqualTo(Option.some(1)); } // -- init @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenInitOfNil() { empty().init().get(); } @Test public void shouldGetInitOfNonNil() { assertThat(of(1, 2, 3).init()).isEqualTo(of(1, 2)); } // -- initOption @Test public void shouldReturnNoneWhenCallingInitOptionOnNil() { assertThat(empty().initOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeInitWhenCallingInitOptionOnNonNil() { assertThat(of(1, 2, 3).initOption()).isEqualTo(Option.some(of(1, 2))); } // -- isEmpty @Test public void shouldRecognizeNil() { assertThat(empty().isEmpty()).isTrue(); } @Test public void shouldRecognizeNonNil() { assertThat(of(1).isEmpty()).isFalse(); } // -- iterator @Test public void shouldNotHasNextWhenNilIterator() { assertThat(empty().iterator().hasNext()).isFalse(); } @Test(expected = NoSuchElementException.class) public void shouldThrowOnNextWhenNilIterator() { empty().iterator().next(); } @Test public void shouldIterateFirstElementOfNonNil() { assertThat(of(1, 2, 3).iterator().next()).isEqualTo(1); } @Test public void shouldFullyIterateNonNil() { final io.vavr.collection.Iterator iterator = of(1, 2, 3).iterator(); int actual; for (int i = 1; i <= 3; i++) { actual = iterator.next(); assertThat(actual).isEqualTo(i); } assertThat(iterator.hasNext()).isFalse(); } @Test public void shouldThrowWhenCallingNextOnEmptyIterator() { assertThatThrownBy(() -> empty().iterator().next()).isInstanceOf(NoSuchElementException.class); } @Test public void shouldThrowWhenCallingNextTooOftenOnNonEmptyIterator() { final io.vavr.collection.Iterator iterator = of(1).iterator(); assertThatThrownBy(() -> { iterator.next(); iterator.next(); }).isInstanceOf(NoSuchElementException.class); } // -- mkString() @Test public void shouldMkStringNil() { assertThat(empty().mkString()).isEqualTo(""); } @Test public void shouldMkStringNonNil() { assertThat(of('a', 'b', 'c').mkString()).isEqualTo("abc"); } // -- mkString(delimiter) @Test public void shouldMkStringWithDelimiterNil() { assertThat(empty().mkString(",")).isEqualTo(""); } @Test public void shouldMkStringWithDelimiterNonNil() { assertThat(of('a', 'b', 'c').mkString(",")).isEqualTo("a,b,c"); } // -- mkString(delimiter, prefix, suffix) @Test public void shouldMkStringWithDelimiterAndPrefixAndSuffixNil() { assertThat(empty().mkString("[", ",", "]")).isEqualTo("[]"); } @Test public void shouldMkStringWithDelimiterAndPrefixAndSuffixNonNil() { assertThat(of('a', 'b', 'c').mkString("[", ",", "]")).isEqualTo("[a,b,c]"); } // -- mkCharSeq() @Test public void shouldMkCharSeqNil() { assertThat(empty().mkCharSeq()).isEqualTo(CharSeq.empty()); } @Test public void shouldMkCharSeqNonNil() { assertThat(of('a', 'b', 'c').mkCharSeq()).isEqualTo(CharSeq.of("abc")); } // -- mkCharSeq(delimiter) @Test public void shouldMkCharSeqWithDelimiterNil() { assertThat(empty().mkCharSeq(",")).isEqualTo(CharSeq.empty()); } @Test public void shouldMkCharSeqWithDelimiterNonNil() { assertThat(of('a', 'b', 'c').mkCharSeq(",")).isEqualTo(CharSeq.of("a,b,c")); } // -- mkCharSeq(delimiter, prefix, suffix) @Test public void shouldMkCharSeqWithDelimiterAndPrefixAndSuffixNil() { assertThat(empty().mkCharSeq("[", ",", "]")).isEqualTo(CharSeq.of("[]")); } @Test public void shouldMkCharSeqWithDelimiterAndPrefixAndSuffixNonNil() { assertThat(of('a', 'b', 'c').mkCharSeq("[", ",", "]")).isEqualTo(CharSeq.of("[a,b,c]")); } // -- last @Test(expected = NoSuchElementException.class) public void shouldThrowWhenLastOnNil() { empty().last(); } @Test public void shouldReturnLastOfNonNil() { assertThat(of(1, 2, 3).last()).isEqualTo(3); } // -- lastOption @Test public void shouldReturnNoneWhenCallingLastOptionOnNil() { assertThat(empty().lastOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeLastWhenCallingLastOptionOnNonNil() { assertThat(of(1, 2, 3).lastOption()).isEqualTo(Option.some(3)); } // -- length @Test public void shouldComputeLengthOfNil() { assertThat(empty().length()).isEqualTo(0); } @Test public void shouldComputeLengthOfNonNil() { assertThat(of(1, 2, 3).length()).isEqualTo(3); } // -- max @Test public void shouldReturnNoneWhenComputingMaxOfNil() { assertThat(empty().max()).isEqualTo(Option.none()); } @Test public void shouldComputeMaxOfOneValue() { assertThat(of(5).max()).isEqualTo(Option.some(5)); } @Test public void shouldComputeMaxOfStrings() { assertThat(of("1", "2", "3").max()).isEqualTo(Option.some("3")); } @Test public void shouldComputeMaxOfBoolean() { assertThat(of(true, false).max()).isEqualTo(Option.some(true)); } @Test public void shouldComputeMaxOfByte() { assertThat(of((byte) 1, (byte) 2).max()).isEqualTo(Option.some((byte) 2)); } @Test public void shouldComputeMaxOfChar() { assertThat(of('a', 'b', 'c').max()).isEqualTo(Option.some('c')); } @Test public void shouldComputeMaxOfDouble() { assertThat(of(.1, .2, .3).max()).isEqualTo(Option.some(.3)); } @Test public void shouldComputeMaxOfFloat() { assertThat(of(.1f, .2f, .3f).max()).isEqualTo(Option.some(.3f)); } @Test public void shouldComputeMaxOfInt() { assertThat(of(1, 2, 3).max()).isEqualTo(Option.some(3)); } @Test public void shouldComputeMaxOfLong() { assertThat(of(1L, 2L, 3L).max()).isEqualTo(Option.some(3L)); } @Test public void shouldComputeMaxOfShort() { assertThat(of((short) 1, (short) 2, (short) 3).max()).isEqualTo(Option.some((short) 3)); } @Test public void shouldComputeMaxOfBigInteger() { assertThat(of(BigInteger.ZERO, BigInteger.ONE).max()).isEqualTo(Option.some(BigInteger.ONE)); } @Test public void shouldComputeMaxOfBigDecimal() { assertThat(of(BigDecimal.ZERO, BigDecimal.ONE).max()).isEqualTo(Option.some(BigDecimal.ONE)); } @Test(expected = NullPointerException.class) public void shouldThrowNPEWhenMaxOfNullAndInt() { of(null, 1).max(); } @Test(expected = NullPointerException.class) public void shouldThrowNPEWhenMaxOfIntAndNull() { of(1, null).max(); } @Test public void shouldCalculateMaxOfDoublesContainingNaN() { assertThat(of(1.0, Double.NaN, 2.0).max().get()).isEqualTo(Double.NaN); } @Test public void shouldCalculateMaxOfFloatsContainingNaN() { assertThat(of(1.0f, Float.NaN, 2.0f).max().get()).isEqualTo(Float.NaN); } @Test public void shouldThrowClassCastExceptionWhenTryingToCalculateMaxOfDoubleAndFloat() { assertThatThrownBy(() -> this. of(1.0, 1.0f).max()).isInstanceOf(ClassCastException.class); } @Test public void shouldCalculateMaxOfDoublePositiveAndNegativeInfinity() { assertThat(of(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY).max().get()).isEqualTo(Double.POSITIVE_INFINITY); } @Test public void shouldCalculateMaxOfFloatPositiveAndNegativeInfinity() { assertThat(of(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY).max().get()).isEqualTo(Float.POSITIVE_INFINITY); } // -- maxBy(Comparator) @Test(expected = NullPointerException.class) public void shouldThrowWhenMaxByWithNullComparator() { of(1).maxBy((Comparator) null); } @Test public void shouldThrowWhenMaxByOfNil() { assertThat(empty().maxBy((o1, o2) -> 0)).isEqualTo(Option.none()); } @Test public void shouldCalculateMaxByOfInts() { assertThat(of(1, 2, 3).maxBy(comparingInt(i -> i))).isEqualTo(Option.some(3)); } @Test public void shouldCalculateInverseMaxByOfInts() { assertThat(of(1, 2, 3).maxBy((i1, i2) -> i2 - i1)).isEqualTo(Option.some(1)); } // -- maxBy(Function) @Test(expected = NullPointerException.class) public void shouldThrowWhenMaxByWithNullFunction() { of(1).maxBy((Function) null); } @Test public void shouldThrowWhenMaxByFunctionOfNil() { assertThat(this. empty().maxBy(i -> i)).isEqualTo(Option.none()); } @Test public void shouldCalculateMaxByFunctionOfInts() { assertThat(of(1, 2, 3).maxBy(i -> i)).isEqualTo(Option.some(3)); } @Test public void shouldCalculateInverseMaxByFunctionOfInts() { assertThat(of(1, 2, 3).maxBy(i -> -i)).isEqualTo(Option.some(1)); } @Test public void shouldCallMaxFunctionOncePerElement() { final int[] cnt = { 0 }; assertThat(of(1, 2, 3).maxBy(i -> { cnt[0]++; return i; })).isEqualTo(Option.some(3)); assertThat(cnt[0]).isEqualTo(3); } // -- min @Test public void shouldReturnNoneWhenComputingMinOfNil() { assertThat(empty().min()).isEqualTo(Option.none()); } @Test public void shouldComputeMinOfOneValue() { assertThat(of(5).min()).isEqualTo(Option.some(5)); } @Test public void shouldComputeMinOfStrings() { assertThat(of("1", "2", "3").min()).isEqualTo(Option.some("1")); } @Test public void shouldComputeMinOfBoolean() { assertThat(of(true, false).min()).isEqualTo(Option.some(false)); } @Test public void shouldComputeMinOfByte() { assertThat(of((byte) 1, (byte) 2).min()).isEqualTo(Option.some((byte) 1)); } @Test public void shouldComputeMinOfChar() { assertThat(of('a', 'b', 'c').min()).isEqualTo(Option.some('a')); } @Test public void shouldComputeMinOfDouble() { assertThat(of(.1, .2, .3).min()).isEqualTo(Option.some(.1)); } @Test public void shouldComputeMinOfFloat() { assertThat(of(.1f, .2f, .3f).min()).isEqualTo(Option.some(.1f)); } @Test public void shouldComputeMinOfInt() { assertThat(of(1, 2, 3).min()).isEqualTo(Option.some(1)); } @Test public void shouldComputeMinOfLong() { assertThat(of(1L, 2L, 3L).min()).isEqualTo(Option.some(1L)); } @Test public void shouldComputeMinOfShort() { assertThat(of((short) 1, (short) 2, (short) 3).min()).isEqualTo(Option.some((short) 1)); } @Test public void shouldComputeMinOfBigInteger() { assertThat(of(BigInteger.ZERO, BigInteger.ONE).min()).isEqualTo(Option.some(BigInteger.ZERO)); } @Test public void shouldComputeMinOfBigDecimal() { assertThat(of(BigDecimal.ZERO, BigDecimal.ONE).min()).isEqualTo(Option.some(BigDecimal.ZERO)); } @Test(expected = NullPointerException.class) public void shouldThrowNPEWhenMinOfNullAndInt() { of(null, 1).min(); } @Test(expected = NullPointerException.class) public void shouldThrowNPEWhenMinOfIntAndNull() { of(1, null).min(); } @Test public void shouldCalculateMinOfDoublesContainingNaN() { assertThat(of(1.0, Double.NaN, 2.0).min().get()).isEqualTo(Double.NaN); } @Test public void shouldCalculateMinOfFloatsContainingNaN() { assertThat(of(1.0f, Float.NaN, 2.0f).min().get()).isEqualTo(Float.NaN); } @Test public void shouldThrowClassCastExceptionWhenTryingToCalculateMinOfDoubleAndFloat() { assertThatThrownBy(() -> this. of(1.0, 1.0f).min()).isInstanceOf(ClassCastException.class); } @Test public void shouldCalculateMinOfDoublePositiveAndNegativeInfinity() { assertThat(of(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY).min().get()).isEqualTo(Double.NEGATIVE_INFINITY); } @Test public void shouldCalculateMinOfFloatPositiveAndNegativeInfinity() { assertThat(of(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY).min().get()).isEqualTo(Double.NEGATIVE_INFINITY); } // -- minBy(Comparator) @Test(expected = NullPointerException.class) public void shouldThrowWhenMinByWithNullComparator() { of(1).minBy((Comparator) null); } @Test public void shouldThrowWhenMinByOfNil() { assertThat(empty().minBy((o1, o2) -> 0)).isEqualTo(Option.none()); } @Test public void shouldCalculateMinByOfInts() { assertThat(of(1, 2, 3).minBy(comparingInt(i -> i))).isEqualTo(Option.some(1)); } @Test public void shouldCalculateInverseMinByOfInts() { assertThat(of(1, 2, 3).minBy((i1, i2) -> i2 - i1)).isEqualTo(Option.some(3)); } // -- minBy(Function) @Test(expected = NullPointerException.class) public void shouldThrowWhenMinByWithNullFunction() { of(1).minBy((Function) null); } @Test public void shouldThrowWhenMinByFunctionOfNil() { assertThat(this. empty().minBy(i -> i)).isEqualTo(Option.none()); } @Test public void shouldCalculateMinByFunctionOfInts() { assertThat(of(1, 2, 3).minBy(i -> i)).isEqualTo(Option.some(1)); } @Test public void shouldCalculateInverseMinByFunctionOfInts() { assertThat(of(1, 2, 3).minBy(i -> -i)).isEqualTo(Option.some(3)); } @Test public void shouldCallMinFunctionOncePerElement() { final int[] cnt = { 0 }; assertThat(of(1, 2, 3).minBy(i -> { cnt[0]++; return i; })).isEqualTo(Option.some(1)); assertThat(cnt[0]).isEqualTo(3); } // -- nonEmpty @Test public void shouldCalculateNonEmpty() { assertThat(empty().nonEmpty()).isFalse(); assertThat(of(1).nonEmpty()).isTrue(); } // -- orElse @Test public void shouldCaclEmptyOrElseSameOther() { final Iterable other = of(42); assertThat(empty().orElse(other)).isSameAs(other); } @Test public void shouldCaclEmptyOrElseEqualOther() { assertThat(empty().orElse(Arrays.asList(1, 2))).isEqualTo(of(1, 2)); } @Test public void shouldCaclNonemptyOrElseOther() { final Traversable src = of(42); assertThat(src.orElse(List.of(1))).isSameAs(src); } @Test public void shouldCaclEmptyOrElseSameSupplier() { final Iterable other = of(42); final Supplier> supplier = () -> other; assertThat(empty().orElse(supplier)).isSameAs(other); } @Test public void shouldCaclEmptyOrElseEqualSupplier() { assertThat(empty().orElse(() -> Arrays.asList(1, 2))).isEqualTo(of(1, 2)); } @Test public void shouldCaclNonemptyOrElseSupplier() { final Traversable src = of(42); assertThat(src.orElse(() -> List.of(1))).isSameAs(src); } // -- partition @Test(expected = NullPointerException.class) public void shouldThrowWhenPartitionNilAndPredicateIsNull() { empty().partition(null); } @Test public void shouldPartitionNil() { assertThat(empty().partition(e -> true)).isEqualTo(Tuple.of(empty(), empty())); } @Test public void shouldPartitionIntsInOddAndEvenHavingOddAndEvenNumbers() { assertThat(of(1, 2, 3, 4).partition(i -> i % 2 != 0)).isEqualTo(Tuple.of(of(1, 3), of(2, 4))); } @Test public void shouldPartitionIntsInOddAndEvenHavingOnlyOddNumbers() { assertThat(of(1, 3).partition(i -> i % 2 != 0)).isEqualTo(Tuple.of(of(1, 3), empty())); } @Test public void shouldPartitionIntsInOddAndEvenHavingOnlyEvenNumbers() { assertThat(of(2, 4).partition(i -> i % 2 != 0)).isEqualTo(Tuple.of(empty(), of(2, 4))); } // -- product @Test public void shouldComputeProductOfNil() { assertThat(empty().product()).isEqualTo(1); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenComputingProductOfStrings() { of("1", "2", "3").product(); } @Test public void shouldComputeProductOfByte() { assertThat(of((byte) 1, (byte) 2).product()).isEqualTo(2L); } @Test public void shouldComputeProductOfDouble() { assertThat(of(.1, .2, .3).product().doubleValue()).isEqualTo(.006, within(10e-18)); } @Test public void shouldComputeProductOfFloat() { assertThat(of(.1f, .2f, .3f).product().doubleValue()).isEqualTo(.006, within(10e-10)); } @Test public void shouldComputeProductOfInt() { assertThat(of(1, 2, 3).product()).isEqualTo(6L); } @Test public void shouldComputeProductOfLong() { assertThat(of(1L, 2L, 3L).product()).isEqualTo(6L); } @Test public void shouldComputeProductOfShort() { assertThat(of((short) 1, (short) 2, (short) 3).product()).isEqualTo(6L); } @Test public void shouldComputeProductOfBigInteger() { assertThat(of(BigInteger.ZERO, BigInteger.ONE).product()).isEqualTo(BigInteger.ZERO); } @Test public void shouldComputeProductOfBigDecimal() { assertThat(of(BigDecimal.ZERO, BigDecimal.ONE).product()).isEqualTo(BigDecimal.ZERO); } // -- reduceOption @Test public void shouldThrowWhenReduceOptionNil() { assertThat(this. empty().reduceOption((a, b) -> a + b)).isSameAs(Option.none()); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceOptionNullOperator() { this. empty().reduceOption(null); } @Test public void shouldReduceOptionNonNil() { assertThat(of(1, 2, 3).reduceOption((a, b) -> a + b)).isEqualTo(Option.of(6)); } // -- reduce @Test(expected = NoSuchElementException.class) public void shouldThrowWhenReduceNil() { this. empty().reduce((a, b) -> a + b); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceNullOperator() { this. empty().reduce(null); } @Test public void shouldReduceNonNil() { assertThat(of(1, 2, 3).reduce((a, b) -> a + b)).isEqualTo(6); } // -- reduceLeftOption @Test public void shouldThrowWhenReduceLeftOptionNil() { assertThat(this. empty().reduceLeftOption((a, b) -> a + b)).isSameAs(Option.none()); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceLeftOptionNullOperator() { this. empty().reduceLeftOption(null); } @Test public void shouldReduceLeftOptionNonNil() { assertThat(of("a", "b", "c").reduceLeftOption((xs, x) -> xs + x)).isEqualTo(Option.of("abc")); } // -- reduceLeft @Test(expected = NoSuchElementException.class) public void shouldThrowWhenReduceLeftNil() { this. empty().reduceLeft((a, b) -> a + b); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceLeftNullOperator() { this. empty().reduceLeft(null); } @Test public void shouldReduceLeftNonNil() { assertThat(of("a", "b", "c").reduceLeft((xs, x) -> xs + x)).isEqualTo("abc"); } // -- reduceRightOption @Test public void shouldThrowWhenReduceRightOptionNil() { assertThat(this. empty().reduceRightOption((a, b) -> a + b)).isSameAs(Option.none()); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceRightOptionNullOperator() { this. empty().reduceRightOption(null); } @Test public void shouldReduceRightOptionNonNil() { assertThat(of("a", "b", "c").reduceRightOption((x, xs) -> x + xs)).isEqualTo(Option.of("abc")); } // -- reduceRight @Test(expected = NoSuchElementException.class) public void shouldThrowWhenReduceRightNil() { this. empty().reduceRight((a, b) -> a + b); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceRightNullOperator() { this. empty().reduceRight(null); } @Test public void shouldReduceRightNonNil() { assertThat(of("a", "b", "c").reduceRight((x, xs) -> x + xs)).isEqualTo("abc"); } // -- replace(curr, new) @Test public void shouldReplaceElementOfNilUsingCurrNew() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(this. empty().replace(1, 2)).isEqualTo(empty()); } else { assertThat(this. empty().replace(1, 2)).isSameAs(empty()); } } @Test public void shouldReplaceFirstOccurrenceOfNonNilUsingCurrNewWhenMultipleOccurrencesExist() { final Traversable testee = of(0, 1, 2, 1); final Traversable actual = testee.replace(1, 3); final Traversable expected = of(0, 3, 2, 1); assertThat(actual).isEqualTo(expected); } @Test public void shouldReplaceElementOfNonNilUsingCurrNewWhenOneOccurrenceExists() { assertThat(of(0, 1, 2).replace(1, 3)).isEqualTo(of(0, 3, 2)); } @Test public void shouldReplaceElementOfNonNilUsingCurrNewWhenNoOccurrenceExists() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(0, 1, 2).replace(33, 3)).isEqualTo(of(0, 1, 2)); } else { final Traversable src = of(0, 1, 2); assertThat(src.replace(33, 3)).isSameAs(src); } } // -- replaceAll(curr, new) @Test public void shouldReplaceAllElementsOfNilUsingCurrNew() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(this. empty().replaceAll(1, 2)).isEqualTo(empty()); } else { assertThat(this. empty().replaceAll(1, 2)).isSameAs(empty()); } } @Test public void shouldReplaceAllElementsOfNonNilUsingCurrNonExistingNew() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(0, 1, 2, 1).replaceAll(33, 3)).isEqualTo(of(0, 1, 2, 1)); } else { final Traversable src = of(0, 1, 2, 1); assertThat(src.replaceAll(33, 3)).isSameAs(src); } } @Test public void shouldReplaceAllElementsOfNonNilUsingCurrNew() { assertThat(of(0, 1, 2, 1).replaceAll(1, 3)).isEqualTo(of(0, 3, 2, 3)); } // -- retainAll @Test public void shouldRetainAllElementsFromNil() { final Traversable empty = empty(); final Traversable actual = empty.retainAll(of(1, 2, 3)); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(actual).isEqualTo(empty); } else { assertThat(actual).isSameAs(empty); } } @Test public void shouldRetainAllExistingElementsFromNonNil() { final Traversable src = of(1, 2, 3, 2, 1, 3); final Traversable expected = of(1, 2, 2, 1); final Traversable actual = src.retainAll(of(1, 2)); assertThat(actual).isEqualTo(expected); } @Test public void shouldRetainAllElementsFromNonNil() { final Traversable src = of(1, 2, 1, 2, 2); final Traversable expected = of(1, 2, 1, 2, 2); final Traversable actual = src.retainAll(of(1, 2)); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(actual).isEqualTo(expected); } else { assertThat(actual).isSameAs(src); } } @Test public void shouldNotRetainAllNonExistingElementsFromNonNil() { final Traversable src = of(1, 2, 3); final Traversable expected = empty(); final Traversable actual = src.retainAll(of(4, 5)); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(actual).isEqualTo(expected); } else { assertThat(actual).isSameAs(expected); } } // -- scan, scanLeft, scanRight @Test public void shouldScanEmpty() { final Traversable testee = empty(); final Traversable actual = testee.scan(0, (s1, s2) -> s1 + s2); assertThat(actual).isEqualTo(this.of(0)); } @Test public void shouldScanLeftEmpty() { final Traversable testee = empty(); final Traversable actual = testee.scanLeft(0, (s1, s2) -> s1 + s2); assertThat(actual).isEqualTo(of(0)); } @Test public void shouldScanRightEmpty() { final Traversable testee = empty(); final Traversable actual = testee.scanRight(0, (s1, s2) -> s1 + s2); assertThat(actual).isEqualTo(of(0)); } @Test public void shouldScanNonEmpty() { final Traversable testee = of(1, 2, 3); final Traversable actual = testee.scan(0, (acc, s) -> acc + s); assertThat(actual).isEqualTo(of(0, 1, 3, 6)); } @Test public void shouldScanLeftNonEmpty() { final Traversable testee = of(1, 2, 3); final Traversable actual = testee.scanLeft("x", (acc, i) -> acc + i); assertThat(actual).isEqualTo(of("x", "x1", "x12", "x123")); } @Test public void shouldScanRightNonEmpty() { final Traversable testee = of(1, 2, 3); final Traversable actual = testee.scanRight("x", (i, acc) -> acc + i); assertThat(actual).isEqualTo(of("x321", "x32", "x3", "x")); } @Test public void shouldScanWithNonComparable() { final Traversable testee = of(new NonComparable("a")); final List actual = List.ofAll(testee.scan(new NonComparable("x"), (u1, u2) -> new NonComparable(u1.value + u2.value))); final List expected = List.of("x", "xa").map(NonComparable::new); assertThat(actual).containsAll(expected); assertThat(expected).containsAll(actual); assertThat(actual.length()).isEqualTo(expected.length()); } @Test public void shouldScanLeftWithNonComparable() { final Traversable testee = of(new NonComparable("a")); final List actual = List.ofAll(testee.scanLeft(new NonComparable("x"), (u1, u2) -> new NonComparable(u1.value + u2.value))); final List expected = List.of("x", "xa").map(NonComparable::new); assertThat(actual).containsAll(expected); assertThat(expected).containsAll(actual); assertThat(actual.length()).isEqualTo(expected.length()); } @Test public void shouldScanRightWithNonComparable() { final Traversable testee = of(new NonComparable("a")); final List actual = List.ofAll(testee.scanRight(new NonComparable("x"), (u1, u2) -> new NonComparable(u1.value + u2.value))); final List expected = List.of("ax", "x").map(NonComparable::new); assertThat(actual).containsAll(expected); assertThat(expected).containsAll(actual); assertThat(actual.length()).isEqualTo(expected.length()); } // -- slideBy(classifier) @Test public void shouldSlideNilByClassifier() { assertThat(empty().slideBy(Function.identity())).isEmpty(); } @Test public void shouldSlideSingularByClassifier() { final List> actual = of(1).slideBy(Function.identity()).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlideNonNilByIdentityClassifier() { final List> actual = of(1, 2, 3).slideBy(Function.identity()).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1), io.vavr.collection.Vector.of(2), io.vavr.collection.Vector.of(3)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlideNonNilByConstantClassifier() { final List> actual = of(1, 2, 3).slideBy(e -> "same").toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2, 3)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlideNonNilBySomeClassifier() { final List> actual = of(10, 20, 30, 42, 52, 60, 72).slideBy(e -> e % 10).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(10, 20, 30), io.vavr.collection.Vector.of(42, 52), io.vavr.collection.Vector.of(60), io.vavr.collection.Vector.of(72)); assertThat(actual).isEqualTo(expected); } // -- sliding(size) @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNilByZeroSize() { empty().sliding(0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNilByNegativeSize() { empty().sliding(-1); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNonNilByZeroSize() { of(1).sliding(0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNonNilByNegativeSize() { of(1).sliding(-1); } @Test public void shouldSlideNilBySize() { assertThat(empty().sliding(1)).isEmpty(); } @Test public void shouldSlideNonNilBySize1() { final List> actual = of(1, 2, 3).sliding(1).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1), io.vavr.collection.Vector.of(2), io.vavr.collection.Vector.of(3)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlideNonNilBySize2() { final List> actual = of(1, 2, 3, 4, 5).sliding(2).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2), io.vavr.collection.Vector.of(2, 3), io.vavr.collection.Vector.of(3, 4), io.vavr.collection.Vector.of(4, 5)); assertThat(actual).isEqualTo(expected); } // -- sliding(size, step) @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNilByPositiveStepAndNegativeSize() { empty().sliding(-1, 1); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNilByNegativeStepAndNegativeSize() { empty().sliding(-1, -1); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNilByNegativeStepAndPositiveSize() { empty().sliding(1, -1); } @Test public void shouldSlideNilBySizeAndStep() { assertThat(empty().sliding(1, 1).isEmpty()).isTrue(); } @Test public void shouldSlide5ElementsBySize2AndStep3() { final List> actual = of(1, 2, 3, 4, 5).sliding(2, 3).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2), io.vavr.collection.Vector.of(4, 5)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlide5ElementsBySize2AndStep4() { final List> actual = of(1, 2, 3, 4, 5).sliding(2, 4).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2), io.vavr.collection.Vector.of(5)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlide5ElementsBySize2AndStep5() { final List> actual = of(1, 2, 3, 4, 5).sliding(2, 5).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlide4ElementsBySize5AndStep3() { final List> actual = of(1, 2, 3, 4).sliding(5, 3).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2, 3, 4)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlide7ElementsBySize1AndStep3() { final List> actual = of(1, 2, 3, 4, 5, 6 ,7).sliding(1, 3).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1), io.vavr.collection.Vector.of(4), io.vavr.collection.Vector.of(7)); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlide7ElementsBySize2AndStep3() { final List> actual = of(1, 2, 3, 4, 5, 6 ,7).sliding(2, 3).toList().map(io.vavr.collection.Vector::ofAll); final List> expected = List.of(io.vavr.collection.Vector.of(1, 2), io.vavr.collection.Vector.of(4, 5), io.vavr.collection.Vector.of(7)); assertThat(actual).isEqualTo(expected); } // -- span @Test public void shouldSpanNil() { assertThat(this. empty().span(i -> i < 2)).isEqualTo(Tuple.of(empty(), empty())); } @Test public void shouldSpanNonNil() { assertThat(of(0, 1, 2, 3).span(i -> i < 2)).isEqualTo(Tuple.of(of(0, 1), of(2, 3))); } @Test public void shouldSpanAndNotTruncate() { assertThat(of(1, 1, 2, 2, 3, 3).span(x -> x % 2 == 1)).isEqualTo(Tuple.of(of(1, 1), of(2, 2, 3, 3))); assertThat(of(1, 1, 2, 2, 4, 4).span(x -> x == 1)).isEqualTo(Tuple.of(of(1, 1), of(2, 2, 4, 4))); } // -- spliterator @Test public void shouldSplitNil() { final java.util.List actual = new java.util.ArrayList<>(); this.empty().spliterator().forEachRemaining(actual::add); assertThat(actual).isEmpty(); } @Test public void shouldSplitNonNil() { final java.util.List actual = new java.util.ArrayList<>(); of(1, 2, 3).spliterator().forEachRemaining(actual::add); assertThat(actual).isEqualTo(asList(1, 2, 3)); } @Test public void shouldHaveImmutableSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.IMMUTABLE)).isTrue(); } // -- stderr @Test public void shouldWriteToStderr() { assertThat(captureErrOut(()->of(1, 2, 3).stderr())).isEqualTo("1\n" + "2\n" + "3\n"); } @Test(expected = IllegalStateException.class) public void shouldHandleStderrIOException() { withFailingErrOut(()->of(0).stderr()); } // -- stdout @Test public void shouldWriteToStdout() { assertThat(captureStdOut(()->of(1, 2, 3).stdout())).isEqualTo("1\n" + "2\n" + "3\n"); } @Test(expected = IllegalStateException.class) public void shouldHandleStdoutIOException() { withFailingStdOut(()->of(0).stdout()); } // -- PrintStream @Test public void shouldWriteToPrintStream() { final ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); final PrintStream out = new PrintStream(baos); of(1, 2, 3).out(out); assertThat(baos.toString()).isEqualTo(of(1, 2, 3).mkString("", lineSeparator(), lineSeparator())); } @Test(expected = IllegalStateException.class) public void shouldHandlePrintStreamIOException() { try (PrintStream failingPrintStream = failingPrintStream()) { of(0).out(failingPrintStream); } } // -- PrintWriter @Test public void shouldWriteToPrintWriter() { final StringWriter sw = new StringWriter(); final PrintWriter out = new PrintWriter(sw); of(1, 2, 3).out(out); assertThat(sw.toString()).isEqualTo(of(1, 2, 3).mkString("", lineSeparator(), lineSeparator())); } @Test(expected = IllegalStateException.class) public void shouldHandlePrintWriterIOException() { try (PrintWriter failingPrintWriter = failingPrintWriter()) { of(0).out(failingPrintWriter); } } // -- sum @Test public void shouldComputeSumOfNil() { assertThat(empty().sum()).isEqualTo(0); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenComputingSumOfStrings() { of("1", "2", "3").sum(); } @Test public void shouldComputeSumOfByte() { assertThat(of((byte) 1, (byte) 2).sum()).isEqualTo(3L); } @Test public void shouldComputeSumOfDouble() { assertThat(of(.1, .2, .3).sum().doubleValue()).isEqualTo(.6, within(10e-16)); } @Test public void shouldComputeSumOfFloat() { assertThat(of(.1f, .2f, .3f).sum().doubleValue()).isEqualTo(.6, within(10e-8)); } @Test public void shouldComputeSumOfInt() { assertThat(of(1, 2, 3).sum()).isEqualTo(6L); } @Test public void shouldComputeSumOfLong() { assertThat(of(1L, 2L, 3L).sum()).isEqualTo(6L); } @Test public void shouldComputeSumOfShort() { assertThat(of((short) 1, (short) 2, (short) 3).sum()).isEqualTo(6L); } @Test public void shouldComputeSumOfBigInteger() { assertThat(of(BigInteger.ZERO, BigInteger.ONE).sum()).isEqualTo(BigInteger.ONE); } @Test public void shouldComputeSumOfBigDecimal() { assertThat(of(BigDecimal.ZERO, BigDecimal.ONE).sum()).isEqualTo(BigDecimal.ONE); } // -- take @Test public void shouldTakeNoneOnNil() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().take(1)).isEqualTo(empty()); } else { assertThat(empty().take(1)).isSameAs(empty()); } } @Test public void shouldTakeNoneIfCountIsNegative() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).take(-1)).isEqualTo(empty()); } else { assertThat(of(1, 2, 3).take(-1)).isSameAs(empty()); } } @Test public void shouldTakeAsExpectedIfCountIsLessThanSize() { assertThat(of(1, 2, 3).take(2)).isEqualTo(of(1, 2)); } @Test public void shouldTakeAllIfCountExceedsSize() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).take(4)).isEqualTo(of(1, 2, 3)); } else { final Traversable t = of(1, 2, 3); assertThat(t.take(4)).isSameAs(t); } } @Test public void shouldReturnSameInstanceIfTakeAll() { final Traversable t = of(1, 2, 3); assertThat(t.take(3)).isSameAs(t); assertThat(t.take(4)).isSameAs(t); } // -- takeRight @Test public void shouldTakeRightNoneOnNil() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().takeRight(1)).isEqualTo(empty()); } else { assertThat(empty().takeRight(1)).isSameAs(empty()); } } @Test public void shouldTakeRightNoneIfCountIsNegative() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).takeRight(-1)).isEqualTo(empty()); } else { assertThat(of(1, 2, 3).takeRight(-1)).isSameAs(empty()); } } @Test public void shouldTakeRightAsExpectedIfCountIsLessThanSize() { assertThat(of(1, 2, 3).takeRight(2)).isEqualTo(of(2, 3)); } @Test public void shouldTakeRightAllIfCountExceedsSize() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).takeRight(4)).isEqualTo(of(1, 2, 3)); } else { final Traversable t = of(1, 2, 3); assertThat(t.takeRight(4)).isSameAs(t); } } @Test public void shouldReturnSameInstanceIfTakeRightAll() { final Traversable t = of(1, 2, 3); assertThat(t.takeRight(3)).isSameAs(t); assertThat(t.takeRight(4)).isSameAs(t); } // -- takeUntil @Test public void shouldTakeUntilNoneOnNil() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().takeUntil(x -> true)).isEqualTo(empty()); } else { assertThat(empty().takeUntil(x -> true)).isSameAs(empty()); } } @Test public void shouldTakeUntilAllOnFalseCondition() { final Traversable t = of(1, 2, 3); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).takeUntil(x -> false)).isEqualTo(of(1, 2, 3)); } else { assertThat(t.takeUntil(x -> false)).isSameAs(t); } } @Test public void shouldTakeUntilAllOnTrueCondition() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).takeUntil(x -> true)).isEqualTo(empty()); } else { assertThat(of(1, 2, 3).takeUntil(x -> true)).isSameAs(empty()); } } @Test public void shouldTakeUntilAsExpected() { assertThat(of(2, 4, 5, 6).takeUntil(x -> x % 2 != 0)).isEqualTo(of(2, 4)); } @Test public void shouldReturnSameInstanceWhenEmptyTakeUntil() { final Traversable empty = empty(); assertThat(empty.takeUntil(ignored -> false)).isSameAs(empty); } // -- takeWhile @Test public void shouldTakeWhileNoneOnNil() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(empty().takeWhile(x -> true)).isEqualTo(empty()); } else { assertThat(empty().takeWhile(x -> true)).isSameAs(empty()); } } @Test public void shouldTakeWhileAllOnFalseCondition() { if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).takeWhile(x -> false)).isEqualTo(empty()); } else { assertThat(of(1, 2, 3).takeWhile(x -> false)).isSameAs(empty()); } } @Test public void shouldTakeWhileAllOnTrueCondition() { final Traversable t = of(1, 2, 3); if (useIsEqualToInsteadOfIsSameAs()) { assertThat(of(1, 2, 3).takeWhile(x -> true)).isEqualTo(of(1, 2, 3)); } else { assertThat(t.takeWhile(x -> true)).isSameAs(t); } } @Test public void shouldTakeWhileAsExpected() { assertThat(of(2, 4, 5, 6).takeWhile(x -> x % 2 == 0)).isEqualTo(of(2, 4)); } @Test public void shouldReturnSameInstanceWhenEmptyTakeWhile() { final Traversable empty = empty(); assertThat(empty.takeWhile(ignored -> false)).isSameAs(empty); } // -- tail @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenTailOnNil() { empty().tail(); } @Test public void shouldReturnTailOfNonNil() { assertThat(of(1, 2, 3).tail()).isEqualTo(of(2, 3)); } // -- tailOption @Test public void shouldReturnNoneWhenCallingTailOptionOnNil() { assertThat(empty().tailOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeTailWhenCallingTailOptionOnNonNil() { assertThat(of(1, 2, 3).tailOption()).isEqualTo(Option.some(of(2, 3))); } // -- unzip @Test public void shouldUnzipNil() { assertThat(empty().unzip(x -> Tuple.of(x, x))).isEqualTo(Tuple.of(empty(), empty())); } @Test public void shouldUnzipNonNil() { final Tuple actual = of(0, 1).unzip(i -> Tuple.of(i, (char) ((short) 'a' + i))); final Tuple expected = Tuple.of(of(0, 1), of('a', 'b')); assertThat(actual).isEqualTo(expected); } @Test public void shouldUnzip3Nil() { assertThat(empty().unzip3(x -> Tuple.of(x, x, x))).isEqualTo(Tuple.of(empty(), empty(), empty())); } @Test public void shouldUnzip3NonNil() { final Tuple actual = of(0, 1).unzip3(i -> Tuple.of(i, (char) ((short) 'a' + i), (char) ((short) 'a' + i + 1))); final Tuple expected = Tuple.of(of(0, 1), of('a', 'b'), of('b', 'c')); assertThat(actual).isEqualTo(expected); } // -- zip @Test public void shouldZipNils() { final Traversable actual = empty().zip(empty()); assertThat(actual).isEmpty(); } @Test public void shouldZipEmptyAndNonNil() { final Traversable actual = empty().zip(of(1)); assertThat(actual).isEmpty(); } @Test public void shouldZipNonEmptyAndNil() { final Traversable actual = of(1).zip(empty()); assertThat(actual).isEmpty(); } @Test public void shouldZipNonNilsIfThisIsSmaller() { final Traversable> actual = of(1, 2).zip(of("a", "b", "c")); @SuppressWarnings("unchecked") final Traversable> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipNonNilsIfThatIsSmaller() { final Traversable> actual = of(1, 2, 3).zip(of("a", "b")); @SuppressWarnings("unchecked") final Traversable> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipNonNilsOfSameSize() { final Traversable> actual = of(1, 2, 3).zip(of("a", "b", "c")); @SuppressWarnings("unchecked") final Traversable> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(3, "c")); assertThat(actual).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldZipWithNonNilsOfSameSize() { final Traversable> actual = of(1, 2, 3).zipWith(of("a", "b", "c"), Tuple::of); final Traversable> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(3, "c")); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipWithThatIsNull() { empty().zip(null); } // -- zipAll @Test public void shouldZipAllNils() { final Traversable actual = empty().zipAll(empty(), null, null); assertThat(actual).isEmpty(); } @Test public void shouldZipAllEmptyAndNonNil() { final Traversable actual = empty().zipAll(of(1), null, null); final Traversable> expected = of(Tuple.of(null, 1)); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonEmptyAndNil() { final Traversable actual = of(1).zipAll(empty(), null, null); final Traversable> expected = of(Tuple.of(1, null)); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThisIsSmaller() { final Traversable> actual = of(1, 2).zipAll(of("a", "b", "c"), 9, "z"); @SuppressWarnings("unchecked") final Traversable> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(9, "c")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThatIsSmaller() { final Traversable> actual = of(1, 2, 3).zipAll(of("a", "b"), 9, "z"); @SuppressWarnings("unchecked") final Traversable> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(3, "z")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsOfSameSize() { final Traversable> actual = of(1, 2, 3).zipAll(of("a", "b", "c"), 9, "z"); @SuppressWarnings("unchecked") final Traversable> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(3, "c")); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipAllWithThatIsNull() { empty().zipAll(null, null, null); } // -- zipWithIndex @Test public void shouldZipNilWithIndex() { assertThat(this.empty().zipWithIndex()).isEqualTo(this.>empty()); } @Test public void shouldZipNonNilWithIndex() { final Traversable> actual = of("a", "b", "c").zipWithIndex(); @SuppressWarnings("unchecked") final Traversable> expected = of(Tuple.of("a", 0), Tuple.of("b", 1), Tuple.of("c", 2)); assertThat(actual).isEqualTo(expected); } @Test @SuppressWarnings("unchecked") public void shouldZipNonNilWithIndexWithMapper() { final Traversable> actual = of("a", "b", "c").zipWithIndex(Tuple::of); final Traversable> expected = of(Tuple.of("a", 0), Tuple.of("b", 1), Tuple.of("c", 2)); assertThat(actual).isEqualTo(expected); } // -- toJavaArray(IntFunction) @Test public void shouldConvertNilToJavaArray() { final Integer[] actual = List. empty().toJavaArray(Integer[]::new); final Integer[] expected = new Integer[] {}; assertThat(actual).isEqualTo(expected); } @Test public void shouldConvertNonNilToJavaArray() { final Integer[] array = of(1, 2).toJavaArray(Integer[]::new); final Integer[] expected = new Integer[] { 1, 2 }; assertThat(array).isEqualTo(expected); } // -- toJavaList @Test public void shouldConvertNilToArrayList() { assertThat(this. empty().toJavaList()).isEqualTo(new ArrayList()); } @Test public void shouldConvertNonNilToArrayList() { assertThat(of(1, 2, 3).toJavaList()).isEqualTo(asList(1, 2, 3)); } // -- toJavaMap(Function) @Test public void shouldConvertNilToHashMap() { assertThat(this. empty().toJavaMap(x -> Tuple.of(x, x))).isEqualTo(new java.util.HashMap<>()); } @Test public void shouldConvertNonNilToHashMap() { final java.util.Map expected = new java.util.HashMap<>(); expected.put(1, 1); expected.put(2, 2); assertThat(of(1, 2).toJavaMap(x -> Tuple.of(x, x))).isEqualTo(expected); } // -- toJavaSet @Test public void shouldConvertNilToHashSet() { assertThat(this. empty().toJavaSet()).isEqualTo(new java.util.HashSet<>()); } @Test public void shouldConvertNonNilToHashSet() { final java.util.Set expected = new java.util.HashSet<>(); expected.add(2); expected.add(1); expected.add(3); assertThat(of(1, 2, 2, 3).toJavaSet()).isEqualTo(expected); } // toTree @Test public void shouldConvertToTree() { //Value["id:parent")] final Traversable value = of( "1:", "2:1", "3:1", "4:2", "5:2", "6:3", "7:4", "8:6", "9:6" ); final Seq> roots = value .toTree(s -> s.split(":")[0], s -> s.split(":").length == 1 ? null : s.split(":")[1]) .map(l -> l.map(s -> s.split(":")[0])); assertThat(roots).hasSize(1); final Tree root = roots.head(); if (value.hasDefiniteSize()) { assertThat(root).hasSameSizeAs(value); } assertThat(root.toLispString()).isEqualTo("(1 (2 (4 7) 5) (3 (6 8 9)))"); } // ++++++ OBJECT ++++++ // -- equals @SuppressWarnings("EqualsWithItself") @Test public void shouldEqualSameTraversableInstance() { final Traversable nonEmpty = of(1); assertThat(nonEmpty.equals(nonEmpty)).isTrue(); assertThat(empty().equals(empty())).isTrue(); } @Test public void shouldNilNotEqualsNull() { assertThat(empty()).isNotNull(); } @Test public void shouldNonNilNotEqualsNull() { assertThat(of(1)).isNotNull(); } @Test public void shouldEmptyNotEqualsDifferentType() { assertThat(empty()).isNotEqualTo(""); } @Test public void shouldNonEmptyNotEqualsDifferentType() { assertThat(of(1)).isNotEqualTo(""); } @Test public void shouldRecognizeEqualityOfNils() { assertThat(empty()).isEqualTo(empty()); } @Test public void shouldRecognizeEqualityOfNonNils() { assertThat(of(1, 2, 3).equals(of(1, 2, 3))).isTrue(); } @Test public void shouldRecognizeNonEqualityOfTraversablesOfSameSize() { assertThat(of(1, 2, 3).equals(of(1, 2, 4))).isFalse(); } @Test public void shouldRecognizeNonEqualityOfTraversablesOfDifferentSize() { assertThat(of(1, 2, 3).equals(of(1, 2))).isFalse(); assertThat(of(1, 2).equals(of(1, 2, 3))).isFalse(); } // -- hashCode @Test public void shouldCalculateHashCodeOfNil() { assertThat(empty().hashCode() == empty().hashCode()).isTrue(); } @Test public void shouldCalculateHashCodeOfNonNil() { assertThat(of(1, 2).hashCode() == of(1, 2).hashCode()).isTrue(); } @Test public void shouldCalculateDifferentHashCodesForDifferentTraversables() { assertThat(of(1, 2).hashCode() != of(2, 3).hashCode()).isTrue(); } @Test public void shouldComputeHashCodeOfEmpty() { assertThat(empty().hashCode()).isEqualTo(1); } @Test public void shouldNotThrowStackOverflowErrorWhenCalculatingHashCodeOf1000000Integers() { assertThat(ofAll(io.vavr.collection.Iterator.range(0, 1000000)).hashCode()).isNotNull(); } // -- toString @Test public void shouldConformEmptyStringRepresentation() { final Traversable testee = empty(); if (!testee.hasDefiniteSize()) { assertThat(testee.toString()).isEqualTo(testee.stringPrefix() + "()"); testee.size(); // evaluates all elements of lazy collections } assertThat(testee.toString()).isEqualTo(toString(testee)); } @Test public void shouldConformNonEmptyStringRepresentation() { final Traversable testee = of("a", "b", "c"); if (isTraversableAgain()) { if (!testee.hasDefiniteSize()) { assertThat(testee.toString()).isEqualTo(testee.stringPrefix() + "(a, ?)"); testee.size(); // evaluates all elements of lazy collections } assertThat(testee.toString()).isEqualTo(toString(testee)); } else { assertThat(testee.toString()).isEqualTo(testee.stringPrefix() + "(?)"); } } private static String toString(Traversable traversable) { return traversable.mkString(traversable.stringPrefix() + "(", ", ", ")"); } // -- static collector() @Test public void shouldStreamAndCollectNil() { testCollector(() -> { final Traversable actual = java.util.stream.Stream.empty().collect(collector()); assertThat(actual).isEmpty(); }); } @Test public void shouldStreamAndCollectNonNil() { testCollector(() -> { final Traversable actual = java.util.stream.Stream.of(1, 2, 3).collect(this. collector()); assertThat(actual).isEqualTo(of(1, 2, 3)); }); } @Test public void shouldParallelStreamAndCollectNil() { testCollector(() -> { final Traversable actual = java.util.stream.Stream.empty().parallel().collect(collector()); assertThat(actual).isEmpty(); }); } @Test public void shouldParallelStreamAndCollectNonNil() { testCollector(() -> { final Traversable actual = java.util.stream.Stream.of(1, 2, 3).parallel().collect(this. collector()); assertThat(actual).isEqualTo(of(1, 2, 3)); }); } // -- single @Test(expected = NoSuchElementException.class) public void shouldSingleFailEmpty() { empty().single(); } @Test(expected = NoSuchElementException.class) public void shouldSingleFailTwo() { of(1, 2).single(); } @Test public void shouldSingleWork() { assertThat(of(1).single()).isEqualTo(1); } // -- singleOption @Test public void shouldSingleOptionFailEmpty() { assertThat(empty().singleOption()).isEqualTo(Option.none()); } @Test public void shouldSingleOptionFailTwo() { assertThat(of(1, 2).singleOption()).isEqualTo(Option.none()); } @Test public void shouldSingleOptionWork() { assertThat(of(1).singleOption()).isEqualTo(Option.of(1)); } @Test public void shouldTabulateTheSeq() { final Function f = i -> i.intValue() * i.intValue(); final Traversable actual = tabulate(3, f); assertThat(actual).isEqualTo(of(0, 1, 4)); } @Test public void shouldTabulateTheSeqCallingTheFunctionInTheRightOrder() { final java.util.LinkedList ints = new java.util.LinkedList<>(asList(0, 1, 2)); final Function f = i -> ints.remove(); final Traversable actual = tabulate(3, f); assertThat(actual).isEqualTo(of(0, 1, 2)); } @Test public void shouldTabulateTheSeqWith0Elements() { assertThat(tabulate(0, i -> i)).isEqualTo(empty()); } @Test public void shouldTabulateTheSeqWith0ElementsWhenNIsNegative() { assertThat(tabulate(-1, i -> i)).isEqualTo(empty()); } // -- fill(int, Supplier) @Test public void shouldFillTheSeqCallingTheSupplierInTheRightOrder() { final java.util.LinkedList ints = new java.util.LinkedList<>(asList(0, 1)); final Traversable actual = fill(2, ints::remove); assertThat(actual).isEqualTo(of(0, 1)); } @Test public void shouldFillTheSeqWith0Elements() { assertThat(fill(0, () -> 1)).isEqualTo(empty()); } @Test public void shouldFillTheSeqWith0ElementsWhenNIsNegative() { assertThat(fill(-1, () -> 1)).isEqualTo(empty()); } @Test public void ofShouldReturnTheSingletonEmpty() { if (!emptyShouldBeSingleton()) { return; } assertThat(of()).isSameAs(empty()); } @Test public void ofAllShouldReturnTheSingletonEmpty() { if (!emptyShouldBeSingleton()) { return; } assertThat(ofAll(io.vavr.collection.Iterator.empty())).isSameAs(empty()); } private void testCollector(Runnable test) { if (isTraversableAgain()) { test.run(); } else { try { collector(); fail("Collections which are not traversable again should not define a Collector."); } catch (UnsupportedOperationException x) { // ok } catch (Throwable x) { fail("Unexpected exception", x); } } } // helpers /** * Wraps a String in order to ensure that it is not Comparable. */ static final class NonComparable { final String value; NonComparable(String value) { this.value = value; } @Override public int hashCode() { return Objects.hash(value); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } else if (obj instanceof NonComparable) { final NonComparable that = (NonComparable) obj; return Objects.equals(this.value, that.value); } else { return false; } } @Override public String toString() { return value; } } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/ArrayTest.java000066400000000000000000000177451342074374400245420ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Value; import io.vavr.Tuple2; import io.vavr.control.Option; import org.junit.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; public class ArrayTest extends AbstractIndexedSeqTest { @Override protected Collector, ? extends Seq> collector() { return Array.collector(); } @Override protected Array empty() { return Array.empty(); } @Override protected Array of(T element) { return Array.of(element); } @SuppressWarnings("varargs") @SafeVarargs @Override protected final Array of(T... elements) { return Array.of(elements); } @Override protected Array ofAll(Iterable elements) { return Array.ofAll(elements); } @Override protected > Array ofJavaStream(java.util.stream.Stream javaStream) { return Array.ofAll(javaStream); } @Override protected Array ofAll(boolean... elements) { return Array.ofAll(elements); } @Override protected Array ofAll(byte... elements) { return Array.ofAll(elements); } @Override protected Array ofAll(char... elements) { return Array.ofAll(elements); } @Override protected Array ofAll(double... elements) { return Array.ofAll(elements); } @Override protected Array ofAll(float... elements) { return Array.ofAll(elements); } @Override protected Array ofAll(int... elements) { return Array.ofAll(elements); } @Override protected Array ofAll(long... elements) { return Array.ofAll(elements); } @Override protected Array ofAll(short... elements) { return Array.ofAll(elements); } @Override protected Array tabulate(int n, Function f) { return Array.tabulate(n, f); } @Override protected Array fill(int n, Supplier s) { return Array.fill(n, s); } @Override protected Traversable fill(int n, T element) { return Array.fill(n, element); } @Override protected Array range(char from, char toExclusive) { return Array.range(from, toExclusive); } @Override protected Array rangeBy(char from, char toExclusive, int step) { return Array.rangeBy(from, toExclusive, step); } @Override protected Array rangeBy(double from, double toExclusive, double step) { return Array.rangeBy(from, toExclusive, step); } @Override protected Array range(int from, int toExclusive) { return Array.range(from, toExclusive); } @Override protected Array rangeBy(int from, int toExclusive, int step) { return Array.rangeBy(from, toExclusive, step); } @Override protected Array range(long from, long toExclusive) { return Array.range(from, toExclusive); } @Override protected Array rangeBy(long from, long toExclusive, long step) { return Array.rangeBy(from, toExclusive, step); } @Override protected Array rangeClosed(char from, char toInclusive) { return Array.rangeClosed(from, toInclusive); } @Override protected Array rangeClosedBy(char from, char toInclusive, int step) { return Array.rangeClosedBy(from, toInclusive, step); } @Override protected Array rangeClosedBy(double from, double toInclusive, double step) { return Array.rangeClosedBy(from, toInclusive, step); } @Override protected Array rangeClosed(int from, int toInclusive) { return Array.rangeClosed(from, toInclusive); } @Override protected Array rangeClosedBy(int from, int toInclusive, int step) { return Array.rangeClosedBy(from, toInclusive, step); } @Override protected Array rangeClosed(long from, long toInclusive) { return Array.rangeClosed(from, toInclusive); } @Override protected Array rangeClosedBy(long from, long toInclusive, long step) { return Array.rangeClosedBy(from, toInclusive, step); } @Override @SuppressWarnings("unchecked") protected Array> transpose(Seq> rows) { return Array.transpose((Array>) rows); } @Override protected int getPeekNonNilPerformingAnAction() { return 1; } //fixme: delete, when useIsEqualToInsteadOfIsSameAs() will be eliminated from AbstractValueTest class @Override protected boolean useIsEqualToInsteadOfIsSameAs() { return false; } // -- static narrow @Test public void shouldNarrowArray() { final Array doubles = of(1.0d); final Array numbers = Array.narrow(doubles); final int actual = numbers.append(new BigDecimal("2.0")).sum().intValue(); assertThat(actual).isEqualTo(3); } // -- transform() @Test public void shouldTransform() { String transformed = of(42).transform(v -> String.valueOf(v.get())); assertThat(transformed).isEqualTo("42"); } // -- unfold @Test public void shouldUnfoldRightToEmpty() { assertThat(Array.unfoldRight(0, x -> Option.none())).isEqualTo(empty()); } @Test public void shouldUnfoldRightSimpleArray() { assertThat( Array.unfoldRight(10, x -> x == 0 ? Option.none() : Option.of(new Tuple2<>(x, x - 1)))) .isEqualTo(of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); } @Test public void shouldUnfoldLeftToEmpty() { assertThat(Array.unfoldLeft(0, x -> Option.none())).isEqualTo(empty()); } @Test public void shouldUnfoldLeftSimpleArray() { assertThat( Array.unfoldLeft(10, x -> x == 0 ? Option.none() : Option.of(new Tuple2<>(x - 1, x)))) .isEqualTo(of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); } @Test public void shouldUnfoldToEmpty() { assertThat(Array.unfold(0, x -> Option.none())).isEqualTo(empty()); } @Test public void shouldUnfoldSimpleArray() { assertThat( Array.unfold(10, x -> x == 0 ? Option.none() : Option.of(new Tuple2<>(x - 1, x)))) .isEqualTo(of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); } // -- toString @Test public void shouldStringifyNil() { assertThat(empty().toString()).isEqualTo("Array()"); } @Test public void shouldStringifyNonNil() { assertThat(of(1, 2, 3).toString()).isEqualTo("Array(1, 2, 3)"); } // -- toArray @Test public void shouldReturnSelfOnConvertToArray() { Value value = of(1, 2, 3); assertThat(value.toArray()).isSameAs(value); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/BitSetTest.java000066400000000000000000000453321342074374400246470ustar00rootroot00000000000000package io.vavr.collection; import io.vavr.Function1; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.Value; import org.assertj.core.api.Assertions; import org.assertj.core.api.IterableAssert; import org.assertj.core.api.ObjectAssert; import org.junit.Test; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Random; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.reverseOrder; import static java.util.stream.Collectors.toList; import static io.vavr.Serializables.deserialize; import static io.vavr.Serializables.serialize; public class BitSetTest extends AbstractSortedSetTest { private final static int MAX_BIT = 1_000_000; private enum E { V1, V2, V3 } @Override protected IterableAssert assertThat(Iterable actual) { return new IterableAssert(actual) { @Override @SuppressWarnings("unchecked") public IterableAssert isEqualTo(Object obj) { if (obj instanceof BitSet || actual instanceof BitSet) { Assertions.assertThat(HashSet.ofAll(actual)).isEqualTo(HashSet.ofAll((Iterable) obj)); } else { super.isEqualTo(obj); } return this; } }; } @Override protected ObjectAssert assertThat(T actual) { return new ObjectAssert(actual) { @Override public ObjectAssert isEqualTo(Object expected) { if (actual instanceof Tuple2) { final Tuple2 t1 = (Tuple2) actual; final Tuple2 t2 = (Tuple2) expected; assertThat((Iterable) t1._1).isEqualTo(t2._1); assertThat((Iterable) t1._2).isEqualTo(t2._2); return this; } else if (actual instanceof Tuple3) { final Tuple3 t1 = (Tuple3) actual; final Tuple3 t2 = (Tuple3) expected; assertThat((Iterable) t1._1).isEqualTo(t2._1); assertThat((Iterable) t1._2).isEqualTo(t2._2); assertThat((Iterable) t1._3).isEqualTo(t2._3); return this; } else { return super.isEqualTo(expected); } } }; } private BitSet.Builder bsBuilder() { final Mapper mapper = new Mapper<>(); return BitSet.withRelations( (Function1 & Serializable) mapper::fromInt, (Function1 & Serializable) mapper::toInt); } @Override protected Collector, ? extends Traversable> collector() { return this. bsBuilder().collector(); } @Override protected BitSet empty() { return this. bsBuilder().empty(); } @Override protected BitSet emptyWithNull() { return empty(); } @Override protected boolean emptyShouldBeSingleton() { return false; } @Override protected BitSet of(T element) { return this. bsBuilder().of(element); } @Override protected BitSet of(Comparator comparator, T element) { // comparator is not used return this. bsBuilder().of(element); } @SuppressWarnings("varargs") @SafeVarargs @Override protected final BitSet of(Comparator comparator, T... elements) { // comparator is not used return this. bsBuilder().of(elements); } @SuppressWarnings("varargs") @SafeVarargs @Override protected final BitSet of(T... elements) { return this. bsBuilder().of(elements); } @Override protected boolean useIsEqualToInsteadOfIsSameAs() { return true; } @Override protected int getPeekNonNilPerformingAnAction() { return 1; } @Override protected BitSet ofAll(Iterable elements) { return this. bsBuilder().ofAll(elements); } @Override protected > BitSet ofJavaStream(java.util.stream.Stream javaStream) { return this. bsBuilder().ofAll(javaStream); } @Override protected BitSet ofAll(boolean... elements) { return BitSet.ofAll(elements); } @Override protected BitSet ofAll(byte... elements) { return BitSet.ofAll(elements); } @Override protected BitSet ofAll(char... elements) { return BitSet.ofAll(elements); } @Override protected BitSet ofAll(double... elements) { return this. bsBuilder().ofAll(Iterator.ofAll(elements)); } @Override protected BitSet ofAll(float... elements) { return this. bsBuilder().ofAll(Iterator.ofAll(elements)); } @Override protected BitSet ofAll(int... elements) { return BitSet.ofAll(elements); } @Override protected BitSet ofAll(long... elements) { return BitSet.ofAll(elements); } @Override protected BitSet ofAll(short... elements) { return BitSet.ofAll(elements); } @Override protected BitSet tabulate(int n, Function f) { return this. bsBuilder().tabulate(n, f); } @Override protected BitSet fill(int n, Supplier s) { return this. bsBuilder().fill(n, s); } @Override protected BitSet range(char from, char toExclusive) { return BitSet.range(from, toExclusive); } @Override protected BitSet rangeBy(char from, char toExclusive, int step) { return BitSet.rangeBy(from, toExclusive, step); } @Override protected BitSet rangeBy(double from, double toExclusive, double step) { return this. bsBuilder().ofAll(Iterator.rangeBy(from, toExclusive, step)); } private static boolean isBadRange(int a, int b) { return a < 0 || b < 0 || a > MAX_BIT || b > MAX_BIT; } private static boolean isBadRange(long a, long b) { return a < 0 || b < 0 || a > MAX_BIT || b > MAX_BIT; } @Override protected BitSet range(int from, int toExclusive) { if (isBadRange(from, toExclusive)) { return this. bsBuilder().ofAll(Iterator.range(from, toExclusive)); } else { return BitSet.range(from, toExclusive); } } @Override protected BitSet rangeBy(int from, int toExclusive, int step) { if (isBadRange(from, toExclusive)) { return this. bsBuilder().ofAll(Iterator.rangeBy(from, toExclusive, step)); } else { return BitSet.rangeBy(from, toExclusive, step); } } @Override protected BitSet range(long from, long toExclusive) { if (isBadRange(from, toExclusive)) { return this. bsBuilder().ofAll(Iterator.range(from, toExclusive)); } else { return BitSet.range(from, toExclusive); } } @Override protected BitSet rangeBy(long from, long toExclusive, long step) { if (isBadRange(from, toExclusive)) { return this. bsBuilder().ofAll(Iterator.rangeBy(from, toExclusive, step)); } else { return BitSet.rangeBy(from, toExclusive, step); } } @Override protected BitSet rangeClosed(char from, char toInclusive) { return BitSet.rangeClosed(from, toInclusive); } @Override protected BitSet rangeClosedBy(char from, char toInclusive, int step) { return BitSet.rangeClosedBy(from, toInclusive, step); } @Override protected BitSet rangeClosedBy(double from, double toInclusive, double step) { return this. bsBuilder().ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @Override protected BitSet rangeClosed(int from, int toInclusive) { if (isBadRange(from, toInclusive)) { return this. bsBuilder().ofAll(Iterator.rangeClosed(from, toInclusive)); } else { return BitSet.rangeClosed(from, toInclusive); } } @Override protected BitSet rangeClosedBy(int from, int toInclusive, int step) { if (isBadRange(from, toInclusive)) { return this. bsBuilder().ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } else { return BitSet.rangeClosedBy(from, toInclusive, step); } } @Override protected BitSet rangeClosed(long from, long toInclusive) { if (isBadRange(from, toInclusive)) { return this. bsBuilder().ofAll(Iterator.rangeClosed(from, toInclusive)); } else { return BitSet.rangeClosed(from, toInclusive); } } @Override protected BitSet rangeClosedBy(long from, long toInclusive, long step) { if (isBadRange(from, toInclusive)) { return this. bsBuilder().ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } else { return BitSet.rangeClosedBy(from, toInclusive, step); } } // BitSet specific @Test public void testBitSet1() { BitSet bs = BitSet.empty(); bs = bs.add(2); assertThat(bs.head()).isEqualTo(2); assertThat(bs.length()).isEqualTo(1); bs = bs.add(4); assertThat(bs.head()).isEqualTo(2); assertThat(bs.length()).isEqualTo(2); bs = bs.remove(2); assertThat(bs.head()).isEqualTo(4); assertThat(bs.contains(2)).isFalse(); assertThat(bs.length()).isEqualTo(1); bs = bs.remove(4); assertThat(bs.isEmpty()).isTrue(); assertThat(bs.length()).isEqualTo(0); } @Test public void testBitSet2() { BitSet bs = BitSet.empty(); bs = bs.add(2); assertThat(bs.head()).isEqualTo(2); assertThat(bs.add(2)).isSameAs(bs); assertThat(bs.length()).isEqualTo(1); bs = bs.add(70); assertThat(bs.head()).isEqualTo(2); assertThat(bs.add(2)).isSameAs(bs); assertThat(bs.add(70)).isSameAs(bs); assertThat(bs.length()).isEqualTo(2); bs = bs.remove(2); assertThat(bs.head()).isEqualTo(70); assertThat(bs.contains(2)).isFalse(); assertThat(bs.length()).isEqualTo(1); bs = bs.remove(70); assertThat(bs.isEmpty()).isTrue(); assertThat(bs.length()).isEqualTo(0); bs = bs.add(2); bs = bs.add(70); bs = bs.add(3); assertThat(bs.length()).isEqualTo(3); bs = bs.add(71); assertThat(bs.length()).isEqualTo(4); bs = bs.add(701); assertThat(bs.length()).isEqualTo(5); } @Test public void testBitSetN() { BitSet bs = BitSet.empty(); bs = bs.add(2); assertThat(bs.head()).isEqualTo(2); bs = bs.add(700); assertThat(bs.head()).isEqualTo(2); assertThat(bs.add(2)).isSameAs(bs); assertThat(bs.add(700)).isSameAs(bs); bs = bs.remove(2); assertThat(bs.head()).isEqualTo(700); assertThat(bs.contains(2)).isFalse(); bs = bs.remove(700); assertThat(bs.isEmpty()).isTrue(); } @Test public void testFactories() { assertThat(BitSet.of(7).contains(7)).isTrue(); // BitSet1, < 64 assertThat(BitSet.of(77).contains(77)).isTrue(); // BitSet2, < 2*64 assertThat(BitSet.of(777).contains(777)).isTrue(); // BitSetN, >= 2*64 assertThat(BitSet.ofAll(List.of(1).toJavaStream())).isEqualTo(BitSet.of(1)); assertThat(BitSet.fill(1, () -> 1)).isEqualTo(BitSet.of(1)); assertThat(BitSet.tabulate(1, i -> 1)).isEqualTo(BitSet.of(1)); } @Test public void shouldAllAll() { assertThat(BitSet.empty().add(7).addAll(List.of(1, 2))).isEqualTo(BitSet.of(1, 2, 7)); assertThat(BitSet.empty().add(77).addAll(List.of(1, 2))).isEqualTo(BitSet.of(1, 2, 77)); assertThat(BitSet.empty().add(777).addAll(List.of(1, 2))).isEqualTo(BitSet.of(1, 2, 777)); } @Test public void shouldCollectInts() { final Traversable actual = java.util.stream.Stream.of(1, 2, 3).collect(BitSet.collector()); assertThat(actual).isEqualTo(of(1, 2, 3)); } @Test public void testEnums() { BitSet bs = BitSet.withEnum(E.class).empty(); bs = bs.add(E.V2); assert bs.head() == E.V2; bs = bs.add(E.V3); assert bs.head() == E.V2; bs = bs.remove(E.V2); assert bs.head() == E.V3; assert !bs.contains(E.V2); assert bs.contains(E.V3); } @Test(expected = IllegalArgumentException.class) public void shouldThrowAddNegativeElementToEmpty() { BitSet.empty().add(-1); } @Test(expected = IllegalArgumentException.class) public void shouldThrowAddNegativeElementToBitSet2() { BitSet.empty().add(77).add(-1); } @Test(expected = IllegalArgumentException.class) public void shouldThrowAddNegativeElementToBitSetN() { BitSet.empty().add(777).add(-1); } @Test(expected = IllegalArgumentException.class) public void shouldThrowAddNegativeElements() { BitSet.empty().addAll(List.of(-1)); } @Test(expected = IllegalArgumentException.class) public void shouldThrowContainsNegativeElements() { BitSet.empty().contains(-1); } @Test public void shouldSerializeDeserializeNativeBitSet() { final Object actual = deserialize(serialize(BitSet.of(1, 2, 3))); final Object expected = BitSet.of(1, 2, 3); assertThat(actual).isEqualTo(expected); } @Test public void shouldSerializeDeserializeEnumBitSet() { final Object actual = deserialize(serialize(BitSet.withEnum(E.class).of(E.V1, E.V2))); final Object expected = BitSet.withEnum(E.class).of(E.V1, E.V2); assertThat(actual).isEqualTo(expected); } @Test public void shouldBehaveExactlyLikeAnotherBitSet() { for (int i = 0; i < 10; i++) { final Random random = getRandom(123456789); final java.util.BitSet mutableBitSet = new java.util.BitSet(); BitSet functionalBitSet = BitSet.empty(); final int size = 5_000; for (int j = 0; j < size; j++) { /* Insert */ if (random.nextInt() % 3 == 0) { assertMinimumsAreEqual(mutableBitSet, functionalBitSet); final int value = random.nextInt(size); mutableBitSet.set(value); functionalBitSet = functionalBitSet.add(value); } assertMinimumsAreEqual(mutableBitSet, functionalBitSet); /* Delete */ if (random.nextInt() % 5 == 0) { if (!mutableBitSet.isEmpty()) { mutableBitSet.clear(mutableBitSet.nextSetBit(0)); } if (!functionalBitSet.isEmpty()) { functionalBitSet = functionalBitSet.tail(); } assertMinimumsAreEqual(mutableBitSet, functionalBitSet); } } final Collection oldValues = mutableBitSet.stream().sorted().boxed().collect(toList()); final Collection newValues = functionalBitSet.toJavaList(); assertThat(oldValues).isEqualTo(newValues); } } private void assertMinimumsAreEqual(java.util.BitSet oldSet, BitSet newSet) { assertThat(oldSet.isEmpty()).isEqualTo(newSet.isEmpty()); if (!newSet.isEmpty()) { assertThat(oldSet.nextSetBit(0)).isEqualTo(newSet.head()); } } // -- toSortedSet @Override @Test public void shouldConvertToSortedSetWithoutComparatorOnComparable() { final Value value = BitSet.of(3, 7, 1, 15, 0); final Set set = value.toSortedSet(); if (value.isSingleValued()) { assertThat(set).isEqualTo(TreeSet.of(3)); } else { assertThat(set).isEqualTo(TreeSet.of(0, 1, 3, 7, 15)); } } // -- toPriorityQueue @Test @Override public void shouldConvertToPriorityQueueUsingImplicitComparator() { final Value value = BitSet.of(1, 3, 2); final PriorityQueue queue = value.toPriorityQueue(); if (value.isSingleValued()) { assertThat(queue).isEqualTo(PriorityQueue.of(1)); } else { assertThat(queue).isEqualTo(PriorityQueue.of(1, 2, 3)); } } @Test @Override public void shouldConvertToPriorityQueueUsingExplicitComparator() { final Comparator comparator = Comparator.naturalOrder(); final Value value = BitSet.of(1, 3, 2); final PriorityQueue queue = value.toPriorityQueue(comparator); if (value.isSingleValued()) { assertThat(queue).isEqualTo(PriorityQueue.of(comparator, 1)); } else { assertThat(queue).isEqualTo(PriorityQueue.of(comparator, 1, 2, 3)); } } // -- head, init, last, tail @Test public void shouldReturnHeadOfNonEmptyHavingReversedOrder() { // BitSet can't have reverse order } @Test public void shouldReturnInitOfNonEmptyHavingReversedOrder() { // BitSet can't have reverse order } @Test public void shouldReturnLastOfNonEmptyHavingReversedOrder() { // BitSet can't have reverse order } @Test public void shouldReturnTailOfNonEmptyHavingReversedOrder() { // BitSet can't have reverse order } // -- classes private static class Mapper implements Serializable { private static final long serialVersionUID = 1L; private final java.util.Map fromIntMap = new java.util.HashMap<>(); private final java.util.Map toIntMap = new java.util.HashMap<>(); private int nextValue = 0; synchronized T fromInt(Integer i) { if (i < nextValue) { return fromIntMap.get(i); } else { throw new RuntimeException(); } } synchronized Integer toInt(T value) { Integer i = toIntMap.get(value); if (i == null) { i = nextValue++; toIntMap.put(value, i); fromIntMap.put(i, value); } return i; } } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/CharSeqTest.java000066400000000000000000004167351342074374400250140ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Serializables; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import org.assertj.core.api.*; import org.junit.Test; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.function.Supplier; import static io.vavr.OutputTester.*; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class CharSeqTest { protected IterableAssert assertThat(Iterable actual) { return new IterableAssert(actual) {}; } protected ObjectAssert assertThat(T actual) { return new ObjectAssert(actual) {}; } protected BooleanAssert assertThat(Boolean actual) { return new BooleanAssert(actual) {}; } protected DoubleAssert assertThat(Double actual) { return new DoubleAssert(actual) {}; } protected IntegerAssert assertThat(Integer actual) { return new IntegerAssert(actual) {}; } protected LongAssert assertThat(Long actual) { return new LongAssert(actual) {}; } protected StringAssert assertThat(String actual) { return new StringAssert(actual) {}; } // -- ofAll @Test public void shouldThrowWhenCreatingCharSeqFromIterableThatContainsNull() { assertThatThrownBy(() -> CharSeq.ofAll(Arrays.asList('1', null))).isInstanceOf(NullPointerException.class); } // -- asJavaMutable* @Test public void shouldConvertAsJava() { final java.util.List list = CharSeq.of('1', '2', '3').asJavaMutable(); list.add('4'); assertThat(list).isEqualTo(Arrays.asList('1', '2', '3', '4')); } @Test public void shouldConvertAsJavaWithConsumer() { final CharSeq seq = CharSeq.of('1', '2', '3').asJavaMutable(list -> { assertThat(list).isEqualTo(Arrays.asList('1', '2', '3')); list.add('4'); }); assertThat(seq).isEqualTo(CharSeq.of('1', '2', '3', '4')); } @Test public void shouldConvertAsJavaAndRethrowException() { assertThatThrownBy(() -> CharSeq.of('1', '2', '3').asJavaMutable(list -> { throw new RuntimeException("test");})) .isInstanceOf(RuntimeException.class) .hasMessage("test"); } @Test public void shouldConvertAsJavaImmutable() { final java.util.List list = CharSeq.of('1', '2', '3').asJava(); assertThat(list).isEqualTo(Arrays.asList('1', '2', '3')); assertThatThrownBy(() -> list.add('4')).isInstanceOf(UnsupportedOperationException.class); } @Test public void shouldConvertAsJavaImmutableWithConsumer() { final CharSeq seq = CharSeq.of('1', '2', '3').asJava(list -> { assertThat(list).isEqualTo(Arrays.asList('1', '2', '3')); assertThatThrownBy(() -> list.add('4')).isInstanceOf(UnsupportedOperationException.class); }); assertThat(seq).isEqualTo(CharSeq.of('1', '2', '3')); } @Test public void shouldConvertAsJavaImmutableAndRethrowException() { assertThatThrownBy(() -> CharSeq.of('1', '2', '3').asJava(list -> { throw new RuntimeException("test");})) .isInstanceOf(RuntimeException.class) .hasMessage("test"); } // -- exists @Test public void shouldBeAwareOfExistingElement() { assertThat(CharSeq.of('1', '2').exists(i -> i == '2')).isTrue(); } @Test public void shouldBeAwareOfNonExistingElement() { assertThat(CharSeq.empty().exists(i -> i == 1)).isFalse(); } // -- forAll @Test public void shouldBeAwareOfPropertyThatHoldsForAll() { assertThat(CharSeq.of('2', '4').forAll(i -> i % 2 == 0)).isTrue(); } @Test public void shouldBeAwareOfPropertyThatNotHoldsForAll() { assertThat(CharSeq.of('2', '3').forAll(i -> i % 2 == 0)).isFalse(); } // -- padTo @Test public void shouldPadEmptyToEmpty() { assertThat(CharSeq.empty().padTo(0, 'a')).isSameAs(CharSeq.empty()); } @Test public void shouldPadEmptyToNonEmpty() { assertThat(CharSeq.empty().padTo(2, 'a')).isEqualTo(CharSeq.of('a', 'a')); } @Test public void shouldPadNonEmptyZeroLen() { final CharSeq seq = CharSeq.of('a'); assertThat(seq.padTo(0, 'b')).isSameAs(seq); } @Test public void shouldPadNonEmpty() { assertThat(CharSeq.of('a').padTo(2, 'a')).isEqualTo(CharSeq.of('a', 'a')); assertThat(CharSeq.of('a').padTo(2, 'b')).isEqualTo(CharSeq.of('a', 'b')); assertThat(CharSeq.of('a').padTo(3, 'b')).isEqualTo(CharSeq.of('a', 'b', 'b')); } @Test public void shouldThrowWhenPadToAddingNulls() { assertThatThrownBy(() -> CharSeq.of('a').padTo(2, null)).isInstanceOf(NullPointerException.class); } // -- leftPadTo @Test public void shouldLeftPadEmptyToEmpty() { assertThat(CharSeq.empty().leftPadTo(0, 'a')).isSameAs(CharSeq.empty()); } @Test public void shouldLeftPadEmptyToNonEmpty() { assertThat(CharSeq.empty().leftPadTo(2, 'a')).isEqualTo(CharSeq.of('a', 'a')); } @Test public void shouldLeftPadNonEmptyZeroLen() { final CharSeq seq = CharSeq.of('a'); assertThat(seq.leftPadTo(0, 'b')).isSameAs(seq); } @Test public void shouldLeftPadNonEmpty() { assertThat(CharSeq.of('a').leftPadTo(2, 'a')).isEqualTo(CharSeq.of('a', 'a')); assertThat(CharSeq.of('a').leftPadTo(2, 'b')).isEqualTo(CharSeq.of('b', 'a')); assertThat(CharSeq.of('a').leftPadTo(3, 'b')).isEqualTo(CharSeq.of('b', 'b', 'a')); } @Test public void shouldThrowWhenLeftPadToAddingNulls() { assertThatThrownBy(() -> CharSeq.of('a').leftPadTo(2, null)).isInstanceOf(NullPointerException.class); } // -- orElse @Test public void shouldCaclEmptyOrElseSameOther() { CharSeq other = CharSeq.of("42"); assertThat(CharSeq.empty().orElse(other)).isSameAs(other); } @Test public void shouldCaclEmptyOrElseEqualOther() { assertThat(CharSeq.empty().orElse(Arrays.asList('1', '2'))).isEqualTo(CharSeq.of("12")); } @Test public void shouldCaclNonemptyOrElseOther() { CharSeq src = CharSeq.of("42"); assertThat(src.orElse(CharSeq.of("12"))).isSameAs(src); } @Test public void shouldCaclEmptyOrElseSupplier() { Supplier other = () -> CharSeq.of("42"); assertThat(CharSeq.empty().orElse(other)).isEqualTo(CharSeq.of("42")); } @Test public void shouldCaclNonemptyOrElseSupplier() { CharSeq src = CharSeq.of("42"); assertThat(src.orElse(() -> CharSeq.of("12"))).isSameAs(src); } // -- patch @Test public void shouldPatchEmptyByEmpty() { assertThat(CharSeq.empty().patch(0, CharSeq.empty(), 0)).isSameAs(CharSeq.empty()); assertThat(CharSeq.empty().patch(-1, CharSeq.empty(), -1)).isSameAs(CharSeq.empty()); assertThat(CharSeq.empty().patch(-1, CharSeq.empty(), 1)).isSameAs(CharSeq.empty()); assertThat(CharSeq.empty().patch(1, CharSeq.empty(), -1)).isSameAs(CharSeq.empty()); assertThat(CharSeq.empty().patch(1, CharSeq.empty(), 1)).isSameAs(CharSeq.empty()); } @Test public void shouldPatchEmptyByNonEmpty() { final Seq s = CharSeq.of('1', '2', '3'); assertThat(CharSeq.empty().patch(0, s, 0)).isEqualTo(s); assertThat(CharSeq.empty().patch(-1, s, -1)).isEqualTo(s); assertThat(CharSeq.empty().patch(-1, s, 1)).isEqualTo(s); assertThat(CharSeq.empty().patch(1, s, -1)).isEqualTo(s); assertThat(CharSeq.empty().patch(1, s, 1)).isEqualTo(s); } @Test public void shouldPatchNonEmptyByEmpty() { final Seq s = CharSeq.of('1', '2', '3'); assertThat(s.patch(-1, CharSeq.empty(), -1)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(-1, CharSeq.empty(), 0)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(-1, CharSeq.empty(), 1)).isEqualTo(CharSeq.of('2', '3')); assertThat(s.patch(-1, CharSeq.empty(), 3)).isSameAs(CharSeq.empty()); assertThat(s.patch(0, CharSeq.empty(), -1)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(0, CharSeq.empty(), 0)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(0, CharSeq.empty(), 1)).isEqualTo(CharSeq.of('2', '3')); assertThat(s.patch(0, CharSeq.empty(), 3)).isSameAs(CharSeq.empty()); assertThat(s.patch(1, CharSeq.empty(), -1)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(1, CharSeq.empty(), 0)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(1, CharSeq.empty(), 1)).isEqualTo(CharSeq.of('1', '3')); assertThat(s.patch(1, CharSeq.empty(), 3)).isEqualTo(CharSeq.of('1')); assertThat(s.patch(4, CharSeq.empty(), -1)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(4, CharSeq.empty(), 0)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(4, CharSeq.empty(), 1)).isEqualTo(CharSeq.of('1', '2', '3')); assertThat(s.patch(4, CharSeq.empty(), 3)).isEqualTo(CharSeq.of('1', '2', '3')); } @Test public void shouldPatchNonEmptyByNonEmpty() { final Seq s = CharSeq.of('1', '2', '3'); final Seq d = CharSeq.of('4', '5', '6'); assertThat(s.patch(-1, d, -1)).isEqualTo(CharSeq.of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(-1, d, 0)).isEqualTo(CharSeq.of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(-1, d, 1)).isEqualTo(CharSeq.of('4', '5', '6', '2', '3')); assertThat(s.patch(-1, d, 3)).isEqualTo(CharSeq.of('4', '5', '6')); assertThat(s.patch(0, d, -1)).isEqualTo(CharSeq.of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(0, d, 0)).isEqualTo(CharSeq.of('4', '5', '6', '1', '2', '3')); assertThat(s.patch(0, d, 1)).isEqualTo(CharSeq.of('4', '5', '6', '2', '3')); assertThat(s.patch(0, d, 3)).isEqualTo(CharSeq.of('4', '5', '6')); assertThat(s.patch(1, d, -1)).isEqualTo(CharSeq.of('1', '4', '5', '6', '2', '3')); assertThat(s.patch(1, d, 0)).isEqualTo(CharSeq.of('1', '4', '5', '6', '2', '3')); assertThat(s.patch(1, d, 1)).isEqualTo(CharSeq.of('1', '4', '5', '6', '3')); assertThat(s.patch(1, d, 3)).isEqualTo(CharSeq.of('1', '4', '5', '6')); assertThat(s.patch(4, d, -1)).isEqualTo(CharSeq.of('1', '2', '3', '4', '5', '6')); assertThat(s.patch(4, d, 0)).isEqualTo(CharSeq.of('1', '2', '3', '4', '5', '6')); assertThat(s.patch(4, d, 1)).isEqualTo(CharSeq.of('1', '2', '3', '4', '5', '6')); assertThat(s.patch(4, d, 3)).isEqualTo(CharSeq.of('1', '2', '3', '4', '5', '6')); } @Test public void shouldThrowWhenPatchingWithNulls() { assertThatThrownBy(() -> CharSeq.of('1').patch(0, List.of((Character) null), 1)).isInstanceOf(NullPointerException.class); } // -- peek @Test public void shouldPeekNil() { assertThat(CharSeq.empty().peek(t -> {})).isSameAs(CharSeq.empty()); } @Test public void shouldPeekNonNilPerformingNoAction() { assertThat(CharSeq.of('1').peek(t -> {})).isEqualTo(CharSeq.of('1')); } @Test public void shouldPeekSingleValuePerformingAnAction() { final char[] effect = { 0 }; final CharSeq actual = CharSeq.of('1').peek(i -> effect[0] = i); assertThat(actual).isEqualTo(CharSeq.of('1')); assertThat(effect[0]).isEqualTo('1'); } // -- static rangeClosed() @Test public void shouldCreateRangeClosedWhereFromIsGreaterThanTo() { assertThat(CharSeq.rangeClosed('b', 'a')).isEmpty(); } @Test public void shouldCreateRangeClosedWhereFromEqualsTo() { assertThat(CharSeq.rangeClosed('a', 'a')).isEqualTo(CharSeq.of('a')); } @Test public void shouldCreateRangeClosedWhereFromIsLessThanTo() { assertThat(CharSeq.rangeClosed('a', 'c')).isEqualTo(CharSeq.of('a', 'b', 'c')); } @Test public void shouldCreateRangeClosedWhereFromAndToEqualMIN_VALUE() { assertThat(CharSeq.rangeClosed(Character.MIN_VALUE, Character.MIN_VALUE)).isEqualTo(CharSeq.of(Character.MIN_VALUE)); } @Test public void shouldCreateRangeClosedWhereFromAndToEqualMAX_VALUE() { assertThat(CharSeq.rangeClosed(Character.MAX_VALUE, Character.MAX_VALUE)).isEqualTo(CharSeq.of(Character.MAX_VALUE)); } // -- static rangeClosedBy() @Test public void shouldCreateRangeClosedByWhereFromIsGreaterThanToAndStepWrongDirection() { assertThat(CharSeq.rangeClosedBy('b', 'a', 1)).isEmpty(); assertThat(CharSeq.rangeClosedBy('b', 'a', 3)).isEmpty(); assertThat(CharSeq.rangeClosedBy('a', 'b', -1)).isEmpty(); assertThat(CharSeq.rangeClosedBy('a', 'b', -3)).isEmpty(); } @Test public void shouldCreateRangeClosedByWhereFromEqualsTo() { assertThat(CharSeq.rangeClosedBy('a', 'a', 1)).isEqualTo(CharSeq.of('a')); assertThat(CharSeq.rangeClosedBy('a', 'a', 3)).isEqualTo(CharSeq.of('a')); assertThat(CharSeq.rangeClosedBy('a', 'a', -1)).isEqualTo(CharSeq.of('a')); assertThat(CharSeq.rangeClosedBy('a', 'a', -3)).isEqualTo(CharSeq.of('a')); } @Test public void shouldCreateRangeClosedByWhereFromIsLessThanToAndStepCorrectDirection() { assertThat(CharSeq.rangeClosedBy('a', 'c', 1)).isEqualTo(CharSeq.of('a', 'b', 'c')); assertThat(CharSeq.rangeClosedBy('a', 'e', 2)).isEqualTo(CharSeq.of('a', 'c', 'e')); assertThat(CharSeq.rangeClosedBy('a', 'f', 2)).isEqualTo(CharSeq.of('a', 'c', 'e')); assertThat(CharSeq.rangeClosedBy((char) (Character.MAX_VALUE - 2), Character.MAX_VALUE, 3)).isEqualTo(CharSeq.of((char) (Character.MAX_VALUE - 2))); assertThat(CharSeq.rangeClosedBy((char) (Character.MAX_VALUE - 3), Character.MAX_VALUE, 3)).isEqualTo(CharSeq.of((char) (Character.MAX_VALUE - 3), Character.MAX_VALUE)); assertThat(CharSeq.rangeClosedBy('c', 'a', -1)).isEqualTo(CharSeq.of('c', 'b', 'a')); assertThat(CharSeq.rangeClosedBy('e', 'a', -2)).isEqualTo(CharSeq.of('e', 'c', 'a')); assertThat(CharSeq.rangeClosedBy('e', (char) ('a' - 1), -2)).isEqualTo(CharSeq.of('e', 'c', 'a')); assertThat(CharSeq.rangeClosedBy((char) (Character.MIN_VALUE + 2), Character.MIN_VALUE, -3)).isEqualTo(CharSeq.of((char) (Character.MIN_VALUE + 2))); assertThat(CharSeq.rangeClosedBy((char) (Character.MIN_VALUE + 3), Character.MIN_VALUE, -3)).isEqualTo(CharSeq.of((char) (Character.MIN_VALUE + 3), Character.MIN_VALUE)); } @Test public void shouldCreateRangeClosedByWhereFromAndToEqualMIN_VALUE() { assertThat(CharSeq.rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, 1)).isEqualTo(CharSeq.of(Character.MIN_VALUE)); assertThat(CharSeq.rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, 3)).isEqualTo(CharSeq.of(Character.MIN_VALUE)); assertThat(CharSeq.rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, -1)).isEqualTo(CharSeq.of(Character.MIN_VALUE)); assertThat(CharSeq.rangeClosedBy(Character.MIN_VALUE, Character.MIN_VALUE, -3)).isEqualTo(CharSeq.of(Character.MIN_VALUE)); } @Test public void shouldCreateRangeClosedByWhereFromAndToEqualMAX_VALUE() { assertThat(CharSeq.rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, 1)).isEqualTo(CharSeq.of(Character.MAX_VALUE)); assertThat(CharSeq.rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, 3)).isEqualTo(CharSeq.of(Character.MAX_VALUE)); assertThat(CharSeq.rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, -1)).isEqualTo(CharSeq.of(Character.MAX_VALUE)); assertThat(CharSeq.rangeClosedBy(Character.MAX_VALUE, Character.MAX_VALUE, -3)).isEqualTo(CharSeq.of(Character.MAX_VALUE)); } // -- static range() @Test public void shouldCreateRangeWhereFromIsGreaterThanTo() { assertThat(CharSeq.range('b', 'a').isEmpty()); } @Test public void shouldCreateRangeWhereFromEqualsTo() { assertThat(CharSeq.range('a', 'a')).isEmpty(); } @Test public void shouldCreateRangeWhereFromIsLessThanTo() { assertThat(CharSeq.range('a', 'c')).isEqualTo(CharSeq.of('a', 'b')); } @Test public void shouldCreateRangeWhereFromAndToEqualMIN_VALUE() { assertThat(CharSeq.range(Character.MIN_VALUE, Character.MIN_VALUE)).isEmpty(); } @Test public void shouldCreateRangeWhereFromAndToEqualMAX_VALUE() { assertThat(CharSeq.range(Character.MAX_VALUE, Character.MAX_VALUE)).isEmpty(); } // -- static rangeBy() @Test public void shouldCreateRangeByWhereFromIsGreaterThanToAndStepWrongDirection() { assertThat(CharSeq.rangeBy('b', 'a', 1)).isEmpty(); assertThat(CharSeq.rangeBy('b', 'a', 3)).isEmpty(); assertThat(CharSeq.rangeBy('a', 'b', -1)).isEmpty(); assertThat(CharSeq.rangeBy('a', 'b', -3)).isEmpty(); } @Test public void shouldCreateRangeByWhereFromEqualsTo() { assertThat(CharSeq.rangeBy('a', 'a', 1)).isEmpty(); assertThat(CharSeq.rangeBy('a', 'a', 3)).isEmpty(); assertThat(CharSeq.rangeBy('a', 'a', -1)).isEmpty(); assertThat(CharSeq.rangeBy('a', 'a', -3)).isEmpty(); } @Test public void shouldCreateRangeByWhereFromIsLessThanToAndStepCorrectDirection() { assertThat(CharSeq.rangeBy('a', 'c', 1)).isEqualTo(CharSeq.of('a', 'b')); assertThat(CharSeq.rangeBy('a', 'd', 2)).isEqualTo(CharSeq.of('a', 'c')); assertThat(CharSeq.rangeBy('c', 'a', -1)).isEqualTo(CharSeq.of('c', 'b')); assertThat(CharSeq.rangeBy('d', 'a', -2)).isEqualTo(CharSeq.of('d', 'b')); assertThat(CharSeq.rangeBy((char) (Character.MAX_VALUE - 3), Character.MAX_VALUE, 3)).isEqualTo(CharSeq.of((char) (Character.MAX_VALUE - 3))); assertThat(CharSeq.rangeBy((char) (Character.MAX_VALUE - 4), Character.MAX_VALUE, 3)).isEqualTo(CharSeq.of((char) (Character.MAX_VALUE - 4), (char) (Character.MAX_VALUE - 1))); assertThat(CharSeq.rangeBy((char) (Character.MIN_VALUE + 3), Character.MIN_VALUE, -3)).isEqualTo(CharSeq.of((char) (Character.MIN_VALUE + 3))); assertThat(CharSeq.rangeBy((char) (Character.MIN_VALUE + 4), Character.MIN_VALUE, -3)).isEqualTo(CharSeq.of((char) (Character.MIN_VALUE + 4), (char) (Character.MIN_VALUE + 1))); } @Test public void shouldCreateRangeByWhereFromAndToEqualMIN_VALUE() { assertThat(CharSeq.rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, 1)).isEmpty(); assertThat(CharSeq.rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, 3)).isEmpty(); assertThat(CharSeq.rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, -1)).isEmpty(); assertThat(CharSeq.rangeBy(Character.MIN_VALUE, Character.MIN_VALUE, -3)).isEmpty(); } @Test public void shouldCreateRangeByWhereFromAndToEqualMAX_VALUE() { assertThat(CharSeq.rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, 1)).isEmpty(); assertThat(CharSeq.rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, 3)).isEmpty(); assertThat(CharSeq.rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, -1)).isEmpty(); assertThat(CharSeq.rangeBy(Character.MAX_VALUE, Character.MAX_VALUE, -3)).isEmpty(); } // step == 0 @Test(expected = IllegalArgumentException.class) public void shouldProhibitCharRangeByStepZero() { CharSeq.rangeBy('a', 'b', 0); } @Test(expected = IllegalArgumentException.class) public void shouldProhibitCharRangeClosedByStepZero() { CharSeq.rangeClosedBy('a', 'b', 0); } // -- average @Test public void shouldReturnNoneWhenComputingAverageOfNil() { assertThat(CharSeq.empty().average()).isEqualTo(Option.none()); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenComputingAverageOfStrings() { CharSeq.of('a', 'b', 'c').average(); } // -- contains @Test public void shouldRecognizeNilContainsNoElement() { final boolean actual = CharSeq.empty().contains((Character) null); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilDoesNotContainElement() { final boolean actual = CharSeq.of('1', '2', '3').contains('0'); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilDoesContainElement() { final boolean actual = CharSeq.of('1', '2', '3').contains('2'); assertThat(actual).isTrue(); } @Test public void shouldRecognizeNonNilDoesNotContainCharSequence() { final boolean actual = CharSeq.of('1', '2', '3').contains("13"); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilDoesContainCharSequence() { final boolean actual = CharSeq.of('1', '2', '3').contains("23"); assertThat(actual).isTrue(); } @Test public void shouldNotContainNull() { assertThat(CharSeq.of('a').contains((Character) null)).isFalse(); } // -- containsAll @Test public void shouldRecognizeNilNotContainsAllElements() { final boolean actual = CharSeq.empty().containsAll(CharSeq.of('1', '2', '3')); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilNotContainsAllOverlappingElements() { final boolean actual = CharSeq.of('1', '2', '3').containsAll(CharSeq.of('2', '3', '4')); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilContainsAllOnSelf() { final boolean actual = CharSeq.of('1', '2', '3').containsAll(CharSeq.of('1', '2', '3')); assertThat(actual).isTrue(); } // -- distinct @Test public void shouldComputeDistinctOfEmptyTraversable() { assertThat(CharSeq.empty().distinct()).isSameAs(CharSeq.empty()); } @Test public void shouldComputeDistinctOfNonEmptyTraversable() { assertThat(CharSeq.of('1', '1', '2', '2', '3', '3').distinct()).isEqualTo(CharSeq.of('1', '2', '3')); } // -- distinct(Comparator) @Test public void shouldComputeDistinctByOfEmptyTraversableUsingComparator() { final Comparator comparator = Comparator.comparingInt(i -> i); assertThat(CharSeq.empty().distinctBy(comparator)).isSameAs(CharSeq.empty()); } @Test public void shouldComputeDistinctByOfNonEmptyTraversableUsingComparator() { final Comparator comparator = (s1, s2) -> (s1 - s2); assertThat(CharSeq.of('1', '2', '3', '3', '4', '5').distinctBy(comparator)) .isEqualTo(CharSeq.of('1', '2', '3', '4', '5')); } // -- distinct(Function) @Test public void shouldComputeDistinctByOfEmptyTraversableUsingKeyExtractor() { assertThat(CharSeq.empty().distinctBy(Function.identity())).isSameAs(CharSeq.empty()); } @Test public void shouldComputeDistinctByOfNonEmptyTraversableUsingKeyExtractor() { assertThat(CharSeq.of('1', '2', '3', '3', '4', '5').distinctBy(c -> c)) .isEqualTo(CharSeq.of('1', '2', '3', '4', '5')); } // -- drop @Test public void shouldDropNoneOnNil() { assertThat(CharSeq.empty().drop(1)).isSameAs(CharSeq.empty()); } @Test public void shouldDropNoneIfCountIsNegative() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.drop(-1)).isSameAs(t); } @Test public void shouldDropAsExpectedIfCountIsLessThanSize() { assertThat(CharSeq.of('1', '2', '3').drop(2)).isEqualTo(CharSeq.of('3')); } @Test public void shouldDropAllIfCountExceedsSize() { assertThat(CharSeq.of('1', '2', '3').drop('4')).isSameAs(CharSeq.empty()); } // -- dropUntil @Test public void shouldDropUntilNoneOnNil() { assertThat(CharSeq.empty().dropUntil(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldDropUntilNoneIfPredicateIsTrue() { assertThat(CharSeq.of('1', '2', '3').dropUntil(ignored -> true)).isEqualTo(CharSeq.of('1', '2', '3')); } @Test public void shouldDropUntilAllIfPredicateIsFalse() { assertThat(CharSeq.of('1', '2', '3').dropUntil(ignored -> false)).isSameAs(CharSeq.empty()); } @Test public void shouldDropUntilCorrect() { assertThat(CharSeq.of('1', '2', '3').dropUntil(i -> i >= '2')).isEqualTo(CharSeq.of('2', '3')); } // -- dropWhile @Test public void shouldDropWhileNoneOnNil() { assertThat(CharSeq.empty().dropWhile(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldDropWhileNoneIfPredicateIsFalse() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.dropWhile(ignored -> false)).isSameAs(t); } @Test public void shouldDropWhileAllIfPredicateIsTrue() { assertThat(CharSeq.of('1', '2', '3').dropWhile(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldDropWhileCorrect() { assertThat(CharSeq.of('1', '2', '3').dropWhile(i -> i == '1')).isEqualTo(CharSeq.of('2', '3')); } // -- dropRight @Test public void shouldDropRightNoneOnNil() { assertThat(CharSeq.empty().dropRight(1)).isSameAs(CharSeq.empty()); } @Test public void shouldDropRightNoneIfCountIsNegative() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.dropRight(-1)).isSameAs(t); } @Test public void shouldDropRightAsExpectedIfCountIsLessThanSize() { assertThat(CharSeq.of('1', '2', '3').dropRight(2)).isEqualTo(CharSeq.of('1')); } @Test public void shouldDropRightAllIfCountExceedsSize() { assertThat(CharSeq.of('1', '2', '3').dropRight(4)).isSameAs(CharSeq.empty()); } // -- dropRightUntil @Test public void shouldDropRightUntilNoneOnNil() { assertThat(CharSeq.empty().dropRightUntil(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldDropRightUntilNoneIfPredicateIsTrue() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.dropRightUntil(ignored -> true)).isSameAs(t); } @Test public void shouldDropRightUntilAllIfPredicateIsFalse() { assertThat(CharSeq.of('1', '2', '3').dropRightUntil(ignored -> false)).isSameAs(CharSeq.empty()); } @Test public void shouldDropRightUntilCorrect() { assertThat(CharSeq.of('1', '2', '3').dropRightUntil(i -> i == '2')).isEqualTo(CharSeq.of('1', '2')); } // -- dropRightWhile @Test public void shouldDropRightWhileNoneOnNil() { assertThat(CharSeq.empty().dropRightWhile(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldDropRightWhileNoneIfPredicateIsFalse() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.dropRightWhile(ignored -> false)).isSameAs(t); } @Test public void shouldDropRightWhileAllIfPredicateIsTrue() { assertThat(CharSeq.of('1', '2', '3').dropRightWhile(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldDropRightWhileAccordingToPredicate() { assertThat(CharSeq.of('1', '2', '3').dropRightWhile(i -> i != '2')).isEqualTo(CharSeq.of('1', '2')); } // -- existsUnique @Test public void shouldBeAwareOfExistingUniqueElement() { assertThat(CharSeq.of('1', '2').existsUnique(i -> i == '1')).isTrue(); } @Test public void shouldBeAwareOfNonExistingUniqueElement() { assertThat(CharSeq.empty().existsUnique(i -> i == '1')).isFalse(); } @Test public void shouldBeAwareOfExistingNonUniqueElement() { assertThat(CharSeq.of('1', '1', '2').existsUnique(i -> i == '1')).isFalse(); } // -- fill @Test public void shouldFillTheCharSeqCallingTheSupplierInTheRightOrder() { final java.util.LinkedList chars = new java.util.LinkedList<>(asList('0', '1')); final CharSeq actual = CharSeq.fill(2, () -> chars.remove()); assertThat(actual).isEqualTo(CharSeq.of('0', '1')); } @Test public void shouldFillTheCharSeqWith0Elements() { assertThat(CharSeq.fill(0, () -> 'a')).isEqualTo(CharSeq.empty()); } @Test public void shouldFillTheCharSeqWith0ElementsWhenNIsNegative() { assertThat(CharSeq.fill(-1, () -> 'a')).isEqualTo(CharSeq.empty()); } @Test public void shouldThrowWhenFillingWithNullValue() { assertThatThrownBy(() -> CharSeq.fill(1, () -> null)).isInstanceOf(NullPointerException.class); } // -- filter @Test public void shouldFilterEmptyTraversable() { assertThat(CharSeq.empty().filter(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldFilterNonEmptyTraversable() { assertThat(CharSeq.of('1', '2', '3', '4').filter(i -> i == '2' || i == '4')).isEqualTo(CharSeq.of('2', '4')); } @Test public void shouldFilterNonEmptyTraversableAllMatch() { final CharSeq t = CharSeq.of('1', '2', '3', '4'); assertThat(t.filter(i -> true)).isSameAs(t); } // -- reject @Test public void shouldRejectEmptyTraversable() { assertThat(CharSeq.empty().reject(ignored -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldRejectNonEmptyTraversable() { assertThat(CharSeq.of('1', '2', '3', '4').reject(i -> i == '2' || i == '4')).isEqualTo(CharSeq.of('1', '3')); } @Test public void shouldRejectNonEmptyTraversableNoneMatch() { final CharSeq t = CharSeq.of('1', '2', '3', '4'); assertThat(t.reject(i -> false)).isSameAs(t); } // -- find @Test public void shouldFindFirstOfNil() { assertThat(CharSeq.empty().find(ignored -> true)).isEqualTo(Option.none()); } @Test public void shouldFindFirstOfNonNil() { assertThat(CharSeq.of('1', '2', '3', '4').find(i -> i % 2 == 0)).isEqualTo(Option.of('2')); } // -- findLast @Test public void shouldFindLastOfNil() { assertThat(CharSeq.empty().findLast(ignored -> true)).isEqualTo(Option.none()); } @Test public void shouldFindLastOfNonNil() { assertThat(CharSeq.of('1', '2', '3', '4').findLast(i -> i % 2 == 0)).isEqualTo(Option.of('4')); } // -- flatMap @Test public void shouldFlatMapEmptyTraversable() { assertThat(CharSeq.empty().flatMap(CharSeq::of)).isEqualTo(Vector.empty()); } @Test public void shouldFlatMapNonEmptyTraversable() { assertThat(CharSeq.of('1', '2', '3').flatMap(CharSeq::of)).isEqualTo(Vector.of('1', '2', '3')); } @Test public void shouldFlatMapTraversableByExpandingElements() { assertThat(CharSeq.of('1', '2', '3').flatMap(i -> { switch (i) { case '1': return CharSeq.of('1', '2', '3'); case '2': return CharSeq.of('4', '5'); default: return CharSeq.of('6'); } })).isEqualTo(Vector.of('1', '2', '3', '4', '5', '6')); } @Test public void shouldFlatMapElementsToSequentialValuesInTheRightOrder() { final AtomicInteger seq = new AtomicInteger('0'); final IndexedSeq actualInts = CharSeq.of('0', '1', '2').flatMap( ignored -> Vector.of((char) seq.getAndIncrement(), (char) seq.getAndIncrement())); final IndexedSeq expectedInts = Vector.of('0', '1', '2', '3', '4', '5'); assertThat(actualInts).isEqualTo(expectedInts); } // -- flatMapChars() @Test public void shouldFlatMapChars() { assertThat(CharSeq.empty().flatMapChars(c -> "X")).isEqualTo(CharSeq.empty()); assertThat(CharSeq.of('1', '2', '3').flatMapChars(c -> c == '1' ? "*" : "-")).isEqualTo(CharSeq.of("*--")); } // -- fold @Test public void shouldFoldNil() { assertThat(CharSeq.empty().fold('0', (a, b) -> b)).isEqualTo('0'); } @Test(expected = NullPointerException.class) public void shouldThrowWhenFoldNullOperator() { CharSeq.empty().fold(null, null); } @Test public void shouldFoldNonNil() { assertThat(CharSeq.of('1', '2', '3').fold('0', (a, b) -> b)).isEqualTo('3'); } // -- foldLeft @Test public void shouldFoldLeftNil() { assertThat(CharSeq.empty().foldLeft("", (xs, x) -> xs + x)).isEqualTo(""); } @Test(expected = NullPointerException.class) public void shouldThrowWhenFoldLeftNullOperator() { CharSeq.empty().foldLeft(null, null); } @Test public void shouldFoldLeftNonNil() { assertThat(CharSeq.of('a', 'b', 'c').foldLeft("", (xs, x) -> xs + x)).isEqualTo("abc"); } // -- foldRight @Test public void shouldFoldRightNil() { assertThat(CharSeq.empty().foldRight("", (x, xs) -> x + xs)).isEqualTo(""); } @Test(expected = NullPointerException.class) public void shouldThrowWhenFoldRightNullOperator() { CharSeq.empty().foldRight(null, null); } @Test public void shouldFoldRightNonNil() { assertThat(CharSeq.of('a', 'b', 'c').foldRight("", (x, xs) -> x + xs)).isEqualTo("abc"); } // -- head @Test(expected = NoSuchElementException.class) public void shouldThrowWhenHeadOnNil() { CharSeq.empty().head(); } @Test public void shouldReturnHeadOfNonNil() { assertThat(CharSeq.of('1', '2', '3').head()).isEqualTo('1'); } // -- headOption @Test public void shouldReturnNoneWhenCallingHeadOptionOnNil() { assertThat(CharSeq.empty().headOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeHeadWhenCallingHeadOptionOnNonNil() { assertThat(CharSeq.of('1', '2', '3').headOption()).isEqualTo(Option.some('1')); } // -- hasDefiniteSize @Test public void shouldReturnSomethingOnHasDefiniteSize() { assertThat(CharSeq.empty().hasDefiniteSize()).isTrue(); } // -- groupBy @Test public void shouldNilGroupBy() { assertThat(CharSeq.empty().groupBy(Function.identity())).isEqualTo(LinkedHashMap.empty()); } @Test public void shouldNonNilGroupByIdentity() { final Map actual = CharSeq.of('a', 'b', 'c').groupBy(Function.identity()); final Map expected = LinkedHashMap.empty().put('a', CharSeq.of('a')).put('b', CharSeq.of('b')).put('c', CharSeq.of('c')); assertThat(actual).isEqualTo(expected); } @Test public void shouldNonNilGroupByEqual() { final Map actual = CharSeq.of('a', 'b', 'c').groupBy(c -> 1); final Map expected = LinkedHashMap.empty().put(1, CharSeq.of('a', 'b', 'c')); assertThat(actual).isEqualTo(expected); } // -- init @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenInitOfNil() { CharSeq.empty().init(); } @Test public void shouldGetInitOfNonNil() { assertThat(CharSeq.of('1', '2', '3').init()).isEqualTo(CharSeq.of('1', '2')); } // -- initOption @Test public void shouldReturnNoneWhenCallingInitOptionOnNil() { assertThat(CharSeq.empty().initOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeInitWhenCallingInitOptionOnNonNil() { assertThat(CharSeq.of('1', '2', '3').initOption()).isEqualTo(Option.some(CharSeq.of('1', '2'))); } // -- isAsync @Test public void shouldVerifyAsyncProperty() { assertThat(CharSeq.empty().isAsync()).isFalse(); assertThat(CharSeq.of('1').isAsync()).isFalse(); } // -- isLazy @Test public void shouldVerifyLazyProperty() { assertThat(CharSeq.empty().isLazy()).isFalse(); assertThat(CharSeq.of('1').isLazy()).isFalse(); } // -- isEmpty @Test public void shouldRecognizeNil() { assertThat(CharSeq.empty().isEmpty()).isTrue(); } @Test public void shouldRecognizeNonNil() { assertThat(CharSeq.of('1').isEmpty()).isFalse(); } // -- iterator @Test public void shouldNotHasNextWhenNilIterator() { assertThat(CharSeq.empty().iterator().hasNext()).isFalse(); } @Test(expected = NoSuchElementException.class) public void shouldThrowOnNextWhenNilIterator() { CharSeq.empty().iterator().next(); } @Test public void shouldIterateFirstElementOfNonNil() { assertThat(CharSeq.of('1', '2', '3').iterator().next()).isEqualTo('1'); } @Test public void shouldFullyIterateNonNil() { final Iterator iterator = CharSeq.of('1', '2', '3').iterator(); int actual; for (int i = 1; i <= 3; i++) { actual = iterator.next(); assertThat(actual).isEqualTo('0' + i); } assertThat(iterator.hasNext()).isFalse(); } // -- mkString() @Test public void shouldMkStringNil() { assertThat(CharSeq.empty().mkString()).isEqualTo(""); } @Test public void shouldMkStringNonNil() { assertThat(CharSeq.of('a', 'b', 'c').mkString()).isEqualTo("abc"); } // -- mkString(delimiter) @Test public void shouldMkStringWithDelimiterNil() { assertThat(CharSeq.empty().mkString(",")).isEqualTo(""); } @Test public void shouldMkStringWithDelimiterNonNil() { assertThat(CharSeq.of('a', 'b', 'c').mkString(",")).isEqualTo("a,b,c"); } // -- mkString(delimiter, prefix, suffix) @Test public void shouldMkStringWithDelimiterAndPrefixAndSuffixNil() { assertThat(CharSeq.empty().mkString("[", ",", "]")).isEqualTo("[]"); } @Test public void shouldMkStringWithDelimiterAndPrefixAndSuffixNonNil() { assertThat(CharSeq.of('a', 'b', 'c').mkString("[", ",", "]")).isEqualTo("[a,b,c]"); } // -- last @Test(expected = NoSuchElementException.class) public void shouldThrowWhenLastOnNil() { CharSeq.empty().last(); } @Test public void shouldReturnLastOfNonNil() { assertThat(CharSeq.of('1', '2', '3').last()).isEqualTo('3'); } // -- lastOption @Test public void shouldReturnNoneWhenCallingLastOptionOnNil() { assertThat(CharSeq.empty().lastOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeLastWhenCallingLastOptionOnNonNil() { assertThat(CharSeq.of('1', '2', '3').lastOption()).isEqualTo(Option.some('3')); } // -- length @Test public void shouldComputeLengthOfNil() { assertThat(CharSeq.empty().length()).isEqualTo(0); } @Test public void shouldComputeLengthOfNonNil() { assertThat(CharSeq.of('1', '2', '3').length()).isEqualTo(3); } // -- map @Test public void shouldMapNil() { assertThat(CharSeq.empty().map(i -> i + 1)).isEqualTo(Vector.empty()); } @Test public void shouldMapNonNil() { assertThat(CharSeq.of('1', '2', '3').map(i -> (char) (i + 1))).isEqualTo(Vector.of('2', '3', '4')); } @Test public void shouldMapElementsToSequentialValuesInTheRightOrder() { final AtomicInteger seq = new AtomicInteger('0'); final Traversable expectedInts = Vector.of('0', '1', '2', '3', '4'); final Traversable actualInts = expectedInts.map(ignored -> (char) seq.getAndIncrement()); assertThat(actualInts).isEqualTo(expectedInts); } @Test public void shouldMapToVectorWhenMapIsUsed() { assertThat(CharSeq.of('a', 'b', 'c').map(Integer::valueOf)).isInstanceOf(Vector.class); } @Test public void shouldMapToCharSeqWhenMapCharsIsUsed() { assertThat(CharSeq.empty().mapChars(c -> (char) (c + 1))).isEqualTo(CharSeq.empty()); assertThat(CharSeq.of('a', 'b', 'c').mapChars(c -> (char) (c + 1))).isEqualTo(CharSeq.of("bcd")); } // -- partition @Test(expected = NullPointerException.class) public void shouldThrowWhenPartitionNilAndPredicateIsNull() { CharSeq.empty().partition(null); } @Test public void shouldPartitionNil() { assertThat(CharSeq.empty().partition(e -> true)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.empty())); } @Test public void shouldPartitionIntsInOddAndEvenHavingOddAndEventNumbers() { assertThat(CharSeq.of('1', '2', '3', '4').partition(i -> i % 2 != 0)) .isEqualTo(Tuple.of(CharSeq.of('1', '3'), CharSeq.of('2', '4'))); } @Test public void shouldPartitionIntsInOddAndEvenHavingOnlyOddNumbers() { assertThat(CharSeq.of('1', '3').partition(i -> i % 2 != 0)).isEqualTo(Tuple.of(CharSeq.of('1', '3'), CharSeq.empty())); } @Test public void shouldPartitionIntsInOddAndEvenHavingOnlyEvenNumbers() { assertThat(CharSeq.of('2', '4').partition(i -> i % 2 != 0)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.of('2', '4'))); } // -- permutations @Test public void shouldComputePermutationsOfEmptyList() { assertThat(CharSeq.empty().permutations()).isEmpty(); } @Test public void shouldComputePermutationsOfNonEmpty() { assertThat(CharSeq.of("123").permutations()) .isEqualTo(Vector.of(CharSeq.of("123"), CharSeq.of("132"), CharSeq.of("213"), CharSeq.of("231"), CharSeq.of("312"), CharSeq.of("321"))); } // -- max @Test public void shouldReturnNoneWhenComputingMaxOfNil() { assertThat(CharSeq.empty().max()).isEqualTo(Option.none()); } @Test public void shouldComputeMaxOfChar() { assertThat(CharSeq.of('a', 'b', 'c').max()).isEqualTo(Option.some('c')); } // -- maxBy(Comparator) @Test(expected = NullPointerException.class) public void shouldThrowWhenMaxByWithNullComparator() { CharSeq.of('1').maxBy((Comparator) null); } @Test public void shouldThrowWhenMaxByOfNil() { assertThat(CharSeq.empty().maxBy((o1, o2) -> 0)).isEqualTo(Option.none()); } @Test public void shouldCalculateMaxByOfInts() { assertThat(CharSeq.of('1', '2', '3').maxBy(Comparator.comparingInt(i -> i))).isEqualTo(Option.some('3')); } @Test public void shouldCalculateInverseMaxByOfInts() { assertThat(CharSeq.of('1', '2', '3').maxBy((i1, i2) -> i2 - i1)).isEqualTo(Option.some('1')); } // -- maxBy(Function) @Test(expected = NullPointerException.class) public void shouldThrowWhenMaxByWithNullFunction() { CharSeq.of('1').maxBy((Function) null); } @Test public void shouldThrowWhenMaxByFunctionOfNil() { assertThat(CharSeq.empty().maxBy(i -> i)).isEqualTo(Option.none()); } @Test public void shouldCalculateMaxByFunctionOfInts() { assertThat(CharSeq.of('1', '2', '3').maxBy(i -> i)).isEqualTo(Option.some('3')); } @Test public void shouldCalculateInverseMaxByFunctionOfInts() { assertThat(CharSeq.of('1', '2', '3').maxBy(i -> -i)).isEqualTo(Option.some('1')); } // -- min @Test public void shouldReturnNoneWhenComputingMinOfNil() { assertThat(CharSeq.empty().min()).isEqualTo(Option.none()); } @Test public void shouldComputeMinOfChar() { assertThat(CharSeq.of('a', 'b', 'c').min()).isEqualTo(Option.some('a')); } // -- minBy(Comparator) @Test(expected = NullPointerException.class) public void shouldThrowWhenMinByWithNullComparator() { CharSeq.of('1').minBy((Comparator) null); } @Test public void shouldThrowWhenMinByOfNil() { assertThat(CharSeq.empty().minBy((o1, o2) -> 0)).isEqualTo(Option.none()); } @Test public void shouldCalculateMinByOfInts() { assertThat(CharSeq.of('1', '2', '3').minBy(Comparator.comparingInt(i -> i))).isEqualTo(Option.some('1')); } @Test public void shouldCalculateInverseMinByOfInts() { assertThat(CharSeq.of('1', '2', '3').minBy((i1, i2) -> i2 - i1)).isEqualTo(Option.some('3')); } // -- minBy(Function) @Test(expected = NullPointerException.class) public void shouldThrowWhenMinByWithNullFunction() { CharSeq.of('1').minBy((Function) null); } @Test public void shouldThrowWhenMinByFunctionOfNil() { assertThat(CharSeq.empty().minBy(i -> i)).isEqualTo(Option.none()); } @Test public void shouldCalculateMinByFunctionOfInts() { assertThat(CharSeq.of('1', '2', '3').minBy(i -> i)).isEqualTo(Option.some('1')); } @Test public void shouldCalculateInverseMinByFunctionOfInts() { assertThat(CharSeq.of('1', '2', '3').minBy(i -> -i)).isEqualTo(Option.some('3')); } // -- peek @Test public void shouldPeekNonNilPerformingAnAction() { final char[] effect = { 0 }; final CharSeq actual = CharSeq.of('1', '2', '3').peek(i -> effect[0] = i); assertThat(actual).isEqualTo(CharSeq.of('1', '2', '3')); // traverses all elements in the lazy case assertThat(effect[0]).isEqualTo('1'); } // -- product @Test public void shouldComputeProductOfNil() { assertThat(CharSeq.empty().product()).isEqualTo(1); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenComputingProductOfStrings() { CharSeq.of('1', '2', '3').product(); } // -- reduce @Test(expected = NoSuchElementException.class) public void shouldThrowWhenReduceNil() { CharSeq.empty().reduce((a, b) -> a); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceNullOperator() { CharSeq.empty().reduce(null); } @Test public void shouldReduceNonNil() { assertThat(CharSeq.of('1', '2', '3').reduce((a, b) -> b)).isEqualTo('3'); } // -- reduceLeft @Test(expected = NoSuchElementException.class) public void shouldThrowWhenReduceLeftNil() { CharSeq.empty().reduceLeft((a, b) -> a); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceLeftNullOperator() { CharSeq.empty().reduceLeft(null); } @Test public void shouldReduceLeftNonNil() { assertThat(CharSeq.of('a', 'b', 'c').reduceLeft((xs, x) -> x)).isEqualTo('c'); } // -- reduceRight @Test(expected = NoSuchElementException.class) public void shouldThrowWhenReduceRightNil() { CharSeq.empty().reduceRight((a, b) -> a); } @Test(expected = NullPointerException.class) public void shouldThrowWhenReduceRightNullOperator() { CharSeq.empty().reduceRight(null); } @Test public void shouldReduceRightNonNil() { assertThat(CharSeq.of('a', 'b', 'c').reduceRight((x, xs) -> x)).isEqualTo('a'); } // -- replace(curr, new) @Test public void shouldReplaceElementOfNilUsingCurrNew() { assertThat(CharSeq.empty().replace('1', '2')).isSameAs(CharSeq.empty()); } @Test public void shouldReplaceElementOfNonNilUsingCurrNew() { assertThat(CharSeq.of('0', '1', '2', '1').replace('1', '3')).isEqualTo(CharSeq.of('0', '3', '2', '1')); } @Test public void shouldReturnSameInstanceWhenReplacingNullCharWithNullChar() { final CharSeq charSeq = CharSeq.of('a'); assertThat(charSeq.replace((Character) null, (Character) null)).isSameAs(charSeq); } @Test public void shouldReturnSameInstanceWhenReplacingNullCharWithNonNullChar() { final CharSeq charSeq = CharSeq.of('a'); assertThat(charSeq.replace((Character) null, 'b')).isSameAs(charSeq); } @Test public void shouldThrowWhenReplacingNonNullCharWithNullChar() { assertThatThrownBy(() -> CharSeq.of('a').replace('a', (Character) null)).isInstanceOf(NullPointerException.class); } // -- replaceAll(curr, new) @Test public void shouldReplaceAllElementsOfNilUsingCurrNew() { assertThat(CharSeq.empty().replaceAll('1', '2')).isSameAs(CharSeq.empty()); } @Test public void shouldReplaceAllElementsOfNonNilUsingCurrNew() { assertThat(CharSeq.of('0', '1', '2', '1').replaceAll('1', '3')).isEqualTo(CharSeq.of('0', '3', '2', '3')); } @Test public void shouldReturnSameInstanceWhenReplacingAllNullCharWithNullChar() { final CharSeq charSeq = CharSeq.of('a'); assertThat(charSeq.replaceAll((Character) null, (Character) null)).isSameAs(charSeq); } @Test public void shouldReturnSameInstanceWhenReplacingAllNullCharWithNonNullChar() { final CharSeq charSeq = CharSeq.of('a'); assertThat(charSeq.replaceAll((Character) null, 'b')).isSameAs(charSeq); } @Test public void shouldThrowWhenReplacingAllNonNullCharWithNullChar() { assertThatThrownBy(() -> CharSeq.of('a').replaceAll('a', (Character) null)).isInstanceOf(NullPointerException.class); } // -- retainAll @Test public void shouldRetainAllElementsFromNil() { assertThat(CharSeq.empty().retainAll(CharSeq.of('1', '2', '3'))).isSameAs(CharSeq.empty()); } @Test public void shouldRetainAllExistingElementsFromNonNil() { assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').retainAll(CharSeq.of('1', '2'))) .isEqualTo(CharSeq.of('1', '2', '1', '2')); } @Test public void shouldNotRetainAllNonExistingElementsFromNonNil() { assertThat(CharSeq.of('1', '2', '3').retainAll(CharSeq.of('4', '5'))).isSameAs(CharSeq.empty()); } // -- shuffle @Test public void shouldShuffleEmpty() { assertThat(CharSeq.empty().shuffle().isEmpty()); } @Test public void shouldShuffleHaveSameLength() { final CharSeq actual = CharSeq.of('1', '2', '3'); assertThat(actual.shuffle().size()).isEqualTo(actual.size()); } @Test public void shouldShuffleHaveSameElements() { final CharSeq actual = CharSeq.of('1', '2', '3'); final CharSeq shuffled = actual.shuffle(); assertThat(shuffled.containsAll(actual)).isTrue(); assertThat(shuffled.indexOf(4)).isEqualTo(-1); } // -- slideBy(classifier) @Test public void shouldSlideNilByClassifier() { assertThat(CharSeq.empty().slideBy(Function.identity())).isEmpty(); } @Test public void shouldSlideSingularByClassifier() { final io.vavr.collection.List> actual = CharSeq.of('1').slideBy(Function.identity()).toList().map(Vector::ofAll); final io.vavr.collection.List> expected = io.vavr.collection.List.of(Vector.of('1')); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlideNonNilByIdentityClassifier() { final io.vavr.collection.List> actual = CharSeq.of('1', '2', '3').slideBy(Function.identity()).toList().map(Vector::ofAll); final io.vavr.collection.List> expected = io.vavr.collection.List.of(Vector.of('1'), Vector.of('2'), Vector.of('3')); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlideNonNilByConstantClassifier() { final io.vavr.collection.List> actual = CharSeq.of('1', '2', '3').slideBy(e -> "same").toList().map(Vector::ofAll); final io.vavr.collection.List> expected = io.vavr.collection.List.of(Vector.of('1', '2', '3')); assertThat(actual).isEqualTo(expected); } @Test public void shouldSlideNonNilBySomeClassifier() { final io.vavr.collection.List> actual = CharSeq.of('1', '1', '1', '2', '2', '3', '4').slideBy(Function.identity()).toList().map(Vector::ofAll); final io.vavr.collection.List> expected = io.vavr.collection.List.of(Vector.of('1', '1', '1'), Vector.of('2', '2'), Vector.of('3'), Vector.of('4')); assertThat(actual).isEqualTo(expected); } // -- sliding(size) @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNilByZeroSize() { CharSeq.empty().sliding(0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNilByNegativeSize() { CharSeq.empty().sliding(-1); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNonNilByZeroSize() { CharSeq.of('1').sliding(0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenSlidingNonNilByNegativeSize() { CharSeq.of('1').sliding(-1); } @Test public void shouldSlideNilBySize() { assertThat(CharSeq.empty().sliding(1).isEmpty()).isTrue(); } @Test public void shouldSlideNonNilBySize1() { assertThat(CharSeq.of('1', '2', '3').sliding(1).toList()) .isEqualTo(io.vavr.collection.List.of(CharSeq.of('1'), CharSeq.of('2'), CharSeq.of('3'))); } @Test public void shouldSlideNonNilBySize2() { assertThat(CharSeq.of('1', '2', '3', '4', '5').sliding(2).toList()) .isEqualTo(io.vavr.collection.List.of(CharSeq.of('1', '2'), CharSeq.of('2', '3'), CharSeq.of('3', '4'), CharSeq.of('4', '5'))); } // -- sliding(size, step) @Test public void shouldSlideNilBySizeAndStep() { assertThat(CharSeq.empty().sliding(1, 1).isEmpty()).isTrue(); } @Test public void shouldSlide5ElementsBySize2AndStep3() { assertThat(CharSeq.of('1', '2', '3', '4', '5').sliding(2, 3).toList()) .isEqualTo(io.vavr.collection.List.of(CharSeq.of('1', '2'), CharSeq.of('4', '5'))); } @Test public void shouldSlide5ElementsBySize2AndStep4() { assertThat(CharSeq.of('1', '2', '3', '4', '5').sliding(2, 4).toList()) .isEqualTo(io.vavr.collection.List.of(CharSeq.of('1', '2'), CharSeq.of('5'))); } @Test public void shouldSlide5ElementsBySize2AndStep5() { assertThat(CharSeq.of('1', '2', '3', '4', '5').sliding(2, 5).toList()).isEqualTo(io.vavr.collection.List.of(CharSeq.of('1', '2'))); } @Test public void shouldSlide4ElementsBySize5AndStep3() { assertThat(CharSeq.of('1', '2', '3', '4').sliding(5, 3).toList()) .isEqualTo(io.vavr.collection.List.of(CharSeq.of('1', '2', '3', '4'))); } // -- span @Test public void shouldSpanNil() { assertThat(CharSeq.empty().span(i -> i < 2)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.empty())); } @Test public void shouldSpanNonNil() { final CharSeq cs = CharSeq.of('0', '1', '2', '3'); assertThat(cs.span(i -> i == '0' || i == '1')) .isEqualTo(Tuple.of(CharSeq.of('0', '1'), CharSeq.of('2', '3'))); assertThat(cs.span(i -> false)) .isEqualTo(Tuple.of(CharSeq.empty(), cs)); assertThat(cs.span(i -> true)) .isEqualTo(Tuple.of(cs, CharSeq.empty())); } // -- spliterator @Test public void shouldSplitNil() { final java.util.List actual = new java.util.ArrayList<>(); CharSeq.empty().spliterator().forEachRemaining(actual::add); assertThat(actual).isEmpty(); } @Test public void shouldSplitNonNil() { final java.util.List actual = new java.util.ArrayList<>(); CharSeq.of('1', '2', '3').spliterator().forEachRemaining(actual::add); assertThat(actual).isEqualTo(asList('1', '2', '3')); } @Test public void shouldHaveImmutableSpliterator() { assertThat(CharSeq.of('1', '2', '3').spliterator().hasCharacteristics(Spliterator.IMMUTABLE)).isTrue(); } @Test public void shouldHaveSizedSpliterator() { assertThat(CharSeq.of('1', '2', '3').spliterator() .hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue(); } @Test public void shouldReturnSizeWhenSpliterator() { assertThat(CharSeq.of('1', '2', '3').spliterator().getExactSizeIfKnown()).isEqualTo(3); } // -- startsWith @Test public void shouldStartsNilOfNilCalculate() { assertThat(CharSeq.empty().startsWith(CharSeq.empty())).isTrue(); } @Test public void shouldStartsNilOfNonNilCalculate() { assertThat(CharSeq.empty().startsWith(CharSeq.of('a'))).isFalse(); } @Test public void shouldStartsNilOfNilWithOffsetCalculate() { assertThat(CharSeq.empty().startsWith(CharSeq.empty(), 1)).isFalse(); } @Test public void shouldStartsNilOfNonNilWithOffsetCalculate() { assertThat(CharSeq.empty().startsWith(CharSeq.of('a'), 1)).isFalse(); } @Test public void shouldStartsNonNilOfNilCalculate() { assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.empty())).isTrue(); } @Test public void shouldStartsNonNilOfNonNilCalculate() { assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.of('a', 'b'))).isTrue(); assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.of('a', 'b', 'c'))).isTrue(); assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.of('a', 'b', 'c', 'd'))).isFalse(); assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.of('a', 'c'))).isFalse(); } @Test public void shouldStartsNonNilOfNilWithOffsetCalculate() { assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.empty(), 1)).isTrue(); } @Test public void shouldStartsNonNilOfNonNilWithOffsetCalculate() { assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.of('b', 'c'), 1)).isTrue(); assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.of('b', 'c', 'd'), 1)).isFalse(); assertThat(CharSeq.of('a', 'b', 'c').startsWith(CharSeq.of('b', 'd'), 1)).isFalse(); } // -- stderr @Test public void shouldWriteToStderr() { assertThat(captureErrOut(()->CharSeq.of('1', '2', '3').stderr())).isEqualTo("1\n" + "2\n" + "3\n"); } @Test(expected = IllegalStateException.class) public void shouldHandleStderrIOException() { withFailingErrOut(()->CharSeq.of('0').stderr()); } // -- stdout @Test public void shouldWriteToStdout() { assertThat(captureStdOut(()->CharSeq.of('1', '2', '3').stdout())).isEqualTo("1\n" + "2\n" + "3\n"); } @Test(expected = IllegalStateException.class) public void shouldHandleStdoutIOException() { withFailingStdOut(()->CharSeq.of('0').stdout()); } // -- sum @Test public void shouldComputeSumOfNil() { assertThat(CharSeq.empty().sum()).isEqualTo(0); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenComputingSumOfStrings() { CharSeq.of('1', '2', '3').sum(); } // -- tabulate @Test public void shouldTabulateTheCharSeq() { final Function f = i -> i.toString().charAt(0); final CharSeq actual = CharSeq.tabulate(3, f); assertThat(actual).isEqualTo(CharSeq.of('0', '1', '2')); } @Test public void shouldTabulateTheCharSeqCallingTheFunctionInTheRightOrder() { final java.util.LinkedList chars = new java.util.LinkedList<>(asList('0', '1', '2')); final CharSeq actual = CharSeq.tabulate(3, i -> chars.remove()); assertThat(actual).isEqualTo(CharSeq.of('0', '1', '2')); } @Test public void shouldTabulateTheCharSeqWith0Elements() { assertThat(CharSeq.tabulate(0, i -> 'a')).isEqualTo(CharSeq.empty()); } @Test public void shouldTabulateTheCharSeqWith0ElementsWhenNIsNegative() { assertThat(CharSeq.tabulate(-1, i -> 'a')).isEqualTo(CharSeq.empty()); } @Test public void shouldThrowWhenTabulatingNullValues() { assertThatThrownBy(() -> CharSeq.tabulate(1, i -> null)).isInstanceOf(NullPointerException.class); } // -- take @Test public void shouldTakeNoneOnNil() { assertThat(CharSeq.empty().take(1)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeNoneIfCountIsNegative() { assertThat(CharSeq.of('1', '2', '3').take(-1)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeAsExpectedIfCountIsLessThanSize() { assertThat(CharSeq.of('1', '2', '3').take(2)).isEqualTo(CharSeq.of('1', '2')); } @Test public void shouldTakeAllIfCountExceedsSize() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.take(4)).isSameAs(t); } // -- takeUntil @Test public void shouldTakeUntilNoneOnNil() { assertThat(CharSeq.empty().takeUntil(x -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeUntilAllOnFalseCondition() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.takeUntil(x -> false)).isSameAs(t); } @Test public void shouldTakeUntilAllOnTrueCondition() { assertThat(CharSeq.of('1', '2', '3').takeUntil(x -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeUntilAsExpected() { assertThat(CharSeq.of('2', '4', '5', '6').takeUntil(x -> x % 2 != 0)).isEqualTo(CharSeq.of('2', '4')); } // -- takeWhile @Test public void shouldTakeWhileNoneOnNil() { assertThat(CharSeq.empty().takeWhile(x -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeWhileAllOnFalseCondition() { assertThat(CharSeq.of('1', '2', '3').takeWhile(x -> false)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeWhileAllOnTrueCondition() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.takeWhile(x -> true)).isSameAs(t); } @Test public void shouldTakeWhileAsExpected() { assertThat(CharSeq.of('2', '4', '5', '6').takeWhile(x -> x % 2 == 0)).isEqualTo(CharSeq.of('2', '4')); } // -- takeRight @Test public void shouldTakeRightNoneOnNil() { assertThat(CharSeq.empty().takeRight(1)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeRightNoneIfCountIsNegative() { assertThat(CharSeq.of('1', '2', '3').takeRight(-1)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeRightAsExpectedIfCountIsLessThanSize() { assertThat(CharSeq.of('1', '2', '3').takeRight(2)).isEqualTo(CharSeq.of('2', '3')); } @Test public void shouldTakeRightAllIfCountExceedsSize() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.takeRight(4)).isSameAs(t); } // -- takeRightUntil @Test public void shouldTakeRightUntilNoneOnNil() { assertThat(CharSeq.empty().takeRightUntil(x -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeRightUntilAllOnFalseCondition() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.takeRightUntil(x -> false)).isSameAs(t); } @Test public void shouldTakeRightUntilAllOnTrueCondition() { assertThat(CharSeq.of('1', '2', '3').takeRightUntil(x -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeRightUntilAsExpected() { assertThat(CharSeq.of('2', '3', '4', '6').takeRightUntil(x -> x % 2 != 0)).isEqualTo(CharSeq.of('4', '6')); } // -- takeRightWhile @Test public void shouldTakeRightWhileNoneOnNil() { assertThat(CharSeq.empty().takeRightWhile(x -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeRightWhileAllOnFalseCondition() { assertThat(CharSeq.of('1', '2', '3').takeRightWhile(x -> false)).isSameAs(CharSeq.empty()); } @Test public void shouldTakeRightWhileAllOnTrueCondition() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.takeRightWhile(x -> true)).isSameAs(t); } @Test public void shouldTakeRightWhileAsExpected() { assertThat(CharSeq.of('2', '3', '4', '6').takeRightWhile(x -> x % 2 == 0)).isEqualTo(CharSeq.of('4', '6')); } // -- tail @Test(expected = UnsupportedOperationException.class) public void shouldThrowWhenTailOnNil() { CharSeq.empty().tail(); } @Test public void shouldReturnTailOfNonNil() { assertThat(CharSeq.of('1', '2', '3').tail()).isEqualTo(CharSeq.of('2', '3')); } // -- tailOption @Test public void shouldReturnNoneWhenCallingTailOptionOnNil() { assertThat(CharSeq.empty().tailOption().isEmpty()).isTrue(); } @Test public void shouldReturnSomeTailWhenCallingTailOptionOnNonNil() { assertThat(CharSeq.of('1', '2', '3').tailOption()).isEqualTo(Option.some(CharSeq.of('2', '3'))); } // -- toLowerCase @Test public void shouldConvertToLowerCase() { assertThat(CharSeq.of("Vavr").toLowerCase()).isEqualTo(CharSeq.of("vavr")); assertThat(CharSeq.of("Vavr").toLowerCase(Locale.ENGLISH)).isEqualTo(CharSeq.of("vavr")); } // -- toUpperCase @Test public void shouldConvertTotoUpperCase() { assertThat(CharSeq.of("Vavr").toUpperCase()).isEqualTo(CharSeq.of("VAVR")); assertThat(CharSeq.of("Vavr").toUpperCase(Locale.ENGLISH)).isEqualTo(CharSeq.of("VAVR")); } // -- capitalize @Test public void shouldCapitalize() { assertThat(CharSeq.of("vavr").capitalize()).isEqualTo(CharSeq.of("Vavr")); assertThat(CharSeq.of("").capitalize()).isEqualTo(CharSeq.of("")); assertThat(CharSeq.of("vavr").capitalize(Locale.ENGLISH)).isEqualTo(CharSeq.of("Vavr")); assertThat(CharSeq.of("").capitalize(Locale.ENGLISH)).isEqualTo(CharSeq.of("")); } // -- toJavaArray(Class) @Test public void shouldHaveOverloadedToJavaArray() { final Character[] actual = CharSeq.of('a', 'b', 'c').toJavaArray(); assertThat(actual).isEqualTo(new Character[] {'a', 'b', 'c'}); } @Test public void shouldConvertNilToJavaArray() { final Character[] actual = CharSeq.empty().toJavaArray(Character[]::new); final Character[] expected = new Character[] {}; assertThat(actual).isEqualTo(expected); } @Test public void shouldConvertNonNilToJavaArray() { final Character[] array = CharSeq.of('1', '2').toJavaArray(Character[]::new); final Character[] expected = new Character[] { '1', '2' }; assertThat(array).isEqualTo(expected); } // -- toJavaList @Test public void shouldConvertNilToArrayList() { assertThat(CharSeq.empty().toJavaList()).isEqualTo(new ArrayList()); } @Test public void shouldConvertNonNilToArrayList() { assertThat(CharSeq.of('1', '2', '3').toJavaList()).isEqualTo(asList('1', '2', '3')); } // -- toJavaMap(Function) @Test public void shouldConvertNilToHashMap() { assertThat(CharSeq.empty().toJavaMap(x -> Tuple.of(x, x))).isEqualTo(new java.util.HashMap<>()); } @Test public void shouldConvertNonNilToHashMap() { final java.util.Map expected = new java.util.HashMap<>(); expected.put('1', '1'); expected.put('2', '2'); assertThat(CharSeq.of('1', '2').toJavaMap(x -> Tuple.of(x, x))).isEqualTo(expected); } // -- toJavaSet @Test public void shouldConvertNilToHashSet() { assertThat(CharSeq.empty().toJavaSet()).isEqualTo(new java.util.HashSet<>()); } @Test public void shouldConvertNonNilToHashSet() { final java.util.Set expected = new java.util.HashSet<>(); expected.add('2'); expected.add('1'); expected.add('3'); assertThat(CharSeq.of('1', '2', '2', '3').toJavaSet()).isEqualTo(expected); } // -- stringPrefix @Test public void shouldReturnStringPrefix() { assertThat(CharSeq.of('1').stringPrefix()).isEqualTo("CharSeq"); } // ++++++ OBJECT ++++++ // -- equals @Test public void shouldEqualSameTraversableInstance() { final Traversable traversable = CharSeq.empty(); assertThat(traversable).isEqualTo(traversable); } @Test public void shouldNilNotEqualsNull() { assertThat(CharSeq.empty()).isNotNull(); } @Test public void shouldNonNilNotEqualsNull() { assertThat(CharSeq.of('1')).isNotNull(); } @Test public void shouldEmptyNotEqualsDifferentType() { assertThat(CharSeq.empty()).isNotEqualTo(""); } @Test public void shouldNonEmptyNotEqualsDifferentType() { assertThat(CharSeq.of('1')).isNotEqualTo(""); } @Test public void shouldRecognizeEqualityOfNils() { assertThat(CharSeq.empty()).isSameAs(CharSeq.empty()); } @Test public void shouldRecognizeEqualityOfNonNils() { assertThat(CharSeq.of('1', '2', '3').equals(CharSeq.of('1', '2', '3'))).isTrue(); } @Test public void shouldRecognizeContentEqualityOfNonNil() { assertThat(CharSeq.of('1', '2', '3').contentEquals(new StringBuffer().append("123"))).isTrue(); assertThat(CharSeq.of('1', '2', '3').contentEquals("123")).isTrue(); } @Test public void shouldRecognizeNonEqualityOfTraversablesOfSameSize() { assertThat(CharSeq.of('1', '2', '3').equals(CharSeq.of('1', '2', '4'))).isFalse(); } @Test public void shouldRecognizeNonEqualityOfTraversablesOfDifferentSize() { assertThat(CharSeq.of('1', '2', '3').equals(CharSeq.of('1', '2'))).isFalse(); } // -- hashCode @Test public void shouldCalculateHashCodeOfNil() { assertThat(CharSeq.empty().hashCode() == CharSeq.empty().hashCode()).isTrue(); } @Test public void shouldCalculateHashCodeOfNonNil() { assertThat(CharSeq.of('1', '2').hashCode() == CharSeq.of('1', '2').hashCode()).isTrue(); } @Test public void shouldCalculateDifferentHashCodesForDifferentTraversables() { assertThat(CharSeq.of('1', '2').hashCode() != CharSeq.of('2', '3').hashCode()).isTrue(); } // -- Serializable interface @Test public void shouldSerializeDeserializeNil() { final Object actual = Serializables.deserialize(Serializables.serialize(CharSeq.empty())); final Object expected = CharSeq.empty(); assertThat(actual).isEqualTo(expected); } @Test public void shouldPreserveSingletonInstanceOnDeserialization() { final boolean actual = Serializables.deserialize(Serializables.serialize(CharSeq.empty())) == CharSeq.empty(); assertThat(actual).isTrue(); } @Test public void shouldSerializeDeserializeNonNil() { final Object actual = Serializables.deserialize(Serializables.serialize(CharSeq.of('1', '2', '3'))); final Object expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } // helpers static PrintStream failingPrintStream() { return new PrintStream(new OutputStream() { @Override public void write(int b) throws IOException { throw new IOException(); } }); } // -- append @Test public void shouldAppendElementToNil() { final CharSeq actual = CharSeq.empty().append('1'); final CharSeq expected = CharSeq.of('1'); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendElementToNonNil() { final CharSeq actual = CharSeq.of('1', '2').append('3'); final CharSeq expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldThrowWhenAppendingNull() { assertThatThrownBy(() -> CharSeq.of('1').append(null)).isInstanceOf(NullPointerException.class); } // -- appendAll @Test(expected = NullPointerException.class) public void shouldThrowOnAppendAllOfNull() { CharSeq.empty().appendAll(null); } @Test public void shouldAppendAllNilToNil() { final CharSeq actual = CharSeq.empty().appendAll(CharSeq.empty()); final CharSeq expected = CharSeq.empty(); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendAllNonNilToNil() { final CharSeq actual = CharSeq.empty().appendAll(CharSeq.of('1', '2', '3')); final CharSeq expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendAllNilToNonNil() { final CharSeq actual = CharSeq.of('1', '2', '3').appendAll(CharSeq.empty()); final CharSeq expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldAppendAllNonNilToNonNil() { final CharSeq actual = CharSeq.of('1', '2', '3').appendAll(CharSeq.of('4', '5', '6')); final CharSeq expected = CharSeq.of('1', '2', '3', '4', '5', '6'); assertThat(actual).isEqualTo(expected); } @Test public void shouldThrowWhenAppendingAllIterableThatContainsNull() { assertThatThrownBy(() -> CharSeq.empty().appendAll(Arrays.asList('1', null))).isInstanceOf(NullPointerException.class); } // -- asPartialFunction @Test public void shouldUseSeqAsPartialFunction() { assertThat(CharSeq.of('1', '2', '3').asPartialFunction().apply(1)).isEqualTo('2'); } // -- combinations @Test public void shouldComputeCombinationsOfEmptyList() { assertThat(CharSeq.empty().combinations()).isEqualTo(Vector.of(CharSeq.empty())); } @Test public void shouldComputeCombinationsOfNonEmptyList() { assertThat(CharSeq.of("123").combinations()).isEqualTo(Vector.of(CharSeq.empty(), CharSeq.of("1"), CharSeq.of("2"), CharSeq.of("3"), CharSeq.of("12"), CharSeq.of("13"), CharSeq.of("23"), CharSeq.of("123"))); } // -- combinations(k) @Test public void shouldComputeKCombinationsOfEmptyList() { assertThat(CharSeq.empty().combinations(1)).isEmpty(); } @Test public void shouldComputeKCombinationsOfNonEmptyList() { assertThat(CharSeq.of("123").combinations(2)).isEqualTo(Vector.of(CharSeq.of("12"), CharSeq.of("13"), CharSeq.of("23"))); } @Test public void shouldComputeKCombinationsOfNegativeK() { assertThat(CharSeq.of("1").combinations(-1)).isEqualTo(Vector.of(CharSeq.empty())); } // -- containsSlice @Test public void shouldRecognizeNilNotContainsSlice() { final boolean actual = CharSeq.empty().containsSlice(CharSeq.of('1', '2', '3')); assertThat(actual).isFalse(); } @Test public void shouldRecognizeNonNilDoesContainSlice() { final boolean actual = CharSeq.of('1', '2', '3', '4', '5').containsSlice(CharSeq.of('2', '3')); assertThat(actual).isTrue(); } @Test public void shouldRecognizeNonNilDoesNotContainSlice() { final boolean actual = CharSeq.of('1', '2', '3', '4', '5').containsSlice(CharSeq.of('2', '1', '4')); assertThat(actual).isFalse(); } // -- crossProduct() @Test public void shouldCalculateCrossProductOfNil() { final Iterator> actual = CharSeq.empty().crossProduct(); assertThat(actual).isEmpty(); } @Test public void shouldCalculateCrossProductOfNonNil() { final io.vavr.collection.List> actual = CharSeq.of('1', '2', '3').crossProduct().toList(); final io.vavr.collection.List> expected = Iterator.of(Tuple.of('1', '1'), Tuple.of('1', '2'), Tuple.of('1', '3'), Tuple.of('2', '1'), Tuple.of('2', '2'), Tuple.of('2', '3'), Tuple.of('3', '1'), Tuple.of('3', '2'), Tuple.of('3', '3')).toList(); assertThat(actual).isEqualTo(expected); } // -- crossProduct(int) @Test public void shouldCalculateCrossProductPower() { final io.vavr.collection.List actual = CharSeq.of("12").crossProduct(2).toList(); final io.vavr.collection.List expected = Iterator.of(CharSeq.of('1', '1'), CharSeq.of('1', '2'), CharSeq.of('2', '1'), CharSeq.of('2', '2')).toList(); assertThat(actual).isEqualTo(expected); } // -- crossProduct(Iterable) @Test public void shouldCalculateCrossProductOfNilAndNil() { final Traversable> actual = CharSeq.empty().crossProduct(CharSeq.empty()); assertThat(actual).isEmpty(); } @Test public void shouldCalculateCrossProductOfNilAndNonNil() { final Traversable> actual = CharSeq.empty().crossProduct(CharSeq.of('1', '2', '3')); assertThat(actual).isEmpty(); } @Test public void shouldCalculateCrossProductOfNonNilAndNil() { final Traversable> actual = CharSeq.of('1', '2', '3') .crossProduct(CharSeq.empty()); assertThat(actual).isEmpty(); } @Test public void shouldCalculateCrossProductOfNonNilAndNonNil() { final io.vavr.collection.List> actual = CharSeq.of('1', '2', '3') .crossProduct(CharSeq.of('a', 'b')) .toList(); final io.vavr.collection.List> expected = Vector.of(Tuple.of('1', 'a'), Tuple.of('1', 'b'), Tuple.of('2', 'a'), Tuple.of('2', 'b'), Tuple.of('3', 'a'), Tuple.of('3', 'b')).toList(); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowWhenCalculatingCrossProductAndThatIsNull() { CharSeq.empty().crossProduct(null); } // -- get @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetWithNegativeIndexOnNil() { CharSeq.empty().get(-1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetWithNegativeIndexOnNonNil() { CharSeq.of('1').get(-1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetOnNil() { CharSeq.empty().get(0); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenGetWithTooBigIndexOnNonNil() { CharSeq.of('1').get(1); } @Test public void shouldGetFirstElement() { assertThat(CharSeq.of('1', '2', '3').get(0)).isEqualTo('1'); } @Test public void shouldGetLastElement() { assertThat(CharSeq.of('1', '2', '3').get(2)).isEqualTo('3'); } // -- grouped @Test public void shouldGroupedNil() { assertThat(CharSeq.empty().grouped(1).isEmpty()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenGroupedWithSizeZero() { CharSeq.empty().grouped(0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenGroupedWithNegativeSize() { CharSeq.empty().grouped(-1); } @Test public void shouldGroupedTraversableWithEqualSizedBlocks() { final io.vavr.collection.List actual = CharSeq.of('1', '2', '3', '4').grouped(2).toList(); final io.vavr.collection.List expected = io.vavr.collection.List.of(CharSeq.of('1', '2'), CharSeq.of('3', '4')); assertThat(actual).isEqualTo(expected); } @Test public void shouldGroupedTraversableWithRemainder() { final io.vavr.collection.List actual = CharSeq.of('1', '2', '3', '4', '5').grouped(2).toList(); final io.vavr.collection.List expected = io.vavr.collection.List.of(CharSeq.of('1', '2'), CharSeq.of('3', '4'), CharSeq.of('5')); assertThat(actual).isEqualTo(expected); } @Test public void shouldGroupedWhenTraversableLengthIsSmallerThanBlockSize() { final io.vavr.collection.List actual = CharSeq.of('1', '2', '3', '4').grouped(5).toList(); final io.vavr.collection.List expected = io.vavr.collection.List.of(CharSeq.of('1', '2', '3', '4')); assertThat(actual).isEqualTo(expected); } // -- indexOf @Test public void shouldNotFindIndexOfElementWhenSeqIsEmpty() { assertThat(CharSeq.empty().indexOf(1)).isEqualTo(-1); assertThat(CharSeq.empty().indexOfOption(1)).isEqualTo(Option.none()); } @Test public void shouldNotFindIndexOfElementWhenStartIsGreater() { assertThat(CharSeq.of('1', '2', '3', '4').indexOf(2, 2)).isEqualTo(-1); assertThat(CharSeq.of('1', '2', '3', '4').indexOfOption(2, 2)).isEqualTo(Option.none()); } @Test public void shouldFindIndexOfFirstElement() { assertThat(CharSeq.of('1', '2', '3').indexOf('1')).isEqualTo(0); assertThat(CharSeq.of('1', '2', '3').indexOf(Character.valueOf('1'))).isEqualTo(0); assertThat(CharSeq.of('1', '2', '3').indexOfOption('1')).isEqualTo(Option.some(0)); assertThat(CharSeq.of('1', '2', '3').indexOfOption(Character.valueOf('1'))).isEqualTo(Option.some(0)); } @Test public void shouldFindIndexOfInnerElement() { assertThat(CharSeq.of('1', '2', '3').indexOf('2')).isEqualTo(1); assertThat(CharSeq.of('1', '2', '3').indexOf(Character.valueOf('2'))).isEqualTo(1); assertThat(CharSeq.of('1', '2', '3').indexOfOption('2')).isEqualTo(Option.some(1)); assertThat(CharSeq.of('1', '2', '3').indexOfOption(Character.valueOf('2'))).isEqualTo(Option.some(1)); } @Test public void shouldFindIndexOfLastElement() { assertThat(CharSeq.of('1', '2', '3').indexOf('3')).isEqualTo(2); assertThat(CharSeq.of('1', '2', '3').indexOf(Character.valueOf('3'))).isEqualTo(2); assertThat(CharSeq.of('1', '2', '3').indexOfOption('3')).isEqualTo(Option.some(2)); assertThat(CharSeq.of('1', '2', '3').indexOfOption(Character.valueOf('3'))).isEqualTo(Option.some(2)); } // -- indexOfSlice @Test public void shouldNotFindIndexOfSliceWhenSeqIsEmpty() { assertThat(CharSeq.empty().indexOfSlice(CharSeq.of('2', '3'))).isEqualTo(-1); assertThat(CharSeq.empty().indexOfSliceOption(CharSeq.of('2', '3'))).isEqualTo(Option.none()); } @Test public void shouldNotFindIndexOfSliceWhenStartIsGreater() { assertThat(CharSeq.of('1', '2', '3', '4').indexOfSlice(CharSeq.of('2', '3'), 2)).isEqualTo(-1); assertThat(CharSeq.of('1', '2', '3', '4').indexOfSliceOption(CharSeq.of('2', '3'), 2)).isEqualTo(Option.none()); } @Test public void shouldFindIndexOfFirstSlice() { assertThat(CharSeq.of('1', '2', '3', '4').indexOfSlice(CharSeq.of('1', '2'))).isEqualTo(0); assertThat(CharSeq.of('1', '2', '3', '4').indexOfSliceOption(CharSeq.of('1', '2'))).isEqualTo(Option.some(0)); } @Test public void shouldFindIndexOfInnerSlice() { assertThat(CharSeq.of('1', '2', '3', '4').indexOfSlice(CharSeq.of('2', '3'))).isEqualTo(1); assertThat(CharSeq.of('1', '2', '3', '4').indexOfSliceOption(CharSeq.of('2', '3'))).isEqualTo(Option.some(1)); } @Test public void shouldFindIndexOfLastSlice() { assertThat(CharSeq.of('1', '2', '3').indexOfSlice(CharSeq.of('2', '3'))).isEqualTo(1); assertThat(CharSeq.of('1', '2', '3').indexOfSliceOption(CharSeq.of('2', '3'))).isEqualTo(Option.some(1)); } // -- lastIndexOf @Test public void shouldNotFindLastIndexOfElementWhenSeqIsEmpty() { assertThat(CharSeq.empty().lastIndexOf(1)).isEqualTo(-1); assertThat(CharSeq.empty().lastIndexOfOption(1)).isEqualTo(Option.none()); } @Test public void shouldNotFindLastIndexOfElementWhenEndIdLess() { assertThat(CharSeq.of('1', '2', '3', '4').lastIndexOf(3, 1)).isEqualTo(-1); assertThat(CharSeq.of('1', '2', '3', '4').lastIndexOfOption(3, 1)).isEqualTo(Option.none()); } @Test public void shouldFindLastIndexOfElement() { assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOf('1')).isEqualTo(3); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOf(Character.valueOf('1'))).isEqualTo(3); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfOption('1')).isEqualTo(Option.some(3)); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfOption(Character.valueOf('1'))).isEqualTo(Option.some(3)); } @Test public void shouldFindLastIndexOfElementWithEnd() { assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOf('1', 1)).isEqualTo(0); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOf(Character.valueOf('1'), 1)).isEqualTo(0); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfOption('1', 1)).isEqualTo(Option.some(0)); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfOption(Character.valueOf('1'), 1)).isEqualTo(Option.some(0)); } // -- lastIndexOfSlice @Test public void shouldNotFindLastIndexOfSliceWhenSeqIsEmpty() { assertThat(CharSeq.empty().lastIndexOfSlice(CharSeq.of('2', '3'))).isEqualTo(-1); assertThat(CharSeq.empty().lastIndexOfSliceOption(CharSeq.of('2', '3'))).isEqualTo(Option.none()); } @Test public void shouldNotFindLastIndexOfSliceWhenEndIdLess() { assertThat(CharSeq.of('1', '2', '3', '4', '5').lastIndexOfSlice(CharSeq.of('3', '4'), 1)).isEqualTo(-1); assertThat(CharSeq.of('1', '2', '3', '4', '5').lastIndexOfSliceOption(CharSeq.of('3', '4'), 1)).isEqualTo(Option.none()); } @Test public void shouldFindLastIndexOfSlice() { assertThat(CharSeq.of('1', '2', '3', '1', '2').lastIndexOfSlice(CharSeq.empty())).isEqualTo(5); assertThat(CharSeq.of('1', '2', '3', '1', '2').lastIndexOfSlice(CharSeq.of('2'))).isEqualTo(4); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3', '4').lastIndexOfSlice(CharSeq.of('2', '3'))).isEqualTo(4); assertThat(CharSeq.of('1', '2', '3', '1', '2').lastIndexOfSliceOption(CharSeq.empty())).isEqualTo(Option.some(5)); assertThat(CharSeq.of('1', '2', '3', '1', '2').lastIndexOfSliceOption(CharSeq.of('2'))).isEqualTo(Option.some(4)); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3', '4').lastIndexOfSliceOption(CharSeq.of('2', '3'))).isEqualTo(Option.some(4)); } @Test public void shouldFindLastIndexOfSliceWithEnd() { assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfSlice(CharSeq.empty(), 2)).isEqualTo(2); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfSlice(CharSeq.of('2'), 2)).isEqualTo(1); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfSlice(CharSeq.of('2', '3'), 2)).isEqualTo(1); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3', '4').lastIndexOfSlice(CharSeq.of('2', '3'), 2)).isEqualTo(1); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfSliceOption(CharSeq.empty(), 2)).isEqualTo(Option.some(2)); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfSliceOption(CharSeq.of('2'), 2)).isEqualTo(Option.some(1)); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').lastIndexOfSliceOption(CharSeq.of('2', '3'), 2)).isEqualTo(Option.some(1)); assertThat(CharSeq.of('1', '2', '3', '1', '2', '3', '4').lastIndexOfSliceOption(CharSeq.of('2', '3'), 2)).isEqualTo(Option.some(1)); } // -- insert @Test public void shouldInsertIntoNil() { final CharSeq actual = CharSeq.empty().insert(0, '1'); final CharSeq expected = CharSeq.of('1'); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertInFrontOfElement() { final CharSeq actual = CharSeq.of('4').insert(0, '1'); final CharSeq expected = CharSeq.of('1', '4'); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertBehindOfElement() { final CharSeq actual = CharSeq.of('4').insert(1, '1'); final CharSeq expected = CharSeq.of('4', '1'); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertIntoSeq() { final CharSeq actual = CharSeq.of('1', '2', '3').insert(2, '4'); final CharSeq expected = CharSeq.of('1', '2', '4', '3'); assertThat(actual).isEqualTo(expected); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNonNilWithNegativeIndex() { CharSeq.of('1').insert(-1, null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNilWithNegativeIndex() { CharSeq.empty().insert(-1, null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnInsertWhenExceedingUpperBound() { CharSeq.empty().insert(1, null); } @Test public void shouldThrowWhenInsertingNull() { assertThatThrownBy(() -> CharSeq.empty().insert(0, null)).isInstanceOf(NullPointerException.class); } // -- insertAll @Test public void shouldInsertAllIntoNil() { final CharSeq actual = CharSeq.empty().insertAll(0, CharSeq.of('1', '2', '3')); final CharSeq expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertAllInFrontOfElement() { final CharSeq actual = CharSeq.of('4').insertAll(0, CharSeq.of('1', '2', '3')); final CharSeq expected = CharSeq.of('1', '2', '3', '4'); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertAllBehindOfElement() { final CharSeq actual = CharSeq.of('4').insertAll(1, CharSeq.of('1', '2', '3')); final CharSeq expected = CharSeq.of('4', '1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldInsertAllIntoSeq() { final CharSeq actual = CharSeq.of('1', '2', '3').insertAll(2, CharSeq.of('4', '5')); final CharSeq expected = CharSeq.of('1', '2', '4', '5', '3'); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowOnInsertAllWithNil() { CharSeq.empty().insertAll(0, null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNonNilAllWithNegativeIndex() { CharSeq.of('1').insertAll(-1, CharSeq.empty()); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenInsertOnNilAllWithNegativeIndex() { CharSeq.empty().insertAll(-1, CharSeq.empty()); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnInsertAllWhenExceedingUpperBound() { CharSeq.empty().insertAll(1, CharSeq.empty()); } @Test public void shouldThrowWhenInsertingAllIterableContainingNull() { assertThatThrownBy(() -> CharSeq.empty().insertAll(0, Arrays.asList(null,null))).isInstanceOf(NullPointerException.class); } // -- intersperse @Test public void shouldIntersperseNil() { assertThat(CharSeq.empty().intersperse(',')).isSameAs(CharSeq.empty()); } @Test public void shouldIntersperseSingleton() { assertThat(CharSeq.of('a').intersperse(',')).isEqualTo(CharSeq.of('a')); } @Test public void shouldIntersperseMultipleElements() { assertThat(CharSeq.of('a', 'b').intersperse(',')).isEqualTo(CharSeq.of('a', ',', 'b')); } @Test public void shouldThrowWhenInterspersingWillNullSeparator() { assertThatThrownBy(() -> CharSeq.of('a', 'b').intersperse(null)).isInstanceOf(NullPointerException.class); } // -- iterator(int) @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenNilIteratorStartingAtIndex() { CharSeq.empty().iterator(1); } @Test public void shouldIterateFirstElementOfNonNilStartingAtIndex() { assertThat(CharSeq.of('1', '2', '3').iterator(1).next()).isEqualTo('2'); } @Test public void shouldFullyIterateNonNilStartingAtIndex() { int actual = -1; for (final java.util.Iterator iter = CharSeq.of('1', '2', '3').iterator(1); iter.hasNext(); ) { actual = iter.next(); } assertThat(actual).isEqualTo('3'); } // -- prepend @Test public void shouldPrependElementToNil() { final CharSeq actual = CharSeq.empty().prepend('1'); final CharSeq expected = CharSeq.of('1'); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependElementToNonNil() { final CharSeq actual = CharSeq.of('2', '3').prepend('1'); final CharSeq expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldThrowWhenPrependingNull() { assertThatThrownBy(() -> CharSeq.empty().prepend(null)).isInstanceOf(NullPointerException.class); } // -- prependAll @Test(expected = NullPointerException.class) public void shouldThrowOnPrependAllOfNull() { CharSeq.empty().prependAll(null); } @Test public void shouldPrependAllNilToNil() { final CharSeq actual = CharSeq.empty().prependAll(CharSeq.empty()); final CharSeq expected = CharSeq.empty(); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependAllNilToNonNil() { final CharSeq actual = CharSeq.of('1', '2', '3').prependAll(CharSeq.empty()); final CharSeq expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependAllNonNilToNil() { final CharSeq actual = CharSeq.empty().prependAll(CharSeq.of('1', '2', '3')); final CharSeq expected = CharSeq.of('1', '2', '3'); assertThat(actual).isEqualTo(expected); } @Test public void shouldPrependAllNonNilToNonNil() { final CharSeq actual = CharSeq.of('4', '5', '6').prependAll(CharSeq.of('1', '2', '3')); final CharSeq expected = CharSeq.of('1', '2', '3', '4', '5', '6'); assertThat(actual).isEqualTo(expected); } @Test public void shouldThrowWhenPrependingIterableContainingNull() { assertThatThrownBy(() -> CharSeq.empty().prependAll(List.of((Character) null))).isInstanceOf(NullPointerException.class); } // -- remove @Test public void shouldRemoveElementFromNil() { assertThat(CharSeq.empty().remove(null)).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveElementFromSingleton() { assertThat(CharSeq.of('1').remove('1')).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveFirstElement() { assertThat(CharSeq.of('1', '2', '3').remove('1')).isEqualTo(CharSeq.of('2', '3')); } @Test public void shouldRemoveLastElement() { assertThat(CharSeq.of('1', '2', '3').remove('3')).isEqualTo(CharSeq.of('1', '2')); } @Test public void shouldRemoveInnerElement() { assertThat(CharSeq.of('1', '2', '3').remove('2')).isEqualTo(CharSeq.of('1', '3')); } @Test public void shouldRemoveNonExistingElement() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.remove('4')).isSameAs(t); } @Test public void shouldRemoveNull() { final CharSeq charSeq = CharSeq.of('a'); assertThat(charSeq.remove(null)).isSameAs(charSeq); } // -- removeFirst(Predicate) @Test public void shouldRemoveFirstElementByPredicateFromNil() { assertThat(CharSeq.empty().removeFirst(v -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveFirstElementByPredicateFromSingleton() { assertThat(CharSeq.of('1').removeFirst(v -> v == '1')).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveFirstElementByPredicateBegin() { assertThat(CharSeq.of('1', '2', '3').removeFirst(v -> v == '1')).isEqualTo(CharSeq.of('2', '3')); } @Test public void shouldRemoveFirstElementByPredicateBeginM() { assertThat(CharSeq.of('1', '2', '1', '3').removeFirst(v -> v == '1')).isEqualTo(CharSeq.of('2', '1', '3')); } @Test public void shouldRemoveFirstElementByPredicateEnd() { assertThat(CharSeq.of('1', '2', '3').removeFirst(v -> v == '3')).isEqualTo(CharSeq.of('1', '2')); } @Test public void shouldRemoveFirstElementByPredicateInner() { assertThat(CharSeq.of('1', '2', '3', '4', '5').removeFirst(v -> v == '3')) .isEqualTo(CharSeq.of('1', '2', '4', '5')); } @Test public void shouldRemoveFirstElementByPredicateInnerM() { assertThat(CharSeq.of('1', '2', '3', '2', '5').removeFirst(v -> v == '2')) .isEqualTo(CharSeq.of('1', '3', '2', '5')); } @Test public void shouldRemoveFirstElementByPredicateNonExisting() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.removeFirst(v -> v == 4)).isSameAs(t); } // -- removeLast(Predicate) @Test public void shouldRemoveLastElementByPredicateFromNil() { assertThat(CharSeq.empty().removeLast(v -> true)).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveLastElementByPredicateFromSingleton() { assertThat(CharSeq.of('1').removeLast(v -> v == '1')).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveLastElementByPredicateBegin() { assertThat(CharSeq.of('1', '2', '3').removeLast(v -> v == '1')).isEqualTo(CharSeq.of('2', '3')); } @Test public void shouldRemoveLastElementByPredicateEnd() { assertThat(CharSeq.of('1', '2', '3').removeLast(v -> v == '3')).isEqualTo(CharSeq.of('1', '2')); } @Test public void shouldRemoveLastElementByPredicateEndM() { assertThat(CharSeq.of('1', '3', '2', '3').removeLast(v -> v == '3')).isEqualTo(CharSeq.of('1', '3', '2')); } @Test public void shouldRemoveLastElementByPredicateInner() { assertThat(CharSeq.of('1', '2', '3', '4', '5').removeLast(v -> v == '3')) .isEqualTo(CharSeq.of('1', '2', '4', '5')); } @Test public void shouldRemoveLastElementByPredicateInnerM() { assertThat(CharSeq.of('1', '2', '3', '2', '5').removeLast(v -> v == '2')) .isEqualTo(CharSeq.of('1', '2', '3', '5')); } @Test public void shouldRemoveLastElementByPredicateNonExisting() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.removeLast(v -> v == 4)).isSameAs(t); } // -- removeAll(Iterable) @Test public void shouldRemoveAllElementsFromNil() { assertThat(CharSeq.empty().removeAll(CharSeq.of('1', '2', '3'))).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveAllExistingElementsFromNonNil() { assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').removeAll(CharSeq.of('1', '2'))) .isEqualTo(CharSeq.of('3', '3')); } @Test public void shouldNotRemoveAllNonExistingElementsFromNonNil() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.removeAll(CharSeq.of('4', '5'))).isSameAs(t); } @Test public void shouldRemoveAllIterableContainingNull() { final CharSeq charSeq = CharSeq.of('a'); assertThat(charSeq.removeAll(List.of((Character) null))).isSameAs(charSeq); } // -- removeAll(Predicate) @SuppressWarnings("deprecation") @Test public void shouldRemoveAllElementsByPredicateFromNil() { assertThat(CharSeq.empty().removeAll(Character::isDigit)).isSameAs(CharSeq.empty()); } @SuppressWarnings("deprecation") @Test public void shouldRemoveAllMatchedElementsFromNonNil() { assertThat(CharSeq.of('1', '2', '3', 'a', 'b', 'c').removeAll(Character::isDigit)) .isEqualTo(CharSeq.of('a', 'b', 'c')); } @SuppressWarnings("deprecation") @Test public void shouldNotRemoveAllNonMatchedElementsFromNonNil() { final CharSeq t = CharSeq.of('a', 'b', 'c'); assertThat(t.removeAll(Character::isDigit)).isSameAs(t); } // -- removeAll(Object) @Test public void shouldRemoveAllObjectsFromNil() { assertThat(CharSeq.empty().removeAll('1')).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveAllExistingObjectsFromNonNil() { assertThat(CharSeq.of('1', '2', '3', '1', '2', '3').removeAll('1')).isEqualTo(CharSeq.of('2', '3', '2', '3')); } @Test public void shouldNotRemoveAllNonObjectsElementsFromNonNil() { final CharSeq t = CharSeq.of('1', '2', '3'); assertThat(t.removeAll('4')).isSameAs(t); } @Test public void shouldRemoveAllNull() { final CharSeq charSeq = CharSeq.of('a'); assertThat(charSeq.removeAll((Character) null)).isSameAs(charSeq); } // -- reverse @Test public void shouldReverseNil() { assertThat(CharSeq.empty().reverse()).isSameAs(CharSeq.empty()); } @Test public void shouldReverseNonNil() { assertThat(CharSeq.of('1', '2', '3').reverse()).isEqualTo(CharSeq.of('3', '2', '1')); } // -- rotateLeft @Test public void shouldRotateLeftOnEmpty() { assertThat(CharSeq.empty().rotateLeft(1)).isSameAs(CharSeq.empty()); } @Test public void shouldRotateLeftOnSingle() { CharSeq seq = CharSeq.of('1'); assertThat(seq.rotateLeft(1)).isSameAs(seq); } @Test public void shouldRotateLeftForZero() { CharSeq seq = CharSeq.of('1', '2', '3', '4', '5'); assertThat(seq.rotateLeft(0)).isSameAs(seq); } @Test public void shouldRotateLeftForNegativeLessThatLen() { assertThat(CharSeq.of('1', '2', '3', '4', '5').rotateLeft(-2)).isEqualTo(CharSeq.of('4', '5', '1', '2', '3')); } @Test public void shouldRotateLeftForPositiveLessThatLen() { assertThat(CharSeq.of('1', '2', '3', '4', '5').rotateLeft(2)).isEqualTo(CharSeq.of('3', '4', '5', '1', '2')); } @Test public void shouldRotateLeftForPositiveGreaterThatLen() { assertThat(CharSeq.of('1', '2', '3', '4', '5').rotateLeft(5 + 2)).isEqualTo(CharSeq.of('3', '4', '5', '1', '2')); } @Test public void shouldRotateLeftForPositiveModuloLen() { CharSeq seq = CharSeq.of('1', '2', '3', '4', '5'); assertThat(seq.rotateLeft(seq.length() * 3)).isSameAs(seq); } // -- rotateRight @Test public void shouldRotateRightOnEmpty() { assertThat(CharSeq.empty().rotateRight(1)).isSameAs(CharSeq.empty()); } @Test public void shouldRotateRightOnSingle() { CharSeq seq = CharSeq.of('1'); assertThat(seq.rotateRight(1)).isSameAs(seq); } @Test public void shouldRotateRightForZero() { CharSeq seq = CharSeq.of('1', '2', '3', '4', '5'); assertThat(seq.rotateRight(0)).isSameAs(seq); } @Test public void shouldRotateRightForNegativeLessThatLen() { assertThat(CharSeq.of('1', '2', '3', '4', '5').rotateRight(-2)).isEqualTo(CharSeq.of('3', '4', '5', '1', '2')); } @Test public void shouldRotateRightForPositiveLessThatLen() { assertThat(CharSeq.of('1', '2', '3', '4', '5').rotateRight(2)).isEqualTo(CharSeq.of('4', '5', '1', '2', '3')); } @Test public void shouldRotateRightForPositiveGreaterThatLen() { assertThat(CharSeq.of('1', '2', '3', '4', '5').rotateRight(5 + 2)).isEqualTo(CharSeq.of('4', '5', '1', '2', '3')); } @Test public void shouldRotateRightForPositiveModuloLen() { CharSeq seq = CharSeq.of('1', '2', '3', '4', '5'); assertThat(seq.rotateRight(seq.length() * 3)).isSameAs(seq); } // -- update @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdateWithNegativeIndexOnNil() { CharSeq.empty().update(-1, (Character) null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdateWithNegativeIndexOnNonNil() { CharSeq.of('1').update(-1, '2'); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdateOnNil() { CharSeq.empty().update(0, (Character) null); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdateWithIndexExceedingByOneOnNonNil() { CharSeq.of('1').update(1, '2'); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenUpdateWithIndexExceedingByTwoOnNonNil() { CharSeq.of('1').update(2, '2'); } @Test public void shouldUpdateFirstElement() { assertThat(CharSeq.of('1', '2', '3').update(0, '4')).isEqualTo(CharSeq.of('4', '2', '3')); } @Test public void shouldUpdateLastElement() { assertThat(CharSeq.of('1', '2', '3').update(2, '4')).isEqualTo(CharSeq.of('1', '2', '4')); } @Test public void shouldThrowWhenUpdatingCharAtIndexWithNullChar() { assertThatThrownBy(() -> CharSeq.of('a').update(0, (Character) null)).isInstanceOf(NullPointerException.class); } // -- higher order update @Test public void shouldUpdateViaFunction() throws Exception { final Seq actual = CharSeq.of("hello").update(0, Character::toUpperCase); final Seq expected = CharSeq.of("Hello"); assertThat(actual).isEqualTo(expected); } @Test public void shouldThrowWhenUpdatingCharAtIndexWithNullCharUsingFunction() { assertThatThrownBy(() -> CharSeq.of('a').update(0, c -> (Character) null)).isInstanceOf(NullPointerException.class); } // -- slice() @Test public void shouldSlice() { assertThat(CharSeq.empty().slice(0, 0)).isSameAs(CharSeq.empty()); assertThat(CharSeq.of("123").slice(0, 0)).isSameAs(CharSeq.empty()); assertThat(CharSeq.of("123").slice(1, 0)).isSameAs(CharSeq.empty()); assertThat(CharSeq.of("123").slice(4, 5)).isSameAs(CharSeq.empty()); assertThat(CharSeq.of("123").slice(0, 3)).isEqualTo(CharSeq.of("123")); assertThat(CharSeq.of("123").slice(-1, 2)).isEqualTo(CharSeq.of("12")); assertThat(CharSeq.of("123").slice(0, 2)).isEqualTo(CharSeq.of("12")); assertThat(CharSeq.of("123").slice(1, 2)).isEqualTo(CharSeq.of("2")); assertThat(CharSeq.of("123").slice(1, 3)).isEqualTo(CharSeq.of("23")); assertThat(CharSeq.of("123").slice(1, 4)).isEqualTo(CharSeq.of("23")); } // -- sorted() @Test public void shouldSortNil() { assertThat(CharSeq.empty().sorted()).isSameAs(CharSeq.empty()); } @Test public void shouldSortNonNil() { assertThat(CharSeq.of('3', '4', '1', '2').sorted()).isEqualTo(CharSeq.of('1', '2', '3', '4')); } // -- sorted(Comparator) @Test public void shouldSortNilUsingComparator() { assertThat(CharSeq.empty().sorted((i, j) -> j - i)).isSameAs(CharSeq.empty()); } @Test public void shouldSortNonNilUsingComparator() { assertThat(CharSeq.of('3', '4', '1', '2').sorted((i, j) -> j - i)).isEqualTo(CharSeq.of('4', '3', '2', '1')); } // -- sortBy() @Test public void shouldSortByFunction() { assertThat(CharSeq.of("123").sortBy(c -> -c)).isEqualTo(CharSeq.of("321")); } @Test public void shouldSortByComparator() { assertThat(CharSeq.of("123").sortBy((i, j) -> j - i, c -> c)).isEqualTo(CharSeq.of("321")); } // -- splitAt(index) @Test public void shouldSplitAtNil() { assertThat(CharSeq.empty().splitAt(1)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.empty())); } @Test public void shouldSplitAtNonNil() { assertThat(CharSeq.of('1', '2', '3').splitAt(1)).isEqualTo(Tuple.of(CharSeq.of('1'), CharSeq.of('2', '3'))); } @Test public void shouldSplitAtBegin() { assertThat(CharSeq.of('1', '2', '3').splitAt(0)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.of('1', '2', '3'))); } @Test public void shouldSplitAtEnd() { assertThat(CharSeq.of('1', '2', '3').splitAt(3)).isEqualTo(Tuple.of(CharSeq.of('1', '2', '3'), CharSeq.empty())); } @Test public void shouldSplitAtOutOfBounds() { assertThat(CharSeq.of('1', '2', '3').splitAt(5)).isEqualTo(Tuple.of(CharSeq.of('1', '2', '3'), CharSeq.empty())); assertThat(CharSeq.of('1', '2', '3').splitAt(-1)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.of('1', '2', '3'))); } // -- splitAt(predicate) @Test public void shouldSplitPredicateAtNil() { assertThat(CharSeq.empty().splitAt(e -> true)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.empty())); } @Test public void shouldSplitPredicateAtNonNil() { assertThat(CharSeq.of('1', '2', '3').splitAt(e -> e == '2')) .isEqualTo(Tuple.of(CharSeq.of('1'), CharSeq.of('2', '3'))); } @Test public void shouldSplitAtPredicateBegin() { assertThat(CharSeq.of('1', '2', '3').splitAt(e -> e == '1')) .isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.of('1', '2', '3'))); } @Test public void shouldSplitAtPredicateEnd() { assertThat(CharSeq.of('1', '2', '3').splitAt(e -> e == '3')) .isEqualTo(Tuple.of(CharSeq.of('1', '2'), CharSeq.of('3'))); } @Test public void shouldSplitAtPredicateNotFound() { assertThat(CharSeq.of('1', '2', '3').splitAt(e -> e == '5')) .isEqualTo(Tuple.of(CharSeq.of('1', '2', '3'), CharSeq.empty())); } // -- splitAtInclusive(predicate) @Test public void shouldSplitInclusivePredicateAtNil() { assertThat(CharSeq.empty().splitAtInclusive(e -> true)).isEqualTo(Tuple.of(CharSeq.empty(), CharSeq.empty())); } @Test public void shouldSplitInclusivePredicateAtNonNil() { assertThat(CharSeq.of('1', '2', '3').splitAtInclusive(e -> e == '2')) .isEqualTo(Tuple.of(CharSeq.of('1', '2'), CharSeq.of('3'))); } @Test public void shouldSplitAtInclusivePredicateBegin() { assertThat(CharSeq.of('1', '2', '3').splitAtInclusive(e -> e == '1')) .isEqualTo(Tuple.of(CharSeq.of('1'), CharSeq.of('2', '3'))); } @Test public void shouldSplitAtInclusivePredicateEnd() { assertThat(CharSeq.of('1', '2', '3').splitAtInclusive(e -> e == '3')) .isEqualTo(Tuple.of(CharSeq.of('1', '2', '3'), CharSeq.empty())); } @Test public void shouldSplitAtInclusivePredicateNotFound() { assertThat(CharSeq.of('1', '2', '3').splitAtInclusive(e -> e == '5')) .isEqualTo(Tuple.of(CharSeq.of('1', '2', '3'), CharSeq.empty())); } // -- removeAt(index) @Test(expected = IndexOutOfBoundsException.class) public void shouldRemoveIndexAtNil() { CharSeq.empty().removeAt(1); } @Test public void shouldRemoveIndexAtSingleton() { assertThat(CharSeq.of('1').removeAt(0)).isSameAs(CharSeq.empty()); } @Test public void shouldRemoveIndexAtNonNil() { assertThat(CharSeq.of('1', '2', '3').removeAt(1)).isEqualTo(CharSeq.of('1', '3')); } @Test public void shouldRemoveIndexAtBegin() { assertThat(CharSeq.of('1', '2', '3').removeAt(0)).isEqualTo(CharSeq.of('2', '3')); } @Test public void shouldRemoveIndexAtEnd() { assertThat(CharSeq.of('1', '2', '3').removeAt(2)).isEqualTo(CharSeq.of('1', '2')); } @Test(expected = IndexOutOfBoundsException.class) public void shouldRemoveIndxOutOfBoundsLeft() { assertThat(CharSeq.of('1', '2', '3').removeAt(-1)).isEqualTo(CharSeq.of('1', '2', '3')); } @Test(expected = IndexOutOfBoundsException.class) public void shouldRemoveIndxOutOfBoundsRight() { assertThat(CharSeq.of('1', '2', '3').removeAt(5)).isEqualTo(CharSeq.of('1', '2', '3')); } // -- repeat @Test public void shouldRepeat() { assertThat(CharSeq.empty().repeat(0)).isEqualTo(CharSeq.empty()); assertThat(CharSeq.empty().repeat(5)).isEqualTo(CharSeq.empty()); assertThat(CharSeq.of("123").repeat(0)).isEqualTo(CharSeq.empty()); assertThat(CharSeq.of("123").repeat(4)).isEqualTo(CharSeq.of("123123123123")); assertThat(CharSeq.of("123").repeat(5)).isEqualTo(CharSeq.of("123123123123123")); assertThat(CharSeq.repeat('1', 0)).isEqualTo(CharSeq.empty()); assertThat(CharSeq.repeat('!', 5)).isEqualTo(CharSeq.of("!!!!!")); } @Test public void shouldCompareRepeatAgainstTestImpl() { final String value = "."; for (int i = 0; i < 10; i++) { final String source = testRepeat(value, i); for (int j = 0; j < 100; j++) { final String actual = CharSeq.of(source).repeat(j).mkString(); final String expected = testRepeat(source, j); assertThat(actual).isEqualTo(expected); } } } private String testRepeat(String source, int times) { return Stream.continually(source).take(times).mkString(); } // -- transform() @Test public void shouldTransform() { final String transformed = CharSeq.of('0').transform(v -> String.valueOf(v.get())); assertThat(transformed).isEqualTo("0"); } // -- scan, scanLeft, scanRight @Test public void shouldScan() { final CharSeq seq = CharSeq.of('1'); final CharSeq result = seq.scan('0', (c1, c2) -> (char) (c1 + c2)); assertThat(result.mkString()).isEqualTo(Vector.of('0', 'a').mkString()); } @Test public void shouldScanLeft() { final CharSeq seq = CharSeq.of('1'); final IndexedSeq result = seq.scanLeft('0', (c1, c2) -> (char) (c1 + c2)); assertThat(result).isEqualTo(Vector.of('0', 'a')); } @Test public void shouldScanRight() { final CharSeq seq = CharSeq.of('1'); final IndexedSeq result = seq.scanRight('0', (c1, c2) -> (char) (c1 + c2)); assertThat(result).isEqualTo(Vector.of('a', '0')); } // -- subSequence(beginIndex) @Test public void shouldReturnNilWhenSubSequenceFrom0OnNil() { final CharSeq actual = CharSeq.empty().subSequence(0); assertThat(actual).isSameAs(CharSeq.empty()); } @Test public void shouldReturnIdentityWhenSubSequenceFrom0OnNonNil() { final CharSeq actual = CharSeq.of('1').subSequence(0); assertThat(actual).isEqualTo(CharSeq.of('1')); } @Test public void shouldReturnNilWhenSubSequenceFrom1OnSeqOf1() { final CharSeq actual = CharSeq.of('1').subSequence(1); assertThat(actual).isSameAs(CharSeq.empty()); } @Test public void shouldReturnSubSequenceWhenIndexIsWithinRange() { final CharSeq actual = CharSeq.of('1', '2', '3').subSequence(1); assertThat(actual).isEqualTo(CharSeq.of('2', '3')); } @Test public void shouldReturnNilWhenSubSequenceBeginningWithSize() { final CharSeq actual = CharSeq.of('1', '2', '3').subSequence(3); assertThat(actual).isSameAs(CharSeq.empty()); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequenceOnNil() { CharSeq.empty().subSequence(1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequenceWithOutOfLowerBound() { CharSeq.of('1', '2', '3').subSequence(-1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequenceWithOutOfUpperBound() { CharSeq.of('1', '2', '3').subSequence(4); } // -- subSequence(beginIndex, endIndex) @Test public void shouldReturnNilWhenSubSequenceFrom0To0OnNil() { final CharSeq actual = CharSeq.empty().subSequence(0, 0); assertThat(actual).isSameAs(CharSeq.empty()); } @Test public void shouldReturnNilWhenSubSequenceFrom0To0OnNonNil() { final CharSeq actual = CharSeq.of('1').subSequence(0, 0); assertThat(actual).isSameAs(CharSeq.empty()); } @Test public void shouldReturnSeqWithFirstElementWhenSubSequenceFrom0To1OnNonNil() { final CharSeq actual = CharSeq.of('1').subSequence(0, 1); assertThat(actual).isEqualTo(CharSeq.of('1')); } @Test public void shouldReturnNilWhenSubSequenceFrom1To1OnNonNil() { final CharSeq actual = CharSeq.of('1').subSequence(1, 1); assertThat(actual).isSameAs(CharSeq.empty()); } @Test public void shouldReturnSubSequenceWhenIndicesAreWithinRange() { final CharSeq actual = CharSeq.of('1', '2', '3').subSequence(1, 3); assertThat(actual).isEqualTo(CharSeq.of('2', '3')); } @Test public void shouldReturnNilWhenIndicesBothAreUpperBound() { final CharSeq actual = CharSeq.of('1', '2', '3').subSequence(3, 3); assertThat(actual).isSameAs(CharSeq.empty()); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnSubSequenceOnNonNilWhenBeginIndexIsGreaterThanEndIndex() { CharSeq.of('1', '2', '3').subSequence(1, 0); } @Test(expected = IllegalArgumentException.class) public void shouldThrowOnSubSequenceOnNilWhenBeginIndexIsGreaterThanEndIndex() { CharSeq.empty().subSequence(1, 0); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnSubSequenceOnNonNilWhenBeginIndexExceedsLowerBound() { CharSeq.of('1', '2', '3').subSequence(-1, 2); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnSubSequenceOnNilWhenBeginIndexExceedsLowerBound() { CharSeq.empty().subSequence(-1, 2); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowWhenSubSequence2OnNil() { CharSeq.empty().subSequence(0, 1); } @Test(expected = IndexOutOfBoundsException.class) public void shouldThrowOnSubSequenceWhenEndIndexExceedsUpperBound() { CharSeq.of('1', '2', '3').subSequence(1, 4).mkString(); // force computation of last element, e.g. because Stream is lazy } // -- unzip @Test public void shouldUnzipNil() { assertThat(CharSeq.empty().unzip(x -> Tuple.of(x, x))).isEqualTo(Tuple.of(Vector.empty(), Vector.empty())); } @Test public void shouldUnzipNonNil() { final Tuple actual = CharSeq.of('0', '1').unzip(i -> Tuple.of(i, i == '0' ? 'a' : 'b')); final Tuple expected = Tuple.of(Vector.of('0', '1'), Vector.of('a', 'b')); assertThat(actual).isEqualTo(expected); } @Test public void shouldUnzip3Nil() { assertThat(CharSeq.empty().unzip3(x -> Tuple.of(x, x, x))).isEqualTo(Tuple.of(Vector.empty(), Vector.empty(), Vector.empty())); } @Test public void shouldUnzip3NonNil() { final Tuple actual = CharSeq.of('0', '1').unzip3(i -> Tuple.of(i, i == '0' ? 'a' : 'b', i == '0' ? 'b' : 'a')); final Tuple expected = Tuple.of(Vector.of('0', '1'), Vector.of('a', 'b'), Vector.of('b', 'a')); assertThat(actual).isEqualTo(expected); } // -- zip @Test public void shouldZipNils() { final Seq actual = CharSeq.empty().zip(CharSeq.empty()); assertThat(actual).isEqualTo(Vector.empty()); } @Test public void shouldZipEmptyAndNonNil() { final Seq actual = CharSeq.empty().zip(CharSeq.of('1')); assertThat(actual).isEqualTo(Vector.empty()); } @Test public void shouldZipNonEmptyAndNil() { final Seq actual = CharSeq.of('1').zip(CharSeq.empty()); assertThat(actual).isEqualTo(Vector.empty()); } @Test public void shouldZipNonNilsIfThisIsSmaller() { final IndexedSeq> actual = CharSeq.of('1', '2').zip(CharSeq.of('a', 'b', 'c')); final IndexedSeq> expected = Vector.of(Tuple.of('1', 'a'), Tuple.of('2', 'b')); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipNonNilsIfThatIsSmaller() { final IndexedSeq> actual = CharSeq.of('1', '2', '3').zip(CharSeq.of('a', 'b')); final IndexedSeq> expected = Vector.of(Tuple.of('1', 'a'), Tuple.of('2', 'b')); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipNonNilsOfSameSize() { final IndexedSeq> actual = CharSeq.of('1', '2', '3').zip(CharSeq.of('a', 'b', 'c')); final IndexedSeq> expected = Vector.of(Tuple.of('1', 'a'), Tuple.of('2', 'b'), Tuple.of('3', 'c')); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipWithThatIsNull() { CharSeq.empty().zip(null); } // -- zipAll @Test public void shouldZipAllNils() { final Seq actual = CharSeq.empty().zipAll(CharSeq.empty(), null, null); assertThat(actual).isEqualTo(Vector.empty()); } @Test public void shouldZipAllEmptyAndNonNil() { final IndexedSeq actual = CharSeq.empty().zipAll(CharSeq.of('1'), null, null); final IndexedSeq> expected = Vector.of(Tuple.of(null, '1')); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonEmptyAndNil() { final IndexedSeq actual = CharSeq.of('1').zipAll(CharSeq.empty(), null, null); final IndexedSeq> expected = Vector.of(Tuple.of('1', null)); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThisIsSmaller() { final IndexedSeq> actual = CharSeq.of('1', '2').zipAll(CharSeq.of('a', 'b', 'c'), '9', 'z'); final IndexedSeq> expected = Vector.of(Tuple.of('1', 'a'), Tuple.of('2', 'b'), Tuple.of('9', 'c')); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThatIsSmaller() { final IndexedSeq> actual = CharSeq.of('1', '2', '3').zipAll(CharSeq.of('a', 'b'), '9', 'z'); final IndexedSeq> expected = Vector.of(Tuple.of('1', 'a'), Tuple.of('2', 'b'), Tuple.of('3', 'z')); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsOfSameSize() { final IndexedSeq> actual = CharSeq.of('1', '2', '3').zipAll(CharSeq.of('a', 'b', 'c'), '9', 'z'); final IndexedSeq> expected = Vector.of(Tuple.of('1', 'a'), Tuple.of('2', 'b'), Tuple.of('3', 'c')); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipAllWithThatIsNull() { CharSeq.empty().zipAll(null, null, null); } // -- zipWithIndex @Test public void shouldZipNilWithIndex() { assertThat(CharSeq.empty().zipWithIndex()).isEqualTo(Vector.empty()); } @Test public void shouldZipNonNilWithIndex() { final IndexedSeq> actual = CharSeq.of("abc").zipWithIndex(); final IndexedSeq> expected = Vector.of(Tuple.of('a', 0), Tuple.of('b', 1), Tuple.of('c', 2)); assertThat(actual).isEqualTo(expected); } // -- static collector() @Test public void shouldStreamAndCollectNil() { final Seq actual = java.util.stream.Stream. empty().collect(CharSeq.collector()); assertThat(actual).isSameAs(CharSeq.empty()); } @Test public void shouldStreamAndCollectNonNil() { final Seq actual = java.util.stream.Stream.of('1', '2', '3').collect(CharSeq.collector()); assertThat(actual).isEqualTo(CharSeq.of('1', '2', '3')); } @Test public void shouldParallelStreamAndCollectNil() { final Seq actual = java.util.stream.Stream. empty().parallel().collect(CharSeq.collector()); assertThat(actual).isSameAs(CharSeq.empty()); } @Test public void shouldParallelStreamAndCollectNonNil() { final Seq actual = java.util.stream.Stream.of('1', '2', '3').parallel().collect(CharSeq.collector()); assertThat(actual).isEqualTo(CharSeq.of('1', '2', '3')); } // -- static empty() @Test public void shouldCreateNil() { final Seq actual = CharSeq.empty(); assertThat(actual.length()).isEqualTo(0); } // -- static of(String) @Test public void shouldWrapOtherCharSeq() { final CharSeq cs1 = CharSeq.of("123"); final CharSeq cs2 = CharSeq.of(cs1); assertThat(cs1 == cs2).isTrue(); } @Test public void shouldCreateSeqOfElements() { final CharSeq actual = CharSeq.of('1', '2'); assertThat(actual.length()).isEqualTo(2); assertThat(actual.get(0)).isEqualTo('1'); assertThat(actual.get(1)).isEqualTo('2'); } // -- static ofAll(Iterable) @Test public void shouldCreateListOfIterable() { final java.util.List arrayList = asList('1', '2'); final CharSeq actual = CharSeq.ofAll(arrayList); assertThat(actual.length()).isEqualTo(2); assertThat(actual.get(0)).isEqualTo('1'); assertThat(actual.get(1)).isEqualTo('2'); } @Test public void ofShouldReturnTheSingletonEmpty() { assertThat(CharSeq.of()).isSameAs(CharSeq.empty()); } @Test public void ofAllShouldReturnTheSingletonEmpty() { assertThat(CharSeq.ofAll(Iterator.empty())).isSameAs(CharSeq.empty()); } // -- unfold @Test public void shouldUnfoldRightToEmpty() { assertThat(CharSeq.unfoldRight(0, x -> Option.none())).isEqualTo(CharSeq.empty()); } @Test public void shouldUnfoldRightSimpleCharSeq() { this. assertThat( CharSeq.unfoldRight('j', x -> x == 'a' ? Option.none() : Option.of(new Tuple2<>(x, (char) (x - 1))))) .isEqualTo(CharSeq.of("jihgfedcb")); } @Test public void shouldUnfoldLeftToEmpty() { assertThat(CharSeq.unfoldLeft(0, x -> Option.none())).isEqualTo(CharSeq.empty()); } @Test public void shouldUnfoldLeftSimpleCharSeq() { this. assertThat( CharSeq.unfoldLeft('j', x -> x == 'a' ? Option.none() : Option.of(new Tuple2<>((char) (x - 1), x)))) .isEqualTo(CharSeq.of("bcdefghij")); } @Test public void shouldUnfoldToEmpty() { assertThat(CharSeq.unfold('j', x -> Option.none())).isEqualTo(CharSeq.empty()); } @Test public void shouldUnfoldSimpleCharSeq() { assertThat( CharSeq.unfold('j', x -> x == 'a' ? Option.none() : Option.of(new Tuple2<>((char) (x - 1), x)))) .isEqualTo(CharSeq.of("bcdefghij")); } // -- number conversion // decode* @Test public void shouldDecodeByte() { assertThat(CharSeq.of("1").decodeByte()).isEqualTo(Byte.decode("1")); } @Test(expected = NumberFormatException.class) public void shouldNotDecodeByteGivenEmptyCharSeq() { CharSeq.empty().decodeByte(); } @Test public void shouldDecodeInteger() { assertThat(CharSeq.of("1").decodeInteger()).isEqualTo(Integer.decode("1")); } @Test(expected = NumberFormatException.class) public void shouldNotDecodeIntegerGivenEmptyCharSeq() { CharSeq.empty().decodeInteger(); } @Test public void shouldDecodeLong() { assertThat(CharSeq.of("1").decodeLong()).isEqualTo(Long.decode("1")); } @Test(expected = NumberFormatException.class) public void shouldNotDecodeLongGivenEmptyCharSeq() { CharSeq.empty().decodeLong(); } @Test public void shouldDecodeShort() { assertThat(CharSeq.of("1").decodeShort()).isEqualTo(Short.decode("1")); } @Test(expected = NumberFormatException.class) public void shouldNotDecodeShortGivenEmptyCharSeq() { CharSeq.empty().decodeShort(); } // parse* @Test public void shouldParseBooleanWhenTrue() { assertThat(CharSeq.of("true").parseBoolean()).isEqualTo(Boolean.parseBoolean("true")); } @Test public void shouldParseBooleanWhenFalse() { assertThat(CharSeq.of("false").parseBoolean()).isEqualTo(Boolean.parseBoolean("false")); } @Test public void shouldParseByte() { assertThat(CharSeq.of("1").parseByte()).isEqualTo((byte) 1); } @Test(expected = NumberFormatException.class) public void shouldNotParseByteGivenEmptyCharSeq() { CharSeq.empty().parseByte(); } @Test public void shouldParseByteUsingRadix() { assertThat(CharSeq.of("11").parseByte(2)).isEqualTo((byte) 3); } @Test(expected = NumberFormatException.class) public void shouldNotParseByteUsingRadixGivenEmptyCharSeq() { CharSeq.empty().parseByte(2); } @Test public void shouldParseDouble() { assertThat(CharSeq.of("1.0").parseDouble()).isEqualTo(1.0d); } @Test(expected = NumberFormatException.class) public void shouldNotParseDoubleGivenEmptyCharSeq() { CharSeq.empty().parseDouble(); } @Test public void shouldParseFloat() { assertThat(CharSeq.of("1.0").parseFloat()).isEqualTo(1.0f); } @Test(expected = NumberFormatException.class) public void shouldNotParseFloatGivenEmptyCharSeq() { CharSeq.empty().parseFloat(); } @Test public void shouldParseInt() { assertThat(CharSeq.of("1").parseInt()).isEqualTo(1); } @Test(expected = NumberFormatException.class) public void shouldNotParseIntGivenEmptyCharSeq() { CharSeq.empty().parseInt(); } @Test public void shouldParseIntUsingRadix() { assertThat(CharSeq.of("11").parseInt(2)).isEqualTo(3); } @Test(expected = NumberFormatException.class) public void shouldNotParseIntUsingRadixGivenEmptyCharSeq() { CharSeq.empty().parseInt(2); } @Test public void shouldParseUnsignedInt() { assertThat(CharSeq.of("+1").parseUnsignedInt()).isEqualTo(1); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedIntGivenNegativeNumber() { CharSeq.of("-1").parseUnsignedInt(); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedIntGivenEmptyCharSeq() { CharSeq.empty().parseUnsignedInt(); } @Test public void shouldParseUnsignedIntUsingRadix() { assertThat(CharSeq.of("+11").parseUnsignedInt(2)).isEqualTo(3); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedIntUsingRadixGivenNegativeNumber() { CharSeq.of("-1").parseUnsignedInt(2); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedIntUsingRadixGivenEmptyCharSeq() { CharSeq.empty().parseUnsignedInt(2); } @Test public void shouldParseLong() { assertThat(CharSeq.of("1").parseLong()).isEqualTo(1L); } @Test(expected = NumberFormatException.class) public void shouldNotParseLongGivenEmptyCharSeq() { CharSeq.empty().parseLong(); } @Test public void shouldParseLongUsingRadix() { assertThat(CharSeq.of("11").parseLong(2)).isEqualTo(3L); } @Test(expected = NumberFormatException.class) public void shouldNotParseLongUsingRadixGivenEmptyCharSeq() { CharSeq.empty().parseLong(2); } @Test public void shouldParseUnsignedLong() { assertThat(CharSeq.of("+1").parseUnsignedLong()).isEqualTo(1); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedLongGivenNegativeNumber() { CharSeq.of("-1").parseUnsignedLong(); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedLongGivenEmptyCharSeq() { CharSeq.empty().parseUnsignedLong(); } @Test public void shouldParseUnsignedLongUsingRadix() { assertThat(CharSeq.of("+11").parseUnsignedLong(2)).isEqualTo(3); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedLongUsingRadixGivenNegativeNumber() { CharSeq.of("-1").parseUnsignedLong(2); } @Test(expected = NumberFormatException.class) public void shouldNotParseUnsignedLongUsingRadixGivenEmptyCharSeq() { CharSeq.empty().parseUnsignedLong(2); } @Test public void shouldParseShort() { assertThat(CharSeq.of("1").parseShort()).isEqualTo((short) 1); } @Test(expected = NumberFormatException.class) public void shouldNotParseShortGivenEmptyCharSeq() { CharSeq.empty().parseShort(); } @Test public void shouldParseShortUsingRadix() { assertThat(CharSeq.of("11").parseShort(2)).isEqualTo((short) 3); } @Test(expected = NumberFormatException.class) public void shouldNotParseShortUsingRadixGivenEmptyCharSeq() { CharSeq.empty().parseShort(2); } // to* @Test public void shouldConvertToBooleanWhenTrue() { assertThat(CharSeq.of("true").toBoolean()).isEqualTo(Boolean.valueOf("true")); } @Test public void shouldConvertToBooleanWhenFalse() { assertThat(CharSeq.of("false").toBoolean()).isEqualTo(Boolean.valueOf("false")); } @Test public void shouldConvertToByte() { assertThat(CharSeq.of("1").toByte()).isEqualTo(Byte.valueOf("1")); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToByteGivenEmptyCharSeq() { CharSeq.empty().toByte(); } @Test public void shouldConvertToByteUsingRadix() { assertThat(CharSeq.of("11").toByte(2)).isEqualTo(Byte.valueOf("11", 2)); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToByteUsingRadixGivenEmptyCharSeq() { CharSeq.empty().toByte(2); } @Test public void shouldConvertToDouble() { assertThat(CharSeq.of("1.0").toDouble()).isEqualTo(Double.valueOf("1.0")); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToDoubleGivenEmptyCharSeq() { CharSeq.empty().toDouble(); } @Test public void shouldConvertToFloat() { assertThat(CharSeq.of("1.0").toFloat()).isEqualTo(Float.valueOf("1.0")); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToFloatGivenEmptyCharSeq() { CharSeq.empty().toFloat(); } @Test public void shouldConvertToInteger() { assertThat(CharSeq.of("1").toInteger()).isEqualTo(Integer.valueOf("1")); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToIntegerGivenEmptyCharSeq() { CharSeq.empty().toInteger(); } @Test public void shouldConvertToIntegerUsingRadix() { assertThat(CharSeq.of("11").toInteger(2)).isEqualTo(Integer.valueOf("11", 2)); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToIntegerUsingRadixGivenEmptyCharSeq() { CharSeq.empty().toInteger(2); } @Test public void shouldConvertToLong() { assertThat(CharSeq.of("1").toLong()).isEqualTo(Long.valueOf("1")); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToLongGivenEmptyCharSeq() { CharSeq.empty().toLong(); } @Test public void shouldConvertToLongUsingRadix() { assertThat(CharSeq.of("11").toLong(2)).isEqualTo(Long.valueOf("11", 2)); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToLongUsingRadixGivenEmptyCharSeq() { CharSeq.empty().toLong(2); } @Test public void shouldConvertToShort() { assertThat(CharSeq.of("1").toShort()).isEqualTo(Short.valueOf("1")); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToShortGivenEmptyCharSeq() { CharSeq.empty().toShort(); } @Test public void shouldConvertToShortUsingRadix() { assertThat(CharSeq.of("11").toShort(2)).isEqualTo(Short.valueOf("11", 2)); } @Test(expected = NumberFormatException.class) public void shouldNotConvertToShortUsingRadixGivenEmptyCharSeq() { CharSeq.empty().toShort(2); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/CollectionsTest.java000066400000000000000000000073521342074374400257330ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; public class CollectionsTest { @Test public void shouldBeEqualSets() throws Exception { forAll(List.of(TreeSet.ofAll(1, 2, 3), HashSet.ofAll(1, 2, 3), LinkedHashSet.ofAll(1, 2, 3), BitSet.ofAll(1, 2, 3)), true); } @Test public void shouldNotBeEqualSets() throws Exception { forAll(List.of(HashSet.ofAll(1, 2, 3), HashSet.ofAll('a', 'b', 'c')), false); } @Test public void shouldBeEqualSeqs() throws Exception { forAll(List.of(Array.ofAll(1, 2, 3), Stream.ofAll(1, 2, 3), Vector.ofAll(1, 2, 3), List.ofAll(1, 2, 3), Queue.ofAll(1, 2, 3)), true); } @Test public void shouldNotBeEqualSeqs() throws Exception { forAll(List.of(Array.ofAll(1, 2, 3), Array.ofAll('a', 'b', 'c')), false); } @Test public void shouldBeEqualMaps() throws Exception { forAll(List.of(TreeMap.of(1, 2, 2, 3, 3, 4), HashMap.of(1, 2, 2, 3, 3, 4), LinkedHashMap.of(1, 2, 2, 3, 3, 4)), true); } @Test public void shouldNotBeEqualMaps() throws Exception { forAll(List.of(HashMap.of(1, 2, 2, 3, 3, 4), HashMap.of('a', 'b', 'c', 'd', 'e', 'f')), false); } @Test public void shouldBeEqualMultimaps() throws Exception { forAll(List.of(TreeMultimap.withSeq().empty().put(1, 1).put(1, 1).put(2, 2), HashMultimap.withSeq().empty().put(1, 1).put(1, 1).put(2, 2), LinkedHashMultimap.withSeq().empty().put(1, 1).put(1, 1).put(2, 2)), true); } @Test public void shouldNotBeEqualMultimaps() throws Exception { forAll(List.of(TreeMultimap.withSeq().empty().put(1, 1).put(1, 1).put(2, 2), HashMultimap.withSeq().empty().put('a', 'b').put('c', 'd').put('e', 'f')), false); } @Test public void shouldNotBeEqualSeqAndSet() throws Exception { forAll(List.of(Array.ofAll(1, 2, 3), TreeSet.ofAll(1, 2, 3)), false); } @Test public void shouldNotBeEqualMapAndSet() throws Exception { forAll(List.of(HashSet.of(Tuple.of(1, 2), Tuple.of(2, 3)), TreeMap.of(1, 2, 2, 3)), false); } private void forAll(List> traversables, boolean value) { for (Traversable traversable1 : traversables) { for (Traversable traversable2 : traversables) { if (traversable1 != traversable2) { assertThat(traversable1.equals(traversable2)).isEqualTo(value); if (value) { assertThat(traversable1.hashCode() == traversable2.hashCode()).isTrue(); } } } } } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/ComparatorsTest.java000066400000000000000000000016771342074374400257530ustar00rootroot00000000000000package io.vavr.collection; import org.junit.Test; import java.util.Comparator; import static io.vavr.collection.Comparators.naturalComparator; import static org.assertj.core.api.Assertions.assertThat; public class ComparatorsTest { // -- naturalComparator() @Test public void shouldCompareTwoIntegersUsingNaturalOrder() { final Comparator comparator = naturalComparator(); assertThat(comparator.compare(0, 1)).isEqualTo(-1); assertThat(comparator.compare(2, -1)).isEqualTo(1); assertThat(comparator.compare(3, 3)).isEqualTo(0); } @Test(expected = NullPointerException.class) public void shouldThrowNPEWhenComparingNullAndIntegerUsingNaturalOrder() { naturalComparator().compare(null, 1); } @Test(expected = NullPointerException.class) public void shouldThrowNPEWhenComparingIntegerAndNullUsingNaturalOrder() { naturalComparator().compare(1, null); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/HashArrayMappedTrieTest.java000066400000000000000000000175741342074374400273210ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import org.junit.Test; import java.util.Random; import java.util.function.Function; import static org.assertj.core.api.Assertions.assertThat; public class HashArrayMappedTrieTest { @Test public void testLeafSingleton() { HashArrayMappedTrie hamt = empty(); hamt = hamt.put(new WeakInteger(1), 1); assertThat(hamt.get(new WeakInteger(1))).isEqualTo(Option.some(1)); assertThat(hamt.get(new WeakInteger(11))).isEqualTo(Option.none()); assertThat(hamt.getOrElse(new WeakInteger(1), 2)).isEqualTo(1); assertThat(hamt.getOrElse(new WeakInteger(11), 2)).isEqualTo(2); assertThat(hamt.get(new WeakInteger(2))).isEqualTo(Option.none()); assertThat(hamt.getOrElse(new WeakInteger(2), 2)).isEqualTo(2); } @Test public void testLeafList() { HashArrayMappedTrie hamt = empty(); hamt = hamt.put(new WeakInteger(1), 1).put(new WeakInteger(31), 31); assertThat(hamt.get(new WeakInteger(1))).isEqualTo(Option.some(1)); assertThat(hamt.get(new WeakInteger(11))).isEqualTo(Option.none()); assertThat(hamt.get(new WeakInteger(31))).isEqualTo(Option.some(31)); assertThat(hamt.getOrElse(new WeakInteger(1), 2)).isEqualTo(1); assertThat(hamt.getOrElse(new WeakInteger(11), 2)).isEqualTo(2); assertThat(hamt.getOrElse(new WeakInteger(31), 2)).isEqualTo(31); assertThat(hamt.get(new WeakInteger(2))).isEqualTo(Option.none()); assertThat(hamt.getOrElse(new WeakInteger(2), 2)).isEqualTo(2); } @Test public void testGetExistingKey() { HashArrayMappedTrie hamt = empty(); hamt = hamt.put(1, 2).put(4, 5).put(null, 7); assertThat(hamt.containsKey(1)).isTrue(); assertThat(hamt.get(1)).isEqualTo(Option.some(2)); assertThat(hamt.getOrElse(1, 42)).isEqualTo(2); assertThat(hamt.containsKey(4)).isTrue(); assertThat(hamt.get(4)).isEqualTo(Option.some(5)); assertThat(hamt.containsKey(null)).isTrue(); assertThat(hamt.get(null)).isEqualTo(Option.some(7)); } @Test public void testGetUnknownKey() { HashArrayMappedTrie hamt = empty(); assertThat(hamt.get(2)).isEqualTo(Option.none()); assertThat(hamt.getOrElse(2, 42)).isEqualTo(42); hamt = hamt.put(1, 2).put(4, 5); assertThat(hamt.containsKey(2)).isFalse(); assertThat(hamt.get(2)).isEqualTo(Option.none()); assertThat(hamt.getOrElse(2, 42)).isEqualTo(42); assertThat(hamt.containsKey(null)).isFalse(); assertThat(hamt.get(null)).isEqualTo(Option.none()); } @Test public void testRemoveFromEmpty() { HashArrayMappedTrie hamt = empty(); hamt = hamt.remove(1); assertThat(hamt.size()).isEqualTo(0); } @Test public void testRemoveUnknownKey() { HashArrayMappedTrie hamt = empty(); hamt = hamt.put(1, 2).remove(3); assertThat(hamt.size()).isEqualTo(1); hamt = hamt.remove(1); assertThat(hamt.size()).isEqualTo(0); } @Test public void testDeepestTree() { final List ints = List.tabulate(Integer.SIZE, i -> 1 << i).sorted(); HashArrayMappedTrie hamt = empty(); hamt = ints.foldLeft(hamt, (h, i) -> h.put(i, i)); assertThat(List.ofAll(hamt.keysIterator()).sorted()).isEqualTo(ints); } @Test public void testBigData() { testBigData(5000, t -> t); } @Test public void testBigDataWeakHashCode() { testBigData(5000, t -> Tuple.of(new WeakInteger(t._1), t._2)); } private , V> void testBigData(int count, Function, Tuple2> mapper) { final Comparator cmp = new Comparator<>(); final java.util.Map rnd = rnd(count, mapper); for (java.util.Map.Entry e : rnd.entrySet()) { cmp.set(e.getKey(), e.getValue()); } cmp.test(); for (K key : new java.util.TreeSet<>(rnd.keySet())) { rnd.remove(key); cmp.remove(key); } cmp.test(); } @Test public void shouldLookupNullInZeroKey() { HashArrayMappedTrie trie = empty(); // should contain all node types for (int i = 0; i < 5000; i++) { trie = trie.put(i, i); } trie = trie.put(null, 2); assertThat(trie.get(0).get()).isEqualTo(0); // key.hashCode = 0 assertThat(trie.get(null).get()).isEqualTo(2); // key.hashCode = 0 } // - toString @Test public void shouldMakeString() { assertThat(empty().toString()).isEqualTo("HashArrayMappedTrie()"); assertThat(empty().put(1, 2).toString()).isEqualTo("HashArrayMappedTrie(1 -> 2)"); } // -- helpers private HashArrayMappedTrie of(int... ints) { HashArrayMappedTrie h = empty(); for (int i : ints) { h = h.put(h.size(), i); } return h; } private HashArrayMappedTrie empty() { return HashArrayMappedTrie.empty(); } private class WeakInteger implements Comparable { final int value; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final WeakInteger that = (WeakInteger) o; return value == that.value; } WeakInteger(int value) { this.value = value; } @Override public int hashCode() { return Math.abs(value) % 10; } @Override public int compareTo(WeakInteger other) { return Integer.compare(value, other.value); } } private class Comparator { private final java.util.Map classic = new java.util.HashMap<>(); private Map hamt = HashMap.empty(); void test() { assertThat(hamt.size()).isEqualTo(classic.size()); hamt.iterator().forEachRemaining(e -> assertThat(classic.get(e._1)).isEqualTo(e._2)); classic.forEach((k, v) -> { assertThat(hamt.get(k).get()).isEqualTo(v); assertThat(hamt.getOrElse(k, null)).isEqualTo(v); }); } void set(K key, V value) { classic.put(key, value); hamt = hamt.put(key, value); } void remove(K key) { classic.remove(key); hamt = hamt.remove(key); } } private java.util.Map rnd(int count, Function, Tuple2> mapper) { final Random r = new Random(); final java.util.HashMap mp = new java.util.HashMap<>(); for (int i = 0; i < count; i++) { final Tuple2 entry = mapper.apply(Tuple.of(r.nextInt(), r.nextInt())); mp.put(entry._1, entry._2); } return mp; } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/HashMapTest.java000066400000000000000000000163261342074374400247770ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple2; import io.vavr.control.Option; import org.assertj.core.api.Assertions; import org.junit.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Spliterator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; import java.util.stream.Stream; public class HashMapTest extends AbstractMapTest { @Override protected String className() { return "HashMap"; } @Override java.util.Map javaEmptyMap() { return new java.util.HashMap<>(); } @Override protected , T2> HashMap emptyMap() { return HashMap.empty(); } @Override protected , V, T extends V> Collector, ? extends Map> collectorWithMapper(Function keyMapper) { return HashMap.collector(keyMapper); } @Override protected , V, T> Collector, ? extends Map> collectorWithMappers(Function keyMapper, Function valueMapper) { return HashMap.collector(keyMapper, valueMapper); } @Override protected Collector, ArrayList>, ? extends Map> mapCollector() { return HashMap.collector(); } @SuppressWarnings("varargs") @SafeVarargs @Override protected final , V> HashMap mapOfTuples(Tuple2... entries) { return HashMap.ofEntries(entries); } @Override protected , V> Map mapOfTuples(Iterable> entries) { return HashMap.ofEntries(entries); } @SuppressWarnings("varargs") @SafeVarargs @Override protected final , V> HashMap mapOfEntries(java.util.Map.Entry... entries) { return HashMap.ofEntries(entries); } @Override protected , V> HashMap mapOf(K k1, V v1) { return HashMap.of(k1, v1); } @Override protected , V> HashMap mapOf(K k1, V v1, K k2, V v2) { return HashMap.of(k1, v1, k2, v2); } @Override protected , V> HashMap mapOf(K k1, V v1, K k2, V v2, K k3, V v3) { return HashMap.of(k1, v1, k2, v2, k3, v3); } @Override protected , V> Map mapOf(Stream stream, Function keyMapper, Function valueMapper) { return HashMap.ofAll(stream, keyMapper, valueMapper); } @Override protected , V> Map mapOf(Stream stream, Function> f) { return HashMap.ofAll(stream, f); } protected , V> HashMap mapOfNullKey(K k1, V v1, K k2, V v2) { return mapOf(k1, v1, k2, v2); } @Override protected , V> HashMap mapOfNullKey(K k1, V v1, K k2, V v2, K k3, V v3) { return mapOf(k1, v1, k2, v2, k3, v3); } @Override protected , V> HashMap mapTabulate(int n, Function> f) { return HashMap.tabulate(n, f); } @Override protected , V> HashMap mapFill(int n, Supplier> s) { return HashMap.fill(n, s); } // -- static narrow @Test public void shouldNarrowHashMap() { final HashMap int2doubleMap = mapOf(1, 1.0d); final HashMap number2numberMap = HashMap.narrow(int2doubleMap); final int actual = number2numberMap.put(new BigDecimal("2"), new BigDecimal("2.0")).values().sum().intValue(); assertThat(actual).isEqualTo(3); } @Test public void shouldWrapMap() { final java.util.Map source = new java.util.HashMap<>(); source.put(1, 2); source.put(3, 4); assertThat(HashMap.ofAll(source)).isEqualTo(emptyIntInt().put(1, 2).put(3, 4)); } // -- specific @Test public void shouldCalculateHashCodeOfCollision() { Assertions.assertThat(HashMap.empty().put(null, 1).put(0, 2).hashCode()) .isEqualTo(HashMap.empty().put(0, 2).put(null, 1).hashCode()); Assertions.assertThat(HashMap.empty().put(null, 1).put(0, 2).hashCode()) .isEqualTo(HashMap.empty().put(null, 1).put(0, 2).hashCode()); } @Test public void shouldCheckHashCodeInLeafList() { HashMap trie = HashMap.empty(); trie = trie.put(0, 1).put(null, 2); // LeafList.hash == 0 final Option none = trie.get(1 << 6); // (key.hash & BUCKET_BITS) == 0 Assertions.assertThat(none).isEqualTo(Option.none()); } @Test public void shouldCalculateBigHashCode() { HashMap h1 = HashMap.empty(); HashMap h2 = HashMap.empty(); final int count = 1234; for (int i = 0; i <= count; i++) { h1 = h1.put(i, i); h2 = h2.put(count - i, count - i); } Assertions.assertThat(h1.hashCode() == h2.hashCode()).isTrue(); } @Test public void shouldEqualsIgnoreOrder() { HashMap map = HashMap. empty().put("Aa", 1).put("BB", 2); HashMap map2 = HashMap. empty().put("BB", 2).put("Aa", 1); Assertions.assertThat(map.hashCode()).isEqualTo(map2.hashCode()); Assertions.assertThat(map).isEqualTo(map2); } // -- spliterator @Test public void shouldNotHaveSortedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SORTED)).isFalse(); } @Test public void shouldNotHaveOrderedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.ORDERED)).isFalse(); } // -- isSequential() @Test public void shouldReturnFalseWhenIsSequentialCalled() { assertThat(of(1, 2, 3).isSequential()).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/HashMultimapTest.java000066400000000000000000000204421342074374400260440ustar00rootroot00000000000000package io.vavr.collection; import io.vavr.Tuple2; import org.assertj.core.api.Assertions; import org.junit.Test; import java.math.BigDecimal; import java.util.*; import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.*; import java.util.stream.Stream; public class HashMultimapTest extends AbstractMultimapTest { @Override protected String className() { return "HashMultimap[" + containerName() + "]"; } @Override java.util.Map javaEmptyMap() { return new java.util.HashMap<>(); } @Override protected , T2> HashMultimap emptyMap(Comparator comparator) { switch (containerType) { case SEQ: return HashMultimap.withSeq().empty(); case SET: return HashMultimap.withSet().empty(); case SORTED_SET: return HashMultimap.withSortedSet(comparator).empty(); default: throw new RuntimeException(); } } @Override protected Collector, ArrayList>, ? extends Multimap> mapCollector() { switch (containerType) { case SEQ: return HashMultimap.withSeq().collector(); case SET: return HashMultimap.withSet().collector(); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).collector(); default: throw new RuntimeException(); } } @SuppressWarnings("varargs") @SafeVarargs @Override protected final , V> HashMultimap mapOfTuples(Tuple2... entries) { switch (containerType) { case SEQ: return HashMultimap.withSeq().ofEntries(entries); case SET: return HashMultimap.withSet().ofEntries(entries); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).ofEntries(entries); default: throw new RuntimeException(); } } @SuppressWarnings("varargs") @SafeVarargs @Override protected final , V> HashMultimap mapOfEntries(java.util.Map.Entry... entries) { switch (containerType) { case SEQ: return HashMultimap.withSeq().ofEntries(entries); case SET: return HashMultimap.withSet().ofEntries(entries); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).ofEntries(entries); default: throw new RuntimeException(); } } @Override protected , V> HashMultimap mapOfPairs(K k1, V v1, K k2, V v2, K k3, V v3) { switch (containerType) { case SEQ: return HashMultimap.withSeq().of(k1, v1, k2, v2, k3, v3); case SET: return HashMultimap.withSet().of(k1, v1, k2, v2, k3, v3); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).of(k1, v1, k2, v2, k3, v3); default: throw new RuntimeException(); } } @Override protected , V> HashMultimap mapOf(K key, V value) { switch (containerType) { case SEQ: return HashMultimap.withSeq().of(key, value); case SET: return HashMultimap.withSet().of(key, value); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).of(key, value); default: throw new RuntimeException(); } } @Override protected , V> HashMultimap mapOf(Map map) { switch (containerType) { case SEQ: return HashMultimap.withSeq().ofAll(map); case SET: return HashMultimap.withSet().ofAll(map); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).ofAll(map); default: throw new RuntimeException(); } } @Override protected , V> HashMultimap mapOf(Stream stream, Function keyMapper, Function valueMapper) { switch (containerType) { case SEQ: return HashMultimap.withSeq().ofAll(stream, keyMapper, valueMapper); case SET: return HashMultimap.withSet().ofAll(stream, keyMapper, valueMapper); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).ofAll(stream, keyMapper, valueMapper); default: throw new RuntimeException(); } } @Override protected , V> HashMultimap mapOf(Stream stream, Function> f) { switch (containerType) { case SEQ: return HashMultimap.withSeq().ofAll(stream, f); case SET: return HashMultimap.withSet().ofAll(stream, f); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).ofAll(stream, f); default: throw new RuntimeException(); } } @Override protected , V> HashMultimap mapTabulate(int n, Function> f) { switch (containerType) { case SEQ: return HashMultimap.withSeq().tabulate(n, f); case SET: return HashMultimap.withSet().tabulate(n, f); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).tabulate(n, f); default: throw new RuntimeException(); } } @Override protected , V> HashMultimap mapFill(int n, Supplier> s) { switch (containerType) { case SEQ: return HashMultimap.withSeq().fill(n, s); case SET: return HashMultimap.withSet().fill(n, s); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).fill(n, s); default: throw new RuntimeException(); } } @Override protected , V> Multimap mapFill(int n, Tuple2 element) { switch (containerType) { case SEQ: return HashMultimap.withSeq().fill(n, element); case SET: return HashMultimap.withSet().fill(n, element); case SORTED_SET: return HashMultimap.withSortedSet(Comparators.naturalComparator()).fill(n, element); default: throw new RuntimeException(); } } // -- static narrow @Test public void shouldNarrowMap() { final HashMultimap int2doubleMap = (HashMultimap) this. emptyMap().put(1, 1.0d); final HashMultimap number2numberMap = HashMultimap.narrow(int2doubleMap); final int actual = number2numberMap.put(new BigDecimal("2"), new BigDecimal("2.0")).values().sum().intValue(); assertThat(actual).isEqualTo(3); } // -- spliterator @Test public void shouldNotHaveSortedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SORTED)).isFalse(); } @Test public void shouldNotHaveOrderedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.ORDERED)).isFalse(); } // -- isSequential() @Test public void shouldReturnTrueWhenIsSequentialCalled() { assertThat(of(1, 2, 3).isSequential()).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/HashSetTest.java000066400000000000000000000355521342074374400250170ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Value; import io.vavr.Tuple2; import org.assertj.core.api.*; import org.junit.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Spliterator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; import static org.junit.Assert.assertTrue; public class HashSetTest extends AbstractSetTest { @Override protected IterableAssert assertThat(Iterable actual) { return new IterableAssert(actual) { @Override public IterableAssert isEqualTo(Object obj) { @SuppressWarnings("unchecked") final Iterable expected = (Iterable) obj; final java.util.Map actualMap = countMap(actual); final java.util.Map expectedMap = countMap(expected); assertThat(actualMap.size()).isEqualTo(expectedMap.size()); actualMap.keySet().forEach(k -> assertThat(actualMap.get(k)).isEqualTo(expectedMap.get(k))); return this; } private java.util.Map countMap(Iterable it) { final java.util.HashMap cnt = new java.util.HashMap<>(); it.forEach(i -> cnt.merge(i, 1, (v1, v2) -> v1 + v2)); return cnt; } }; } @Override protected ObjectAssert assertThat(T actual) { return new ObjectAssert(actual) { }; } @Override protected BooleanAssert assertThat(Boolean actual) { return new BooleanAssert(actual) { }; } @Override protected DoubleAssert assertThat(Double actual) { return new DoubleAssert(actual) { }; } @Override protected IntegerAssert assertThat(Integer actual) { return new IntegerAssert(actual) { }; } @Override protected LongAssert assertThat(Long actual) { return new LongAssert(actual) { }; } @Override protected StringAssert assertThat(String actual) { return new StringAssert(actual) { }; } // -- construction @Override protected Collector, HashSet> collector() { return HashSet.collector(); } @Override protected HashSet empty() { return HashSet.empty(); } @Override protected HashSet emptyWithNull() { return empty(); } @Override protected HashSet of(T element) { return HashSet.of(element); } @SuppressWarnings("varargs") @SafeVarargs @Override protected final HashSet of(T... elements) { return HashSet.of(elements); } @Override protected HashSet ofAll(Iterable elements) { return HashSet.ofAll(elements); } @Override protected > HashSet ofJavaStream(java.util.stream.Stream javaStream) { return HashSet.ofAll(javaStream); } @Override protected HashSet ofAll(boolean... elements) { return HashSet.ofAll(elements); } @Override protected HashSet ofAll(byte... elements) { return HashSet.ofAll(elements); } @Override protected HashSet ofAll(char... elements) { return HashSet.ofAll(elements); } @Override protected HashSet ofAll(double... elements) { return HashSet.ofAll(elements); } @Override protected HashSet ofAll(float... elements) { return HashSet.ofAll(elements); } @Override protected HashSet ofAll(int... elements) { return HashSet.ofAll(elements); } @Override protected HashSet ofAll(long... elements) { return HashSet.ofAll(elements); } @Override protected HashSet ofAll(short... elements) { return HashSet.ofAll(elements); } @Override protected HashSet tabulate(int n, Function f) { return HashSet.tabulate(n, f); } @Override protected HashSet fill(int n, Supplier s) { return HashSet.fill(n, s); } @Override protected int getPeekNonNilPerformingAnAction() { return 1; } // -- static narrow @Test public void shouldNarrowHashSet() { final HashSet doubles = of(1.0d); final HashSet numbers = HashSet.narrow(doubles); final int actual = numbers.add(new BigDecimal("2.0")).sum().intValue(); assertThat(actual).isEqualTo(3); } // -- slideBy is not expected to work for larger subsequences, due to unspecified iteration order @Test public void shouldSlideNonNilBySomeClassifier() { // ignore } // TODO move to traversable // -- zip @Test public void shouldZipNils() { final HashSet> actual = empty().zip(empty()); assertThat(actual).isEqualTo(empty()); } @Test public void shouldZipEmptyAndNonNil() { final HashSet> actual = empty().zip(of(1)); assertThat(actual).isEqualTo(empty()); } @Test public void shouldZipNonEmptyAndNil() { final HashSet> actual = of(1).zip(empty()); assertThat(actual).isEqualTo(empty()); } @Test public void shouldZipNonNilsIfThisIsSmaller() { final HashSet> actual = of(1, 2).zip(of("a", "b", "c")); final HashSet> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipNonNilsIfThatIsSmaller() { final HashSet> actual = of(1, 2, 3).zip(of("a", "b")); final HashSet> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipNonNilsOfSameSize() { final HashSet> actual = of(1, 2, 3).zip(of("a", "b", "c")); final HashSet> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(3, "c")); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipWithThatIsNull() { empty().zip(null); } // TODO move to traversable // -- zipAll @Test public void shouldZipAllNils() { // ignore } @Test public void shouldZipAllEmptyAndNonNil() { // ignore } @Test public void shouldZipAllNonEmptyAndNil() { final HashSet actual = of(1).zipAll(empty(), null, null); final HashSet> expected = of(Tuple.of(1, null)); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThisIsSmaller() { final HashSet> actual = of(1, 2).zipAll(of("a", "b", "c"), 9, "z"); final HashSet> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(9, "c")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsIfThatIsSmaller() { final HashSet> actual = of(1, 2, 3).zipAll(of("a", "b"), 9, "z"); final HashSet> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(3, "z")); assertThat(actual).isEqualTo(expected); } @Test public void shouldZipAllNonNilsOfSameSize() { final HashSet> actual = of(1, 2, 3).zipAll(of("a", "b", "c"), 9, "z"); final HashSet> expected = of(Tuple.of(1, "a"), Tuple.of(2, "b"), Tuple.of(3, "c")); assertThat(actual).isEqualTo(expected); } @Test(expected = NullPointerException.class) public void shouldThrowIfZipAllWithThatIsNull() { empty().zipAll(null, null, null); } // TODO move to traversable // -- zipWithIndex @Test public void shouldZipNilWithIndex() { assertThat(this. empty().zipWithIndex()).isEqualTo(this.> empty()); } @Test public void shouldZipNonNilWithIndex() { final HashSet> actual = of("a", "b", "c").zipWithIndex(); final HashSet> expected = of(Tuple.of("a", 0), Tuple.of("b", 1), Tuple.of("c", 2)); assertThat(actual).isEqualTo(expected); } // -- transform() @Test public void shouldTransform() { final String transformed = of(42).transform(v -> String.valueOf(v.get())); assertThat(transformed).isEqualTo("42"); } // HashSet special cases @Override public void shouldDropRightAsExpectedIfCountIsLessThanSize() { assertThat(of(1, 2, 3).dropRight(2)).isEqualTo(of(3)); } @Override public void shouldTakeRightAsExpectedIfCountIsLessThanSize() { assertThat(of(1, 2, 3).takeRight(2)).isEqualTo(of(1, 2)); } @Override public void shouldGetInitOfNonNil() { assertThat(of(1, 2, 3).init()).isEqualTo(of(2, 3)); } @Override public void shouldFoldRightNonNil() { final String actual = of('a', 'b', 'c').foldRight("", (x, xs) -> x + xs); final List expected = List.of('a', 'b', 'c').permutations().map(List::mkString); assertThat(actual).isIn(expected); } @Override public void shouldReduceRightNonNil() { final String actual = of("a", "b", "c").reduceRight((x, xs) -> x + xs); final List expected = List.of("a", "b", "c").permutations().map(List::mkString); assertThat(actual).isIn(expected); } @Override public void shouldMkStringWithDelimiterNonNil() { final String actual = of('a', 'b', 'c').mkString(","); final List expected = List.of('a', 'b', 'c').permutations().map(l -> l.mkString(",")); assertThat(actual).isIn(expected); } @Override public void shouldMkStringWithDelimiterAndPrefixAndSuffixNonNil() { final String actual = of('a', 'b', 'c').mkString("[", ",", "]"); final List expected = List.of('a', 'b', 'c').permutations().map(l -> l.mkString("[", ",", "]")); assertThat(actual).isIn(expected); } @Override public void shouldComputeDistinctByOfNonEmptyTraversableUsingComparator() { // TODO } @Override public void shouldComputeDistinctByOfNonEmptyTraversableUsingKeyExtractor() { // TODO } @Override public void shouldFindLastOfNonNil() { final int actual = of(1, 2, 3, 4).findLast(i -> i % 2 == 0).get(); assertThat(actual).isIn(List.of(1, 2, 3, 4)); } @Override public void shouldThrowWhenFoldRightNullOperator() { throw new NullPointerException(); // TODO } @Override public void shouldReturnSomeInitWhenCallingInitOptionOnNonNil() { // TODO } @Test public void shouldBeEqual() { assertTrue(HashSet.of(1).equals(HashSet.of(1))); } //fixme: delete, when useIsEqualToInsteadOfIsSameAs() will be eliminated from AbstractValueTest class @Override protected boolean useIsEqualToInsteadOfIsSameAs() { return false; } @Override protected HashSet range(char from, char toExclusive) { return HashSet.range(from, toExclusive); } @Override protected HashSet rangeBy(char from, char toExclusive, int step) { return HashSet.rangeBy(from, toExclusive, step); } @Override protected HashSet rangeBy(double from, double toExclusive, double step) { return HashSet.rangeBy(from, toExclusive, step); } @Override protected HashSet range(int from, int toExclusive) { return HashSet.range(from, toExclusive); } @Override protected HashSet rangeBy(int from, int toExclusive, int step) { return HashSet.rangeBy(from, toExclusive, step); } @Override protected HashSet range(long from, long toExclusive) { return HashSet.range(from, toExclusive); } @Override protected HashSet rangeBy(long from, long toExclusive, long step) { return HashSet.rangeBy(from, toExclusive, step); } @Override protected HashSet rangeClosed(char from, char toInclusive) { return HashSet.rangeClosed(from, toInclusive); } @Override protected HashSet rangeClosedBy(char from, char toInclusive, int step) { return HashSet.rangeClosedBy(from, toInclusive, step); } @Override protected HashSet rangeClosedBy(double from, double toInclusive, double step) { return HashSet.rangeClosedBy(from, toInclusive, step); } @Override protected HashSet rangeClosed(int from, int toInclusive) { return HashSet.rangeClosed(from, toInclusive); } @Override protected HashSet rangeClosedBy(int from, int toInclusive, int step) { return HashSet.rangeClosedBy(from, toInclusive, step); } @Override protected HashSet rangeClosed(long from, long toInclusive) { return HashSet.rangeClosed(from, toInclusive); } @Override protected HashSet rangeClosedBy(long from, long toInclusive, long step) { return HashSet.rangeClosedBy(from, toInclusive, step); } // -- toSet @Test public void shouldReturnSelfOnConvertToSet() { final Value value = of(1, 2, 3); assertThat(value.toSet()).isSameAs(value); } // -- spliterator @Test public void shouldNotHaveSortedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SORTED)).isFalse(); } @Test public void shouldNotHaveOrderedSpliterator() { assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.ORDERED)).isFalse(); } // -- isSequential() @Test public void shouldReturnFalseWhenIsSequentialCalled() { assertThat(of(1, 2, 3).isSequential()).isFalse(); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/IntMap.java000066400000000000000000000320261342074374400240010ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.Tuple3; import io.vavr.control.Option; import io.vavr.Tuple2; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.Spliterator; import java.util.function.*; public final class IntMap implements Traversable, Serializable { private static final long serialVersionUID = 1L; private final Map original; private static final IntMap EMPTY = new IntMap<>(HashMap.empty()); @SuppressWarnings("unchecked") public static IntMap of(Map original) { return original.isEmpty() ? (IntMap) EMPTY : new IntMap<>(original); } // DEV-NOTE: needs to be used internally to ensure the isSameAs property of the original is reflected by this impl private IntMap unit(Map original) { return (this.original == original) ? this : of(original); } private IntMap(Map original) { this.original = original; } @Override public boolean isAsync() { return original.isAsync(); } @Override public boolean isDistinct() { return original.isDistinct(); } @Override public boolean isLazy() { return original.isLazy(); } @Override public boolean equals(Object o) { final Object that = (o instanceof IntMap) ?((IntMap) o).original : o; return Collections.equals(original, that); } @Override public int hashCode() { return original.hashCode(); } @Override public String stringPrefix() { return "IntMap"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } @Override public Seq collect(PartialFunction partialFunction) { Objects.requireNonNull(partialFunction, "partialFunction is null"); final PartialFunction, R> pf = new PartialFunction, R>() { private static final long serialVersionUID = 1L; @Override public R apply(Tuple2 entry) { return partialFunction.apply(entry._2); } @Override public boolean isDefinedAt(Tuple2 entry) { return partialFunction.isDefinedAt(entry._2); } }; return original.collect(pf); } @Override public IntMap distinct() { return unit(original.distinct()); } @Override public IntMap distinctBy(Comparator comparator) { return unit(original.distinctBy((o1, o2) -> comparator.compare(o1._2, o2._2))); } @Override public IntMap distinctBy(Function keyExtractor) { return unit(original.distinctBy(f -> keyExtractor.apply(f._2))); } @Override public IntMap drop(int n) { final Map dropped = original.drop(n); return dropped == original ? this : unit(dropped); } @Override public IntMap dropRight(int n) { final Map dropped = original.dropRight(n); return dropped == original ? this : unit(dropped); } @Override public IntMap dropUntil(Predicate predicate) { return unit(original.dropUntil(p -> predicate.test(p._2))); } @Override public IntMap dropWhile(Predicate predicate) { return unit(original.dropWhile(p -> predicate.test(p._2))); } @Override public IntMap filter(Predicate predicate) { return unit(original.filter(p -> predicate.test(p._2))); } @Override public IntMap reject(Predicate predicate) { return unit(original.reject(p -> predicate.test(p._2))); } @Override public Seq flatMap(Function> mapper) { return original.flatMap(e -> mapper.apply(e._2)); } @Override public U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return original.foldRight(zero, (e, u) -> f.apply(e._2, u)); } @Override public Map> groupBy(Function classifier) { return original.groupBy(e -> classifier.apply(e._2)).map((k, v) -> Tuple.of(k, IntMap.of(v))); } @Override public Iterator> grouped(int size) { return original.grouped(size).map(IntMap::of); } @Override public boolean hasDefiniteSize() { return original.hasDefiniteSize(); } @Override public T head() { return original.head()._2; } @Override public Option headOption() { return original.headOption().map(o -> o._2); } @Override public IntMap init() { return IntMap.of(original.init()); } @Override public Option> initOption() { return original.initOption().map(IntMap::of); } @Override public boolean isEmpty() { return original.isEmpty(); } @Override public boolean isTraversableAgain() { return original.isTraversableAgain(); } @Override public T last() { return original.last()._2; } @Override public int length() { return original.length(); } @Override public Seq map(Function mapper) { return original.map(e -> mapper.apply(e._2)); } @Override public IntMap orElse(Iterable other) { return unit(original.orElse(List.ofAll(other).zipWithIndex().map(t -> Tuple.of(t._2, t._1)))); } @SuppressWarnings("unchecked") @Override public IntMap orElse(Supplier> supplier) { return unit(original.orElse(() -> (Iterable>) List.ofAll(supplier.get()).zipWithIndex().map(t -> Tuple.of(t._2, t._1)))); } @Override public Tuple2, IntMap> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return original.partition(p -> predicate.test(p._2)).map(IntMap::of, IntMap::of); } @Override public IntMap peek(Consumer action) { original.peek(e -> action.accept(e._2)); return this; } @Override public IntMap replace(T currentElement, T newElement) { final Option> currentEntryOpt = original.find(e -> e._2.equals(currentElement)); if (currentEntryOpt.isDefined()) { final Tuple2 currentEntry = currentEntryOpt.get(); return unit(original.replace(currentEntry, Tuple.of(original.size() + 1, newElement))); } else { return this; } } @Override public IntMap replaceAll(T currentElement, T newElement) { Map result = original; for (Tuple2 entry : original.filter(e -> e._2.equals(currentElement))) { result = result.replaceAll(entry, Tuple.of(entry._1, newElement)); } return unit(result); } @Override public IntMap retainAll(Iterable elements) { final Set elementsSet = HashSet.ofAll(elements); return unit(original.retainAll(original.filter(e -> elementsSet.contains(e._2)))); } @Override public Traversable scan(T zero, BiFunction operation) { final int[] index = new int[] { 0 }; return original.scan(Tuple.of(-1, zero), (i, t) -> Tuple.of(index[0]++, operation.apply(i._2, t._2))).values(); } @Override public Traversable scanLeft(U zero, BiFunction operation) { return original.scanLeft(zero, (i, t) -> operation.apply(i, t._2)); } @Override public Traversable scanRight(U zero, BiFunction operation) { return original.scanRight(zero, (t, i) -> operation.apply(t._2, i)); } @Override public Iterator> slideBy(Function classifier) { return original.slideBy(e -> classifier.apply(e._2)).map(IntMap::of); } @Override public Iterator> sliding(int size) { return original.sliding(size).map(IntMap::of); } @Override public Iterator> sliding(int size, int step) { return original.sliding(size, step).map(IntMap::of); } @Override public Tuple2, ? extends IntMap> span(Predicate predicate) { return original.span(p -> predicate.test(p._2)).map(IntMap::of, IntMap::of); } public Spliterator spliterator() { class SpliteratorProxy implements Spliterator { private final Spliterator> spliterator; private SpliteratorProxy(Spliterator> spliterator) { this.spliterator = spliterator; } @Override public boolean tryAdvance(Consumer action) { return spliterator.tryAdvance(a -> action.accept(a._2)); } @Override public Spliterator trySplit() { return new SpliteratorProxy(spliterator.trySplit()); } @Override public long estimateSize() { return spliterator.estimateSize(); } @Override public int characteristics() { return spliterator.characteristics(); } @Override public Comparator getComparator() { if (hasCharacteristics(Spliterator.SORTED)) { return null; } throw new IllegalStateException(); } } return new SpliteratorProxy(original.spliterator()); } @Override public IntMap tail() { return IntMap.of(original.tail()); } @Override public Option> tailOption() { return original.tailOption().map(IntMap::of); } @Override public IntMap take(int n) { return unit(original.take(n)); } @Override public IntMap takeRight(int n) { return unit(original.takeRight(n)); } @Override public Traversable takeUntil(Predicate predicate) { return unit(original.takeUntil(p -> predicate.test(p._2))); } @Override public IntMap takeWhile(Predicate predicate) { return unit(original.takeWhile(p -> predicate.test(p._2))); } @Override public Tuple2, Seq> unzip(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip(unzipper).map(Stream::ofAll, Stream::ofAll); } @Override public Tuple3, Seq, Seq> unzip3(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map(Stream::ofAll, Stream::ofAll, Stream::ofAll); } @Override public Seq> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public Seq zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWith(that, mapper)); } @Override public Seq> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return Stream.ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public Seq> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public Seq zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWithIndex(mapper)); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/IntMod2.java000066400000000000000000000032131342074374400240610ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; /** * An Int wrapper that implements equality by comparing int values modulo 2. *
* Examples: *
    *
  • IntMod2(0) equals IntMod2(2) equals IntMod2(4) ...
  • *
  • IntMod2(1) equals IntMod2(3) equals IntMod2(5) ...
  • *
  • IntMod2(0) < IntMod2(1)
  • *
  • IntMod2(_even_int_) < IntMod2(_odd_int_)
  • *
*/ final class IntMod2 implements Comparable { private final int val; IntMod2(int val) { this.val = val; } @Override public int compareTo(IntMod2 that) { return this.hashCode() - that.hashCode(); } @Override public boolean equals(Object that) { return that == this || (that instanceof IntMod2 && this.hashCode() == that.hashCode()); } @Override public int hashCode() { return val % 2; } @Override public String toString() { return String.valueOf(val); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/IntMod2Test.java000066400000000000000000000031111342074374400247160ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; public class IntMod2Test { private static final IntMod2 _1 = new IntMod2(1); private static final IntMod2 _2 = new IntMod2(2); private static final IntMod2 _3 = new IntMod2(3); private static final IntMod2 _4 = new IntMod2(4); @Test public void shouldBeEqualIfEven() { assertThat(_2.equals(_4)).isTrue(); assertThat(_2.compareTo(_4)).isEqualTo(0); } @Test public void shouldBeEqualIfOdd() { assertThat(_1.equals(_3)).isTrue(); assertThat(_1.compareTo(_3)).isEqualTo(0); } @Test public void shouldNotBeEqualIfEvenAndOdd() { assertThat(_1.equals(_2)).isFalse(); assertThat(_1.compareTo(_2)).isEqualTo(1); assertThat(_2.compareTo(_3)).isEqualTo(-1); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/IntMultimap.java000066400000000000000000000323461342074374400250610ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.PartialFunction; import io.vavr.Tuple; import io.vavr.Tuple3; import io.vavr.Tuple2; import io.vavr.control.Option; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.Spliterator; import java.util.function.*; public final class IntMultimap implements Traversable, Serializable { private static final long serialVersionUID = 1L; private final Multimap original; public static IntMultimap of(Multimap original) { return new IntMultimap<>(original); } // DEV-NOTE: needs to be used internally to ensure the isSameAs property of the original is reflected by this impl private IntMultimap unit(Multimap original) { return (this.original == original) ? this : of(original); } private IntMultimap(Multimap original) { this.original = original; } @Override public boolean isAsync() { return original.isAsync(); } @Override public boolean isDistinct() { return original.isDistinct(); } @Override public boolean isLazy() { return original.isLazy(); } @Override public boolean isSequential() { return original.isSequential(); } @Override public boolean equals(Object o) { final Object that = (o instanceof IntMultimap) ? ((IntMultimap) o).original : o; return Collections.equals(original, that); } @Override public int hashCode() { return original.hashCode(); } @Override public String stringPrefix() { return "IntMultimap"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } @Override public Seq collect(PartialFunction partialFunction) { Objects.requireNonNull(partialFunction, "partialFunction is null"); final PartialFunction, R> pf = new PartialFunction, R>() { private static final long serialVersionUID = 1L; @Override public R apply(Tuple2 entry) { return partialFunction.apply(entry._2); } @Override public boolean isDefinedAt(Tuple2 entry) { return partialFunction.isDefinedAt(entry._2); } }; return original.collect(pf); } @Override public IntMultimap distinct() { return unit(original.distinct()); } @Override public IntMultimap distinctBy(Comparator comparator) { return unit(original.distinctBy((o1, o2) -> comparator.compare(o1._2, o2._2))); } @Override public IntMultimap distinctBy(Function keyExtractor) { return unit(original.distinctBy(f -> keyExtractor.apply(f._2))); } @Override public IntMultimap drop(int n) { final Multimap dropped = original.drop(n); return dropped == original ? this : unit(dropped); } @Override public IntMultimap dropRight(int n) { final Multimap dropped = original.dropRight(n); return dropped == original ? this : unit(dropped); } @Override public IntMultimap dropUntil(Predicate predicate) { return unit(original.dropUntil(p -> predicate.test(p._2))); } @Override public IntMultimap dropWhile(Predicate predicate) { return unit(original.dropWhile(p -> predicate.test(p._2))); } @Override public IntMultimap filter(Predicate predicate) { return unit(original.filter(p -> predicate.test(p._2))); } @Override public IntMultimap reject(Predicate predicate) { return unit(original.reject(p -> predicate.test(p._2))); } @Override public Seq flatMap(Function> mapper) { return original.flatMap(e -> mapper.apply(e._2)); } @Override public U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return original.foldRight(zero, (e, u) -> f.apply(e._2, u)); } @Override public Map> groupBy(Function classifier) { return original.groupBy(e -> classifier.apply(e._2)).map((k, v) -> Tuple.of(k, IntMultimap.of(v))); } @Override public Iterator> grouped(int size) { return original.grouped(size).map(IntMultimap::of); } @Override public boolean hasDefiniteSize() { return original.hasDefiniteSize(); } @Override public T head() { return original.head()._2; } @Override public Option headOption() { return original.headOption().map(o -> o._2); } @Override public IntMultimap init() { return IntMultimap.of(original.init()); } @Override public Option> initOption() { return original.initOption().map(IntMultimap::of); } @Override public boolean isEmpty() { return original.isEmpty(); } @Override public boolean isTraversableAgain() { return original.isTraversableAgain(); } @Override public T last() { return original.last()._2; } @Override public int length() { return original.length(); } @Override public Seq map(Function mapper) { return original.map(e -> mapper.apply(e._2)); } @Override public IntMultimap orElse(Iterable other) { return unit(original.orElse(List.ofAll(other).zipWithIndex().map(t -> Tuple.of(t._2, t._1)))); } @SuppressWarnings("unchecked") @Override public IntMultimap orElse(Supplier> supplier) { return unit(original.orElse(() -> (Iterable>) List.ofAll(supplier.get()).zipWithIndex().map(t -> Tuple.of(t._2, t._1)))); } @Override public Tuple2, IntMultimap> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return original.partition(p -> predicate.test(p._2)).map(IntMultimap::of, IntMultimap::of); } @Override public IntMultimap peek(Consumer action) { original.peek(e -> action.accept(e._2)); return this; } @Override public IntMultimap replace(T currentElement, T newElement) { final Option> currentEntryOpt = original.find(e -> e._2.equals(currentElement)); if (currentEntryOpt.isDefined()) { final Tuple2 currentEntry = currentEntryOpt.get(); return unit(original.replace(currentEntry, Tuple.of(original.size() + 1, newElement))); } else { return this; } } @Override public IntMultimap replaceAll(T currentElement, T newElement) { Multimap result = original; for (Tuple2 entry : original.filter(e -> e._2.equals(currentElement))) { result = result.replaceAll(entry, Tuple.of(entry._1, newElement)); } return unit(result); } @Override public IntMultimap retainAll(Iterable elements) { final Set elementsSet = HashSet.ofAll(elements); return unit(original.retainAll(original.filter(e -> elementsSet.contains(e._2)))); } @Override public Traversable scan(T zero, BiFunction operation) { final int[] index = new int[] { 0 }; return original.scan(Tuple.of(-1, zero), (i, t) -> Tuple.of(index[0]++, operation.apply(i._2, t._2))).values(); } @Override public Traversable scanLeft(U zero, BiFunction operation) { return original.scanLeft(zero, (i, t) -> operation.apply(i, t._2)); } @Override public Traversable scanRight(U zero, BiFunction operation) { return original.scanRight(zero, (t, i) -> operation.apply(t._2, i)); } @Override public Iterator> slideBy(Function classifier) { return original.slideBy(e -> classifier.apply(e._2)).map(IntMultimap::of); } @Override public Iterator> sliding(int size) { return original.sliding(size).map(IntMultimap::of); } @Override public Iterator> sliding(int size, int step) { return original.sliding(size, step).map(IntMultimap::of); } @Override public Tuple2, ? extends IntMultimap> span(Predicate predicate) { return original.span(p -> predicate.test(p._2)).map(IntMultimap::of, IntMultimap::of); } public Spliterator spliterator() { class SpliteratorProxy implements Spliterator { private final Spliterator> spliterator; private SpliteratorProxy(Spliterator> spliterator) { this.spliterator = spliterator; } @Override public boolean tryAdvance(Consumer action) { return spliterator.tryAdvance(a -> action.accept(a._2)); } @Override public Spliterator trySplit() { return new SpliteratorProxy(spliterator.trySplit()); } @Override public long estimateSize() { return spliterator.estimateSize(); } @Override public int characteristics() { return spliterator.characteristics(); } @Override public Comparator getComparator() { if (hasCharacteristics(Spliterator.SORTED)) { return null; } throw new IllegalStateException(); } } return new SpliteratorProxy(original.spliterator()); } @Override public IntMultimap tail() { return IntMultimap.of(original.tail()); } @Override public Option> tailOption() { return original.tailOption().map(IntMultimap::of); } @Override public IntMultimap take(int n) { return unit(original.take(n)); } @Override public IntMultimap takeRight(int n) { return unit(original.takeRight(n)); } @Override public Traversable takeUntil(Predicate predicate) { return unit(original.takeUntil(p -> predicate.test(p._2))); } @Override public IntMultimap takeWhile(Predicate predicate) { return unit(original.takeWhile(p -> predicate.test(p._2))); } @Override public Tuple2, Seq> unzip(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip(unzipper).map(Stream::ofAll, Stream::ofAll); } @Override public Tuple3, Seq, Seq> unzip3(Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map(Stream::ofAll, Stream::ofAll, Stream::ofAll); } @Override public Seq> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public Seq zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWith(that, mapper)); } @Override public Seq> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return Stream.ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public Seq> zipWithIndex() { return zipWithIndex(Tuple::of); } @Override public Seq zipWithIndex(BiFunction mapper) { Objects.requireNonNull(mapper, "mapper is null"); return Stream.ofAll(iterator().zipWithIndex(mapper)); } } vavr-0.10.0/vavr/src/test/java/io/vavr/collection/IteratorTest.java000066400000000000000000000674521342074374400252550ustar00rootroot00000000000000/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/ * * Copyright 2014-2019 Vavr, http://vavr.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.control.Option; import org.assertj.core.api.Assertions; import org.assertj.core.api.IterableAssert; import org.assertj.core.api.ObjectAssert; import org.junit.Ignore; import org.junit.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Spliterator; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; import static io.vavr.collection.Iterator.*; public class IteratorTest extends AbstractTraversableTest { @Override protected IterableAssert assertThat(Iterable actual) { return new IterableAssert(actual) { @SuppressWarnings("unchecked") @Override public IterableAssert isEqualTo(Object expected) { if (actual instanceof Option) { final Option opt1 = ((Option) actual); final Option opt2 = (Option) expected; Assertions.assertThat(wrapIterator(opt1)).isEqualTo(wrapIterator(opt2)); return this; } else { final Iterable iterable = (Iterable) expected; Assertions.assertThat(List.ofAll(actual)).isEqualTo(List.ofAll(iterable)); return this; } } private Option wrapIterator(Option option) { return option.map(o -> (o instanceof Iterator) ? List.ofAll((Iterator) o) : o); } }; } @Override protected ObjectAssert assertThat(T actual) { return new ObjectAssert(actual) { @Override public ObjectAssert isEqualTo(Object expected) { if (actual instanceof Tuple2) { final Tuple2 t1 = ((Tuple2) actual).map(this::toList); final Tuple2 t2 = ((Tuple2) expected).map(this::toList); Assertions.assertThat((Object) t1).isEqualTo(t2); return this; } else if (actual instanceof Tuple3) { final Tuple3 t1 = ((Tuple3) actual).map(this::toList); final Tuple3 t2 = ((Tuple3) expected).map(this::toList); Assertions.assertThat((Object) t1).isEqualTo(t2); return this; } else { return super.isEqualTo(expected); } } private Tuple2 toList(Object o1, Object o2) { return Tuple.of(wrapIterator(o1), wrapIterator(o2)); } private Tuple3 toList(Object o1, Object o2, Object o3) { return Tuple.of(wrapIterator(o1), wrapIterator(o2), wrapIterator(o3)); } private Object wrapIterator(Object o) { return (o instanceof Iterator) ? List.ofAll((Iterator) o) : o; } }; } @Override protected Collector, ? extends Iterator> collector() { throw new UnsupportedOperationException(); } @Override protected Iterator empty() { return Iterator.empty(); } @Override protected Iterator of(T element) { return Iterator.of(element); } @SuppressWarnings("varargs") @SafeVarargs @Override protected final Iterator of(T... elements) { return Iterator.of(elements); } @Override protected Iterator ofAll(Iterable elements) { return Iterator.ofAll(elements); } @Override protected > Iterator ofJavaStream(java.util.stream.Stream javaStream) { return Iterator.ofAll(javaStream.iterator()); } @Override protected Iterator ofAll(boolean... elements) { return Iterator.ofAll(elements); } @Override protected Iterator ofAll(byte... elements) { return Iterator.ofAll(elements); } @Override protected Iterator ofAll(char... elements) { return Iterator.ofAll(elements); } @Override protected Iterator ofAll(double... elements) { return Iterator.ofAll(elements); } @Override protected Iterator ofAll(float... elements) { return Iterator.ofAll(elements); } @Override protected Iterator ofAll(int... elements) { return Iterator.ofAll(elements); } @Override protected Iterator ofAll(long... elements) { return Iterator.ofAll(elements); } @Override protected Iterator ofAll(short... elements) { return Iterator.ofAll(elements); } @Override protected Iterator tabulate(int n, Function f) { return Iterator.tabulate(n, f); } @Override protected Iterator fill(int n, Supplier s) { return Iterator.fill(n, s); } protected Iterator fill(int n, T element) { return Iterator.fill(n, element); } @Override protected boolean useIsEqualToInsteadOfIsSameAs() { return true; } @Override protected int getPeekNonNilPerformingAnAction() { return 3; } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyArgList() { of().next(); } // -- static narrow() @Test public void shouldNarrowIterator() { final Iterator doubles = of(1.0d); final Iterator numbers = narrow(doubles); final int actual = numbers.concat(Iterator.of(new BigDecimal("2.0"))).sum().intValue(); assertThat(actual).isEqualTo(3); } // -- static ofAll() @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyIterable() { ofAll(List.empty()).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyBoolean() { ofAll(new boolean[0]).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyByte() { ofAll(new byte[0]).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyChar() { ofAll(new char[0]).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyDouble() { ofAll(new double[0]).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyFloat() { ofAll(new float[0]).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyInt() { ofAll(new int[0]).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyLong() { ofAll(new long[0]).next(); } @Test(expected = NoSuchElementException.class) public void shouldFailOfEmptyShort() { ofAll(new short[0]).next(); } // -- static concat() @Test public void shouldConcatEmptyIterableIterable() { final Iterable> empty = List.empty(); assertThat(concat(empty)).isSameAs(Iterator.empty()); } @Test public void shouldConcatNonEmptyIterableIterable() { final Iterable> itIt = List.of(List.of(1, 2), List.of(3)); assertThat(concat(itIt)).isEqualTo(Iterator.of(1, 2, 3)); } @Test public void shouldConcatEmptyArrayIterable() { assertThat(concat()).isSameAs(Iterator.empty()); } @Test public void shouldConcatNonEmptyArrayIterable() { assertThat(concat(List.of(1, 2), List.of(3))).isEqualTo(Iterator.of(1, 2, 3)); } @Test public void shouldConcatNestedConcatIterators() { assertThat(concat(List.of(1, 2), List.of(3), concat(List.of(4, 5)))).isEqualTo(Iterator.of(1, 2, 3, 4, 5)); assertThat(concat(concat(List.of(4, 5)), List.of(1, 2), List.of(3))).isEqualTo(Iterator.of(4, 5, 1, 2, 3)); } @Test public void shouldConcatToConcatIterator() { assertThat(concat(List.of(1, 2)).concat(List.of(3).iterator())).isEqualTo(Iterator.of(1, 2, 3)); } // -- fill(int, Supplier) @Test public void shouldReturnManyAfterFillWithConstantSupplier() { assertThat(fill(17, () -> 7)) .hasSize(17); } // -- fill(int, T) @Test public void shouldReturnEmptyAfterFillWithZeroCount() { assertThat(fill(0, 7)).isEqualTo(empty()); } @Test public void shouldReturnEmptyAfterFillWithNegativeCount() { assertThat(fill(-1, 7)).isEqualTo(empty()); } @Test public void shouldReturnManyAfterFillWithConstant() { assertThat(fill(17, 7)) .hasSize(17); } // -- concat @Test public void shouldConcatThisNonEmptyWithEmpty() { final Iterator it = Iterator.of(1); assertThat(it.concat(Iterator. empty())).isSameAs(it); } @Test public void shouldConcatThisEmptyWithNonEmpty() { final Iterator it = Iterator.of(1); assertThat(Iterator. empty().concat(it)).isSameAs(it); } @Test public void shouldConcatThisNonEmptyWithNonEmpty() { assertThat(Iterator.of(1).concat(Iterator.of(2))).isEqualTo(Iterator.of(1, 2)); } // -- transform @Test public void shouldTransform() { final Iterator it = Iterator.of(1, 2).transform(ii -> ii.drop(1)); assertThat(it).isEqualTo(Iterator.of(2)); } // -- static from(int) @Test public void shouldGenerateIntStream() { assertThat(from(-1).take(3)).isEqualTo(Iterator.of(-1, 0, 1)); } @Test public void shouldGenerateOverflowingIntStream() { //noinspection NumericOverflow assertThat(from(Integer.MAX_VALUE).take(2)) .isEqualTo(Iterator.of(Integer.MAX_VALUE, Integer.MAX_VALUE + 1)); } // -- static from(int, int) @Test public void shouldGenerateIntStreamWithStep() { assertThat(from(-1, 6).take(3)).isEqualTo(Iterator.of(-1, 5, 11)); } @Test public void shouldGenerateOverflowingIntStreamWithStep() { //noinspection NumericOverflow assertThat(from(Integer.MAX_VALUE, 2).take(2)) .isEqualTo(Iterator.of(Integer.MAX_VALUE, Integer.MAX_VALUE + 2)); } // -- static from(long) @Test public void shouldGenerateLongStream() { assertThat(from(-1L).take(3)).isEqualTo(Iterator.of(-1L, 0L, 1L)); } @Test public void shouldGenerateOverflowingLongStream() { //noinspection NumericOverflow assertThat(from(Long.MAX_VALUE).take(2)).isEqualTo(Iterator.of(Long.MAX_VALUE, Long.MAX_VALUE + 1)); } // -- static from(long, long) @Test public void shouldGenerateLongStreamWithStep() { assertThat(from(-1L, 5L).take(3)).isEqualTo(Iterator.of(-1L, 4L, 9L)); } @Test public void shouldGenerateOverflowingLongStreamWithStep() { //noinspection NumericOverflow assertThat(from(Long.MAX_VALUE, 2).take(2)).isEqualTo(Iterator.of(Long.MAX_VALUE, Long.MAX_VALUE + 2)); } // -- static continually(Supplier) @Test public void shouldGenerateInfiniteStreamBasedOnSupplier() { assertThat(continually(() -> 1).take(13).reduce((i, j) -> i + j)).isEqualTo(13); } @Test public void shouldGenerateInfiniteStreamBasedOnConstant() { assertThat(continually(1).take(13).reduce((i, j) -> i + j)).isEqualTo(13); } // -- static iterate(T, Function) @Test public void shouldGenerateInfiniteStreamBasedOnSupplierWithAccessToPreviousValue() { assertThat(iterate(2, (i) -> i + 2).take(3).reduce((i, j) -> i + j)).isEqualTo(12); } @Test public void shouldNotCallSupplierUntilNecessary() { assertThat(iterate(2, (i) -> { throw new RuntimeException(); }).head()).isEqualTo(2); } // -- static iterate(Supplier

* See Object.equals(Object). * * @param o An object * @return true, if this equals o, false otherwise */ @Override boolean equals(Object o); /** * Clarifies that values have a proper hashCode() method implemented. *