├── .gitignore ├── LICENSE ├── README.md ├── license_header.txt ├── nbactions.xml ├── pom.xml └── src └── main └── java └── com └── speedment ├── annotation └── Api.java ├── stream └── MapStream.java └── util ├── CollectorUtil.java └── StaticClassUtil.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.sonar 3 | /.idea 4 | /nb-configuration.xml 5 | /sonar-project.properties 6 | *~ 7 | /nbproject/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MapStream 2 | MapStream is a convenient extension to the Java 8 Stream API that let you stream over Key-Value pairs. The project is a fork of the [Speedment MapStream component](http://github.com/speedment/speedment/) in case you want to use it as a stand-alone. 3 | 4 | ## Example Usage 5 | ```java 6 | Map numberOfCats = new HashMap<>(); 7 | 8 | numberOfCats.put("Anne", 3); 9 | numberOfCats.put("Berty", 1); 10 | numberOfCats.put("Cecilia", 1); 11 | numberOfCats.put("Denny", 0); 12 | numberOfCats.put("Erica", 0); 13 | numberOfCats.put("Fiona", 2); 14 | 15 | System.out.println( 16 | MapStream.of(numberOfCats) 17 | .filterValue(v -> v > 0) 18 | .sortedByValue(Integer::compareTo) 19 | .mapKey(k -> k + " has ") 20 | .mapValue(v -> v + (v == 1 ? " cat." : " cats.")) 21 | .map((k, v) -> k + v) 22 | .collect(Collectors.joining("\n")) 23 | ); 24 | ``` 25 | Output: 26 | ``` 27 | Cecilia has 1 cat. 28 | Berty has 1 cat. 29 | Fiona has 2 cats. 30 | Anne has 3 cats. 31 | ``` 32 | 33 | If you want to use static imports, replace `Collectors.joining("\n")` with `joining("\n")`. 34 | 35 | ## Download 36 | The easiest way to include MapStream in your projects is to add the following dependency to your `pom.xml`-file: 37 | ```xml 38 | 39 | com.github.pyknic 40 | map-stream 41 | 2.3.1 42 | 43 | ``` 44 | 45 | ## License 46 | Licensed under the Apache License, Version 2.0 (the "License"); 47 | you may not use this project except in compliance with the License. 48 | You may obtain a copy of the License at 49 | 50 | [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) 51 | 52 | Unless required by applicable law or agreed to in writing, software 53 | distributed under the License is distributed on an "AS IS" BASIS, 54 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 55 | See the License for the specific language governing permissions and 56 | limitations under the License. 57 | 58 | Attribution should be done to [Speedment, Inc.](http://speedment.org) 59 | -------------------------------------------------------------------------------- /license_header.txt: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2006-${currentYear}, Speedment, Inc. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); You may not 5 | use this file except in compliance with the License. You may obtain a copy of 6 | the License at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | License for the specific language governing permissions and limitations under 14 | the License. 15 | 16 | 17 | -------------------------------------------------------------------------------- /nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CUSTOM-Deploy Snapshot 5 | Deploy Snapshot 6 | 7 | clean 8 | deploy 9 | 10 | 11 | 12 | CUSTOM-Deploy Release 13 | Deploy Release 14 | 15 | clean 16 | deploy 17 | -P 18 | release 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 4.0.0 22 | com.github.pyknic 23 | map-stream 24 | 2.3.2-SNAPSHOT 25 | jar 26 | 27 | MapStream 28 | 29 | A wrapper class for creating Key-Value Streams using the standard 30 | Java 8 API. 31 | 32 | https://www.github.com/Pyknic/MapStream/ 33 | 34 | 35 | UTF-8 36 | 1.8 37 | 1.8 38 | 39 | 40 | 41 | 42 | Apache License, Version 2.0 43 | http://www.apache.org/licenses/LICENSE-2.0 44 | repo 45 | 46 | 47 | 48 | 49 | 50 | emifor 51 | Emil Forslund 52 | emil@speedment.com 53 | Speedment 54 | http://www.speedment.org 55 | 56 | 57 | permin 58 | Per Ake Minborg 59 | minborg@speedment.com 60 | Speedment 61 | http://www.speedment.org 62 | 63 | 64 | 65 | 66 | scm:git:git://github.com/pyknic/mapstream.git 67 | scm:git:git@github.com:pyknic/mapstream.git 68 | git@github.com:pyknic/mapstream.git 69 | 70 | 71 | 72 | Github 73 | https://github.com/pyknic/mapstream/issues 74 | 75 | 76 | 77 | 78 | ossrh 79 | Sonatype Nexus snapshot repository 80 | https://oss.sonatype.org/content/repositories/snapshots 81 | 82 | 83 | ossrh 84 | Sonatype Nexus release staging repository 85 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-compiler-plugin 94 | 3.3 95 | 96 | -Xlint:all 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | ossrh 107 | 108 | 109 | 110 | com.mycila 111 | license-maven-plugin 112 | 2.11 113 | 114 |
license_header.txt
115 | 116 | 2016 117 | 118 | 119 | **/README 120 | **/LICENSE 121 | **/nbactions.xml 122 | **/nb-configuration.xml 123 | src/test/resources/** 124 | src/main/resources/** 125 | 126 |
127 | 128 | 129 | 130 | check 131 | 132 | 133 | 134 |
135 | 136 | org.apache.maven.plugins 137 | maven-source-plugin 138 | 3.0.0 139 | 140 | 141 | attach-sources 142 | 143 | jar-no-fork 144 | 145 | 146 | 147 | 148 | 149 | org.apache.maven.plugins 150 | maven-javadoc-plugin 151 | 2.10.3 152 | 153 | 154 | attach-javadocs 155 | 156 | jar 157 | 158 | 159 | 160 | 161 | true 162 | com.speedment.internal.* 163 | 164 | 165 | 166 | org.apache.maven.plugins 167 | maven-gpg-plugin 168 | 1.6 169 | 170 | 171 | sign-artifacts 172 | verify 173 | 174 | sign 175 | 176 | 177 | 178 | 179 | true 180 | ${gpg.keyname} 181 | ${gpg.passphrase} 182 | ${gpg.executable} 183 | 184 | 185 | 186 | org.sonatype.plugins 187 | nexus-staging-maven-plugin 188 | 1.6.3 189 | true 190 | 191 | 192 | default-deploy 193 | deploy 194 | 195 | deploy 196 | 197 | 198 | 199 | 200 | ossrh 201 | https://oss.sonatype.org/ 202 | true 203 | 204 | 205 |
206 |
207 |
208 |
209 |
-------------------------------------------------------------------------------- /src/main/java/com/speedment/annotation/Api.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2006-2016, Speedment, Inc. All Rights Reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); You may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | package com.speedment.annotation; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Marks a Method, Type or Constructor as an API. An API marked entity with a 26 | * certain API version will remain "Compatible" across new software releases 27 | * indefinitely , for that particular API version. 28 | *

29 | * "Compatible" is defined as follows: 30 | *

31 | * Method: Its signature (i.e. name and parameters), and return type will 32 | * remain. 33 | *

34 | * Interface: Its name and all its declared methods with its return type and 35 | * signature and static fields will remain. New methods and static field might 36 | * be added. 37 | *

38 | * Enum: Its elements will remain and their individual order will remain. New 39 | * elements might be added. 40 | * 41 | * @author pemi 42 | */ 43 | @Api(version = "2.2", snapshot = false) 44 | @Retention(value = RetentionPolicy.RUNTIME) 45 | @Target({ElementType.METHOD, ElementType.TYPE, ElementType.CONSTRUCTOR}) 46 | public @interface Api { 47 | 48 | /** 49 | * Returns the current API version. 50 | * 51 | * @return the current API version. 52 | */ 53 | String version(); 54 | 55 | /** 56 | * Returns if this API version is a snapshot, i.e. it is not yet "frozen" 57 | * and may change within the given API version. 58 | * 59 | * @return true if this API version is a snapshot, false otherwise. 60 | */ 61 | boolean snapshot() default false; 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/speedment/stream/MapStream.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2006-2016, Speedment, Inc. All Rights Reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); You may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | package com.speedment.stream; 18 | 19 | import com.speedment.annotation.Api; 20 | import com.speedment.util.CollectorUtil; 21 | import java.util.AbstractMap; 22 | import static java.util.Collections.newSetFromMap; 23 | import java.util.Comparator; 24 | import java.util.Iterator; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.Optional; 28 | import java.util.Set; 29 | import java.util.SortedMap; 30 | import java.util.Spliterator; 31 | import java.util.TreeMap; 32 | import java.util.concurrent.ConcurrentHashMap; 33 | import java.util.concurrent.ConcurrentNavigableMap; 34 | import java.util.concurrent.ConcurrentSkipListMap; 35 | import java.util.function.BiConsumer; 36 | import java.util.function.BiFunction; 37 | import java.util.function.BiPredicate; 38 | import java.util.function.BinaryOperator; 39 | import java.util.function.Consumer; 40 | import java.util.function.Function; 41 | import java.util.function.IntFunction; 42 | import java.util.function.Predicate; 43 | import java.util.function.Supplier; 44 | import java.util.function.ToDoubleBiFunction; 45 | import java.util.function.ToDoubleFunction; 46 | import java.util.function.ToIntBiFunction; 47 | import java.util.function.ToIntFunction; 48 | import java.util.function.ToLongBiFunction; 49 | import java.util.function.ToLongFunction; 50 | import java.util.stream.Collector; 51 | import java.util.stream.Collectors; 52 | import java.util.stream.DoubleStream; 53 | import java.util.stream.IntStream; 54 | import java.util.stream.LongStream; 55 | import java.util.stream.Stream; 56 | 57 | /** 58 | * A java {@code Stream} wrapper that stream over Key-Value pairs. With this 59 | * wrapper you get access to additional operators for working with two valued 60 | * collections. 61 | * 62 | * @author Emil Forslund 63 | * @param the key type 64 | * @param the value type 65 | */ 66 | @Api(version = "2.2") 67 | public final class MapStream implements Stream> { 68 | 69 | private Stream> inner; 70 | 71 | /** 72 | * Constructs a new {@code MapStream} from a single entry. 73 | * 74 | * @param key type 75 | * @param value type 76 | * @param entry the entry 77 | * @return created {@code MapStream} 78 | */ 79 | public static MapStream of(Map.Entry entry) { 80 | return new MapStream<>(Stream.of(entry)); 81 | } 82 | 83 | /** 84 | * Constructs a new {@code MapStream} from an array of entries. 85 | * 86 | * @param key type 87 | * @param value type 88 | * @param entries elements to stream over 89 | * @return created {@code MapStream} 90 | */ 91 | @SafeVarargs // Creating a Stream of an array is safe. 92 | @SuppressWarnings({"unchecked", "varargs"}) 93 | public static MapStream of(Map.Entry... entries) { 94 | return new MapStream<>(Stream.of(entries)); 95 | } 96 | 97 | /** 98 | * Constructs a new {@code MapStream} from a map of key-value pairs. The map 99 | * will not be affected. 100 | *

101 | * This is equivalent to writing: 102 | * {@code MapStream.of(map.entrySet().stream());} 103 | * 104 | * @param key type 105 | * @param value type 106 | * @param map elements to stream over 107 | * @return created {@code MapStream} 108 | */ 109 | public static MapStream of(Map map) { 110 | return new MapStream<>(map.entrySet().stream()); 111 | } 112 | 113 | /** 114 | * Constructs a new {@code MapStream} by wrapping a key-value pair stream. 115 | * The provided stream will be wrapped in this stream. After this method is 116 | * called, no more changes should be done to the stream! 117 | * 118 | * @param key type 119 | * @param value type 120 | * @param stream stream to wrap 121 | * @return created {@code MapStream} 122 | */ 123 | public static MapStream of(Stream> stream) { 124 | return new MapStream<>(stream); 125 | } 126 | 127 | /** 128 | * Constructs a new {@code MapStream} by wrapping a key-stream and 129 | * calculating the corresponding values using the supplied function. 130 | * 131 | * @param key type 132 | * @param value type 133 | * @param keys stream of keys to wrap 134 | * @param valueFromKey method for calculating values from keys 135 | * @return created {@code MapStream} 136 | */ 137 | public static MapStream fromKeys(Stream keys, Function valueFromKey) { 138 | return new MapStream<>(keys.map(k -> new AbstractMap.SimpleEntry<>(k, valueFromKey.apply(k)))); 139 | } 140 | 141 | /** 142 | * Constructs a new {@code MapStream} by wrapping a value-stream and 143 | * calculating the corresponding keys using the supplied function. 144 | * 145 | * @param key type 146 | * @param value type 147 | * @param values stream of values to wrap 148 | * @param keyFromValue method for calculating keys from values 149 | * @return created {@code MapStream} 150 | */ 151 | public static MapStream fromValues(Stream values, Function keyFromValue) { 152 | return new MapStream<>(values.map(v -> new AbstractMap.SimpleEntry<>(keyFromValue.apply(v), v))); 153 | } 154 | 155 | /** 156 | * Constructs a new {@code MapStream} by wrapping a stream of objects and 157 | * calculating both keys and values using the supplied functions. 158 | * 159 | * @param original stream type 160 | * @param key type 161 | * @param value type 162 | * @param stream original stream 163 | * @param keyMapper method for calculating keys 164 | * @param valueMapper method for calculating values 165 | * @return created {@code MapStream} 166 | */ 167 | public static MapStream fromStream(Stream stream, Function keyMapper, Function valueMapper) { 168 | return new MapStream<>(stream.map( 169 | e -> new AbstractMap.SimpleEntry<>( 170 | keyMapper.apply(e), 171 | valueMapper.apply(e) 172 | ) 173 | )); 174 | } 175 | 176 | /** 177 | * Constructs an empty {@code MapStream}. 178 | * 179 | * @param key type 180 | * @param value type 181 | * @return an empty {@code MapStream} 182 | */ 183 | public static MapStream empty() { 184 | return new MapStream<>(Stream.empty()); 185 | } 186 | 187 | /** 188 | * Produces a new MapStream by flipping the specified one so that keys 189 | * become values and values become keys. This will consume the supplied 190 | * stream. 191 | * 192 | * @param original key type 193 | * @param original value type 194 | * @param original original MapStream 195 | * @return new MapStream with keys and values flipped 196 | */ 197 | public static MapStream flip(MapStream original) { 198 | return MapStream.fromStream( 199 | original, 200 | Map.Entry::getValue, 201 | Map.Entry::getKey 202 | ); 203 | } 204 | 205 | /** 206 | * Returns a stream consisting of the elements of this stream that match 207 | * the given predicate. 208 | *

209 | * This is an intermediate operation. 210 | * 211 | * @param predicate a non-interfering, stateless predicate to apply to each 212 | * element to determine if it should be included 213 | * @return the new stream 214 | */ 215 | @Override 216 | public MapStream filter(Predicate> predicate) { 217 | inner = inner.filter(predicate); 218 | return this; 219 | } 220 | 221 | /** 222 | * Returns a stream consisting of the elements of this stream that match 223 | * the given predicate. 224 | *

225 | * This is an intermediate operation. 226 | * 227 | * @param predicate a non-interfering, stateless predicate to apply to each 228 | * key-value pair to determine if it should be included 229 | * @return the new stream 230 | */ 231 | public MapStream filter(BiPredicate predicate) { 232 | return filter(e -> predicate.test(e.getKey(), e.getValue())); 233 | } 234 | 235 | /** 236 | * Returns a stream consisting of the elements of this stream where the key 237 | * component matches the given predicate. 238 | *

239 | * This is an intermediate operation. 240 | * 241 | * @param predicate a non-interfering, stateless predicate to apply to each 242 | * key to determine if the entry should be included 243 | * @return the new stream 244 | */ 245 | public MapStream filterKey(Predicate predicate) { 246 | return filter(e -> predicate.test(e.getKey())); 247 | } 248 | 249 | /** 250 | * Returns a stream consisting of the elements of this stream where the 251 | * value component matches the given predicate. 252 | *

253 | * This is an intermediate operation. 254 | * 255 | * @param predicate a non-interfering, stateless predicate to apply to each 256 | * value to determine if the entry should be included 257 | * @return the new stream 258 | */ 259 | public MapStream filterValue(Predicate predicate) { 260 | return filter(e -> predicate.test(e.getValue())); 261 | } 262 | 263 | /** 264 | * Returns a stream consisting of the results of applying the given 265 | * function to the elements of this stream. 266 | *

267 | * This is an intermediate operation. 268 | * 269 | * @param the element type of the new stream 270 | * @param mapper a non-interfering, stateless function to apply to each 271 | * element 272 | * @return the new stream 273 | */ 274 | @Override 275 | public Stream map(Function, ? extends R> mapper) { 276 | return inner.map(mapper); 277 | } 278 | 279 | /** 280 | * Returns a stream consisting of the results of applying the given 281 | * function to the elements of this stream. 282 | *

283 | * This is an intermediate operation. 284 | * 285 | * @param the element type of the new stream 286 | * @param mapper a non-interfering, stateless function to apply to each 287 | * key-value pair 288 | * @return the new stream 289 | */ 290 | public Stream map(BiFunction mapper) { 291 | return map(e -> mapper.apply(e.getKey(), e.getValue())); 292 | } 293 | 294 | /** 295 | * Returns a stream consisting of the results of applying the given 296 | * function to the key-component of this stream. 297 | *

298 | * This is an intermediate operation. 299 | * 300 | * @param the element type of the new stream 301 | * @param mapper a non-interfering, stateless function to apply to each 302 | * key in the stream 303 | * @return the new stream 304 | */ 305 | public MapStream mapKey(BiFunction mapper) { 306 | return new MapStream<>(inner.map(e 307 | -> new AbstractMap.SimpleEntry<>( 308 | mapper.apply(e.getKey(), e.getValue()), 309 | e.getValue() 310 | ) 311 | )); 312 | } 313 | 314 | /** 315 | * Returns a stream consisting of the results of applying the given 316 | * function to the key-component of this stream. 317 | *

318 | * This is an intermediate operation. 319 | * 320 | * @param the element type of the new stream 321 | * @param mapper a non-interfering, stateless function to apply to each 322 | * key in the stream 323 | * @return the new stream 324 | */ 325 | public MapStream mapKey(Function mapper) { 326 | return new MapStream<>(inner.map(e 327 | -> new AbstractMap.SimpleEntry<>( 328 | mapper.apply(e.getKey()), 329 | e.getValue() 330 | ) 331 | )); 332 | } 333 | 334 | /** 335 | * Returns a stream consisting of the results of applying the given 336 | * function to the value-component of this stream. 337 | *

338 | * This is an intermediate operation. 339 | * 340 | * @param the element type of the new stream 341 | * @param mapper a non-interfering, stateless function to apply to each 342 | * value in the stream 343 | * @return the new stream 344 | */ 345 | public MapStream mapValue(BiFunction mapper) { 346 | return new MapStream<>(inner.map(e 347 | -> new AbstractMap.SimpleEntry<>( 348 | e.getKey(), 349 | mapper.apply(e.getKey(), e.getValue()) 350 | ) 351 | )); 352 | } 353 | 354 | /** 355 | * Returns a stream consisting of the results of applying the given 356 | * function to the value-component of this stream. 357 | *

358 | * This is an intermediate operation. 359 | * 360 | * @param the element type of the new stream 361 | * @param mapper a non-interfering, stateless function to apply to each 362 | * value in the stream 363 | * @return the new stream 364 | */ 365 | public MapStream mapValue(Function mapper) { 366 | return new MapStream<>(inner.map(e 367 | -> new AbstractMap.SimpleEntry<>( 368 | e.getKey(), 369 | mapper.apply(e.getValue()) 370 | ) 371 | )); 372 | } 373 | 374 | /** 375 | * Returns an {@code IntStream} consisting of the results of applying the 376 | * given function to the elements of this stream. 377 | *

378 | * This is an intermediate operation. 379 | * 380 | * @param mapper a non-interfering, stateless function to apply to each 381 | * element 382 | * @return the new stream 383 | */ 384 | @Override 385 | public IntStream mapToInt(ToIntFunction> mapper) { 386 | return inner.mapToInt(mapper); 387 | } 388 | 389 | /** 390 | * Returns an {@code IntStream} consisting of the results of applying the 391 | * given function to the elements of this stream. 392 | *

393 | * This is an intermediate operation. 394 | * 395 | * @param mapper a non-interfering, stateless function to apply to each 396 | * element 397 | * @return the new stream 398 | */ 399 | public IntStream mapToInt(ToIntBiFunction mapper) { 400 | return inner.mapToInt(e -> mapper.applyAsInt(e.getKey(), e.getValue())); 401 | } 402 | 403 | /** 404 | * Returns a {@code LongStream} consisting of the results of applying the 405 | * given function to the elements of this stream. 406 | *

407 | * This is an intermediate operation. 408 | * 409 | * @param mapper a non-interfering, stateless function to apply to each 410 | * element 411 | * @return the new stream 412 | */ 413 | @Override 414 | public LongStream mapToLong(ToLongFunction> mapper) { 415 | return inner.mapToLong(mapper); 416 | } 417 | 418 | /** 419 | * Returns a {@code LongStream} consisting of the results of applying the 420 | * given function to the elements of this stream. 421 | *

422 | * This is an intermediate operation. 423 | * 424 | * @param mapper a non-interfering, stateless function to apply to each 425 | * element 426 | * @return the new stream 427 | */ 428 | public LongStream mapToLong(ToLongBiFunction mapper) { 429 | return inner.mapToLong(e -> mapper.applyAsLong(e.getKey(), e.getValue())); 430 | } 431 | 432 | /** 433 | * Returns a {@code DoubleStream} consisting of the results of applying the 434 | * given function to the elements of this stream. 435 | *

436 | * This is an intermediate operation. 437 | * 438 | * @param mapper a non-interfering, stateless function to apply to each 439 | * element 440 | * @return the new stream 441 | */ 442 | @Override 443 | public DoubleStream mapToDouble(ToDoubleFunction> mapper) { 444 | return inner.mapToDouble(mapper); 445 | } 446 | 447 | /** 448 | * Returns a {@code DoubleStream} consisting of the results of applying the 449 | * given function to the elements of this stream. 450 | *

451 | * This is an intermediate operation. 452 | * 453 | * @param mapper a non-interfering, stateless function to apply to each 454 | * element 455 | * @return the new stream 456 | */ 457 | public DoubleStream mapToDouble(ToDoubleBiFunction mapper) { 458 | return inner.mapToDouble(e -> mapper.applyAsDouble(e.getKey(), e.getValue())); 459 | } 460 | 461 | /** 462 | * Returns a stream consisting of the results of replacing each element of 463 | * this stream with the contents of a mapped stream produced by applying 464 | * the provided mapping function to each element. Each mapped stream is 465 | * {@link java.util.stream.BaseStream#close() closed} after its contents 466 | * have been placed into this stream. (If a mapped stream is {@code null} 467 | * an empty stream is used, instead.) 468 | *

469 | * This is an intermediate operation. 470 | * 471 | *

472 | * The {@code flatMap()} operation has the effect of applying a one-to-many 473 | * transformation to the elements of the stream, and then flattening the 474 | * resulting elements into a new stream. 475 | *

476 | * Examples. 477 | * 478 | *

If {@code orders} is a stream of purchase orders, and each purchase 479 | * order contains a collection of line items, then the following produces a 480 | * stream containing all the line items in all the orders: 481 | *

{@code
 482 |      *     orders.flatMap(order -> order.getLineItems().stream())...
 483 |      * }
484 | *

485 | * If {@code path} is the path to a file, then the following produces a 486 | * stream of the {@code words} contained in that file: 487 | *

{@code
 488 |      *     Stream lines = Files.lines(path, StandardCharsets.UTF_8);
 489 |      *     Stream words = lines.flatMap(line -> Stream.of(line.split(" +")));
 490 |      * }
491 | * The {@code mapper} function passed to {@code flatMap} splits a line, 492 | * using a simple regular expression, into an array of words, and then 493 | * creates a stream of words from that array. 494 | * 495 | * @param the element type of the new stream 496 | * @param mapper a non-interfering, stateless function to apply to each 497 | * element which produces a stream of new elements 498 | * @return the new stream 499 | */ 500 | @Override 501 | public Stream flatMap(Function, ? extends Stream> mapper) { 502 | return inner.flatMap(mapper); 503 | } 504 | 505 | /** 506 | * Returns a stream consisting of the results of replacing each element of 507 | * this stream with the contents of a mapped stream produced by applying 508 | * the provided mapping function to each element. Each mapped stream is 509 | * {@link java.util.stream.BaseStream#close() closed} after its contents 510 | * have been placed into this stream. (If a mapped stream is {@code null} 511 | * an empty stream is used, instead.) 512 | *

513 | * This is an intermediate operation. 514 | * 515 | *

516 | * The {@code flatMap()} operation has the effect of applying a one-to-many 517 | * transformation to the elements of the stream, and then flattening the 518 | * resulting elements into a new stream. 519 | *

520 | * Examples. 521 | * 522 | *

If {@code orders} is a stream of purchase orders, and each purchase 523 | * order contains a collection of line items, then the following produces a 524 | * stream containing all the line items in all the orders: 525 | *

{@code
 526 |      *     orders.flatMap(order -> order.getLineItems().stream())...
 527 |      * }
528 | *

529 | * If {@code path} is the path to a file, then the following produces a 530 | * stream of the {@code words} contained in that file: 531 | *

{@code
 532 |      *     Stream lines = Files.lines(path, StandardCharsets.UTF_8);
 533 |      *     Stream words = lines.flatMap(line -> Stream.of(line.split(" +")));
 534 |      * }
535 | * The {@code mapper} function passed to {@code flatMap} splits a line, 536 | * using a simple regular expression, into an array of words, and then 537 | * creates a stream of words from that array. 538 | * 539 | * @param the element type of the new stream 540 | * @param mapper a non-interfering, stateless function to apply to each 541 | * element which produces a stream of new elements 542 | * @return the new stream 543 | */ 544 | public Stream flatMap(BiFunction> mapper) { 545 | return inner.flatMap(e -> mapper.apply(e.getKey(), e.getValue())); 546 | } 547 | 548 | /** 549 | * Returns a stream where the key-component of this stream has been replaced 550 | * by the result of applying the specified mapping function to the entry. 551 | * Each mapped stream is {@link java.util.stream.BaseStream#close() closed} 552 | * after its contents have been placed into this stream. (If a mapped stream 553 | * is {@code null} an empty stream is used, instead.) 554 | *

555 | * This is an intermediate operation. 556 | * 557 | *

558 | * The {@code flatMap()} operation has the effect of applying a one-to-many 559 | * transformation to the elements of the stream, and then flattening the 560 | * resulting elements into a new stream. 561 | * 562 | * @param the element type of the new stream 563 | * @param mapper a non-interfering, stateless function to apply to each 564 | * key-value pair which produces a stream of new keys 565 | * @return the new stream 566 | */ 567 | public MapStream flatMapKey(BiFunction> mapper) { 568 | return new MapStream<>(inner.flatMap(e 569 | -> mapper.apply(e.getKey(), e.getValue()) 570 | .map(k 571 | -> new AbstractMap.SimpleEntry<>( 572 | k, 573 | e.getValue() 574 | ) 575 | ) 576 | )); 577 | } 578 | 579 | /** 580 | * Returns a stream where the key-component of this stream has been replaced 581 | * by the result of applying the specified mapping function to the entry. 582 | * Each mapped stream is {@link java.util.stream.BaseStream#close() closed} 583 | * after its contents have been placed into this stream. (If a mapped stream 584 | * is {@code null} an empty stream is used, instead.) 585 | *

586 | * This is an intermediate operation. 587 | * 588 | *

589 | * The {@code flatMap()} operation has the effect of applying a one-to-many 590 | * transformation to the elements of the stream, and then flattening the 591 | * resulting elements into a new stream. 592 | * 593 | * @param the element type of the new stream 594 | * @param mapper a non-interfering, stateless function to apply to each 595 | * key-value pair which produces a stream of new keys 596 | * @return the new stream 597 | */ 598 | public MapStream flatMapKey(Function> mapper) { 599 | return new MapStream<>(inner.flatMap(e 600 | -> mapper.apply(e.getKey()) 601 | .map(k 602 | -> new AbstractMap.SimpleEntry<>( 603 | k, 604 | e.getValue() 605 | ) 606 | ) 607 | )); 608 | } 609 | 610 | /** 611 | * Returns a stream where the value-component of this stream has been 612 | * replaced by the result of applying the specified mapping function to the 613 | * entry. Each mapped stream is 614 | * {@link java.util.stream.BaseStream#close() closed} after its contents 615 | * have been placed into this stream. (If a mapped stream is {@code null} an 616 | * empty stream is used, instead.) 617 | *

618 | * This is an intermediate operation. 619 | * 620 | *

621 | * The {@code flatMap()} operation has the effect of applying a one-to-many 622 | * transformation to the elements of the stream, and then flattening the 623 | * resulting elements into a new stream. 624 | * 625 | * @param the element type of the new stream 626 | * @param mapper a non-interfering, stateless function to apply to each 627 | * key-value pair which produces a stream of new values 628 | * @return the new stream 629 | */ 630 | public MapStream flatMapValue(BiFunction> mapper) { 631 | return new MapStream<>(inner.flatMap(e 632 | -> mapper.apply(e.getKey(), e.getValue()) 633 | .map(v 634 | -> new AbstractMap.SimpleEntry<>( 635 | e.getKey(), 636 | v 637 | ) 638 | ) 639 | )); 640 | } 641 | 642 | /** 643 | * Returns a stream where the value-component of this stream has been 644 | * replaced by the result of applying the specified mapping function to the 645 | * entry. Each mapped stream is 646 | * {@link java.util.stream.BaseStream#close() closed} after its contents 647 | * have been placed into this stream. (If a mapped stream is {@code null} an 648 | * empty stream is used, instead.) 649 | *

650 | * This is an intermediate operation. 651 | * 652 | *

653 | * The {@code flatMap()} operation has the effect of applying a one-to-many 654 | * transformation to the elements of the stream, and then flattening the 655 | * resulting elements into a new stream. 656 | * 657 | * @param the element type of the new stream 658 | * @param mapper a non-interfering, stateless function to apply to each 659 | * key-value pair which produces a stream of new values 660 | * @return the new stream 661 | */ 662 | public MapStream flatMapValue(Function> mapper) { 663 | return new MapStream<>(inner.flatMap(e 664 | -> mapper.apply(e.getValue()) 665 | .map(v 666 | -> new AbstractMap.SimpleEntry<>( 667 | e.getKey(), 668 | v 669 | ) 670 | ) 671 | )); 672 | } 673 | 674 | /** 675 | * Returns an {@code IntStream} consisting of the results of replacing each 676 | * element of this stream with the contents of a mapped stream produced by 677 | * applying the provided mapping function to each element. Each mapped 678 | * stream is {@link java.util.stream.BaseStream#close() closed} after its 679 | * contents have been placed into this stream. (If a mapped stream is 680 | * {@code null} an empty stream is used, instead.) 681 | *

682 | * This is an intermediate operation. 683 | * 684 | * @param mapper a non-interfering, stateless function to apply to each 685 | * element which produces a stream of new elements 686 | * @return the new stream 687 | * 688 | * @see #flatMap(Function) 689 | */ 690 | @Override 691 | public IntStream flatMapToInt(Function, ? extends IntStream> mapper) { 692 | return inner.flatMapToInt(mapper); 693 | } 694 | 695 | /** 696 | * Returns an {@code IntStream} consisting of the results of replacing each 697 | * key-value pair of this stream with the contents of a mapped stream 698 | * produced by applying the provided mapping function to each element. Each 699 | * mapped stream is {@link java.util.stream.BaseStream#close() closed} after 700 | * its contents have been placed into this stream. (If a mapped stream is 701 | * {@code null} an empty stream is used, instead.) 702 | *

703 | * This is an intermediate operation. 704 | * 705 | * @param mapper a non-interfering, stateless function to apply to each 706 | * key-value pair which produces a stream of new elements 707 | * @return the new stream 708 | * 709 | * @see #flatMap(Function) 710 | */ 711 | public IntStream flatMapToInt(BiFunction mapper) { 712 | return inner.flatMapToInt(e -> mapper.apply(e.getKey(), e.getValue())); 713 | } 714 | 715 | /** 716 | * Returns an {@code LongStream} consisting of the results of replacing each 717 | * element of this stream with the contents of a mapped stream produced by 718 | * applying the provided mapping function to each element. Each mapped 719 | * stream is {@link java.util.stream.BaseStream#close() closed} after its 720 | * contents have been placed into this stream. (If a mapped stream is 721 | * {@code null} an empty stream is used, instead.) 722 | *

723 | * This is an intermediate operation. 724 | * 725 | * @param mapper a non-interfering, stateless function to apply to each 726 | * element which produces a stream of new elements 727 | * @return the new stream 728 | * 729 | * @see #flatMap(Function) 730 | */ 731 | @Override 732 | public LongStream flatMapToLong(Function, ? extends LongStream> mapper) { 733 | return inner.flatMapToLong(mapper); 734 | } 735 | 736 | /** 737 | * Returns an {@code LongStream} consisting of the results of replacing each 738 | * key-value pair of this stream with the contents of a mapped stream 739 | * produced by applying the provided mapping function to each element. Each 740 | * mapped stream is {@link java.util.stream.BaseStream#close() closed} after 741 | * its contents have been placed into this stream. (If a mapped stream is 742 | * {@code null} an empty stream is used, instead.) 743 | *

744 | * This is an intermediate operation. 745 | * 746 | * @param mapper a non-interfering, stateless function to apply to each 747 | * key-value pair which produces a stream of new elements 748 | * @return the new stream 749 | * 750 | * @see #flatMap(Function) 751 | */ 752 | public LongStream flatMapToLong(BiFunction mapper) { 753 | return inner.flatMapToLong(e -> mapper.apply(e.getKey(), e.getValue())); 754 | } 755 | 756 | /** 757 | * Returns an {@code DoubleStream} consisting of the results of replacing 758 | * each element of this stream with the contents of a mapped stream produced 759 | * by applying the provided mapping function to each element. Each mapped 760 | * stream is {@link java.util.stream.BaseStream#close() closed} after its 761 | * contents have placed been into this stream. (If a mapped stream is 762 | * {@code null} an empty stream is used, instead.) 763 | *

764 | * This is an intermediate operation. 765 | * 766 | * @param mapper a non-interfering, stateless function to apply to each 767 | * element which produces a stream of new elements 768 | * @return the new stream 769 | * 770 | * @see #flatMap(Function) 771 | */ 772 | @Override 773 | public DoubleStream flatMapToDouble(Function, ? extends DoubleStream> mapper) { 774 | return inner.flatMapToDouble(mapper); 775 | } 776 | 777 | /** 778 | * Returns an {@code DoubleStream} consisting of the results of replacing 779 | * each key-value pair of this stream with the contents of a mapped stream 780 | * produced by applying the provided mapping function to each element. Each 781 | * mapped stream is {@link java.util.stream.BaseStream#close() closed} after 782 | * its contents have placed been into this stream. (If a mapped stream is 783 | * {@code null} an empty stream is used, instead.) 784 | *

785 | * This is an intermediate operation. 786 | * 787 | * @param mapper a non-interfering, stateless function to apply to each 788 | * key-value pair which produces a stream of new elements 789 | * @return the new stream 790 | * 791 | * @see #flatMap(Function) 792 | */ 793 | public DoubleStream flatMapToDouble(BiFunction mapper) { 794 | return inner.flatMapToDouble(e -> mapper.apply(e.getKey(), e.getValue())); 795 | } 796 | 797 | /** 798 | * Returns a stream of only the keys in this {@code MapStream}. 799 | *

800 | * This is an intermediate operation. 801 | * 802 | * @return a new stream of all keys 803 | */ 804 | public Stream keys() { 805 | return inner.map(Map.Entry::getKey); 806 | } 807 | 808 | /** 809 | * Returns a stream of only the values in this {@code MapStream}. 810 | *

811 | * This is an intermediate operation. 812 | * 813 | * @return a new stream of all values 814 | */ 815 | public Stream values() { 816 | return inner.map(Map.Entry::getValue); 817 | } 818 | 819 | /** 820 | * Returns a stream consisting of the distinct elements (according to 821 | * {@link Object#equals(Object)}) of this stream. 822 | *

823 | * For ordered streams, the selection of distinct elements is stable 824 | * (for duplicated elements, the element appearing first in the encounter 825 | * order is preserved.) For unordered streams, no stability guarantees 826 | * are made. 827 | *

828 | * This is a stateful intermediate operation. 829 | * 830 | *

831 | * Preserving stability for {@code distinct()} in parallel pipelines is 832 | * relatively expensive (requires that the operation act as a full barrier, 833 | * with substantial buffering overhead), and stability is often not needed. 834 | * Using an unordered stream source (such as {@link #generate(Supplier)}) 835 | * or removing the ordering constraint with {@link #unordered()} may result 836 | * in significantly more efficient execution for {@code distinct()} in parallel 837 | * pipelines, if the semantics of your situation permit. If consistency 838 | * with encounter order is required, and you are experiencing poor performance 839 | * or memory utilization with {@code distinct()} in parallel pipelines, 840 | * switching to sequential execution with {@link #sequential()} may improve 841 | * performance. 842 | * 843 | * @return the new stream 844 | */ 845 | @Override 846 | public MapStream distinct() { 847 | inner = inner.distinct(); 848 | return this; 849 | } 850 | 851 | /** 852 | * Returns a stream consisting of the distinct elements (according to 853 | * {@link Object#equals(Object)}) of this stream based on the key only. If 854 | * the same key is encountered multiple times, only the first occurence will 855 | * be allowed to pass. 856 | *

857 | * This is a stateful intermediate operation. 858 | * 859 | * @return the new stream 860 | */ 861 | public MapStream distinctKeys() { 862 | final Set temp = newSetFromMap(new ConcurrentHashMap<>()); 863 | 864 | inner = inner.flatMap(e -> 865 | temp.add(e.getKey()) 866 | ? Stream.of(e) 867 | : Stream.empty() 868 | ); 869 | 870 | return this; 871 | } 872 | 873 | /** 874 | * Returns a stream consisting of the distinct elements (according to 875 | * {@link Object#equals(Object)}) of this stream based on the value only. If 876 | * the same value is encountered multiple times, only the first occurence 877 | * will be allowed to pass. 878 | *

879 | * This is a stateful intermediate operation. 880 | * 881 | * @return the new stream 882 | */ 883 | public MapStream distinctValues() { 884 | final Set temp = newSetFromMap(new ConcurrentHashMap<>()); 885 | 886 | inner = inner.flatMap(e -> 887 | temp.add(e.getValue()) 888 | ? Stream.of(e) 889 | : Stream.empty() 890 | ); 891 | 892 | return this; 893 | } 894 | 895 | /** 896 | * Returns a stream consisting of the distinct elements (according to 897 | * {@link Object#equals(Object)}) of this stream based on the key only. If 898 | * the same key is encountered multiple times, the specified value merger 899 | * will be used to determine which value can pass. 900 | *

901 | * This operation will consume the wrapped stream and produce a new one. The 902 | * complexity of this operation is therefore O(n). 903 | *

904 | * This is a stateful intermediate operation. 905 | * 906 | * @param merger the merging operation to use 907 | * @return the new stream 908 | */ 909 | public MapStream distinctKeys(BinaryOperator merger) { 910 | final Map result = new ConcurrentHashMap<>(); 911 | 912 | inner.forEach(e -> { 913 | result.compute(e.getKey(), (k, v) -> 914 | merger.apply(e.getValue(), v) 915 | ); 916 | }); 917 | 918 | return MapStream.of(result); 919 | } 920 | 921 | /** 922 | * Returns a stream consisting of the distinct elements (according to 923 | * {@link Object#equals(Object)}) of this stream based on the value only. If 924 | * the same value is encountered multiple times, the specified key merger 925 | * will be used to determine which value can pass. 926 | *

927 | * This operation will consume the wrapped stream and produce a new one. The 928 | * complexity of this operation is therefore O(n). 929 | *

930 | * This is a stateful intermediate operation. 931 | * 932 | * @param merger the merging operation to use 933 | * @return the new stream 934 | */ 935 | public MapStream distinctValues(BinaryOperator merger) { 936 | final Map result = new ConcurrentHashMap<>(); 937 | 938 | inner.forEach(e -> { 939 | result.compute(e.getValue(), (v, k) -> 940 | merger.apply(e.getKey(), k) 941 | ); 942 | }); 943 | 944 | return MapStream.flip(MapStream.of(result)); 945 | } 946 | 947 | /** 948 | * Returns a stream consisting of the elements of this stream, sorted 949 | * according to natural order. If the elements of this stream are not 950 | * {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown 951 | * when the terminal operation is executed. 952 | *

953 | * For ordered streams, the sort is stable. For unordered streams, no 954 | * stability guarantees are made. 955 | *

956 | * This is a stateful intermediate operation. 957 | * 958 | * @return the new stream 959 | */ 960 | @Override 961 | public MapStream sorted() { 962 | final Comparator c = (a, b) -> { 963 | if (a == null && b == null) { 964 | return 0; 965 | } else if (a != null && b != null) { 966 | if (a instanceof Comparable) { 967 | @SuppressWarnings("unchecked") 968 | final Comparable ac = (Comparable) a; 969 | 970 | return ac.compareTo(b); 971 | } 972 | } 973 | 974 | throw new UnsupportedOperationException("Can only sort keys that implement Comparable."); 975 | }; 976 | 977 | inner = inner.sorted((a, b) -> c.compare(a.getKey(), b.getKey())); 978 | return this; 979 | } 980 | 981 | /** 982 | * Returns a stream consisting of the elements of this stream, sorted 983 | * according to the provided {@code Comparator}. 984 | *

985 | * For ordered streams, the sort is stable. For unordered streams, no 986 | * stability guarantees are made. 987 | *

988 | * This is a stateful intermediate operation. 989 | * 990 | * @param comparator a non-interfering, stateless {@code Comparator} to be 991 | * used to compare stream elements 992 | * @return the new stream 993 | */ 994 | @Override 995 | public MapStream sorted(Comparator> comparator) { 996 | inner = inner.sorted(comparator); 997 | return this; 998 | } 999 | 1000 | /** 1001 | * Returns a stream consisting of the elements of this stream, sorted 1002 | * according to the provided {@code Comparator} applied to the keys of the 1003 | * entries. 1004 | *

1005 | * For ordered streams, the sort is stable. For unordered streams, no 1006 | * stability guarantees are made. 1007 | *

1008 | * This is a stateful intermediate operation. 1009 | * 1010 | * @param comparator a non-interfering, stateless {@code Comparator} to be 1011 | * used to compare entity keys 1012 | * @return the new stream 1013 | */ 1014 | public MapStream sortedByKey(Comparator comparator) { 1015 | inner = inner.sorted(byKeyOnly(comparator)); 1016 | return this; 1017 | } 1018 | 1019 | /** 1020 | * Returns a stream consisting of the elements of this stream, sorted 1021 | * according to the provided {@code Comparator} applied to the values of the 1022 | * entries. 1023 | *

1024 | * For ordered streams, the sort is stable. For unordered streams, no 1025 | * stability guarantees are made. 1026 | *

1027 | * This is a stateful intermediate operation. 1028 | * 1029 | * @param comparator a non-interfering, stateless {@code Comparator} to be 1030 | * used to compare entity values 1031 | * @return the new stream 1032 | */ 1033 | public MapStream sortedByValue(Comparator comparator) { 1034 | inner = inner.sorted(byValueOnly(comparator)); 1035 | return this; 1036 | } 1037 | 1038 | /** 1039 | * Returns a stream consisting of the elements of this stream, additionally 1040 | * performing the provided action on each element as elements are consumed 1041 | * from the resulting stream. 1042 | *

1043 | * This is an intermediate operation. 1044 | *

1045 | * For parallel stream pipelines, the action may be called at 1046 | * whatever time and in whatever thread the element is made available by the 1047 | * upstream operation. If the action modifies shared state, 1048 | * it is responsible for providing the required synchronization. 1049 | * 1050 | *

This method exists mainly to support debugging, where you want 1051 | * to see the elements as they flow past a certain point in a pipeline: 1052 | *

{@code
1053 |      *     Stream.of("one", "two", "three", "four")
1054 |      *         .filter(e -> e.length() > 3)
1055 |      *         .peek(e -> System.out.println("Filtered value: " + e))
1056 |      *         .map(String::toUpperCase)
1057 |      *         .peek(e -> System.out.println("Mapped value: " + e))
1058 |      *         .collect(Collectors.toList());
1059 |      * }
1060 | * 1061 | * @param action a non-interfering action to perform on the elements as 1062 | * they are consumed from the stream 1063 | * @return the new stream 1064 | */ 1065 | @Override 1066 | public MapStream peek(Consumer> action) { 1067 | inner = inner.peek(action); 1068 | return this; 1069 | } 1070 | 1071 | /** 1072 | * Returns a stream consisting of the key-value pairs of this stream, 1073 | * additionally performing the provided action on each element as elements 1074 | * are consumed from the resulting stream. 1075 | *

1076 | * This is an intermediate operation. 1077 | *

1078 | * For parallel stream pipelines, the action may be called at 1079 | * whatever time and in whatever thread the element is made available by the 1080 | * upstream operation. If the action modifies shared state, 1081 | * it is responsible for providing the required synchronization. 1082 | * 1083 | *

This method exists mainly to support debugging, where you want 1084 | * to see the elements as they flow past a certain point in a pipeline: 1085 | *

{@code
1086 |      *     Stream.of("one", "two", "three", "four")
1087 |      *         .filter(e -> e.length() > 3)
1088 |      *         .peek(e -> System.out.println("Filtered value: " + e))
1089 |      *         .map(String::toUpperCase)
1090 |      *         .peek(e -> System.out.println("Mapped value: " + e))
1091 |      *         .collect(Collectors.toList());
1092 |      * }
1093 | * 1094 | * @param action a non-interfering action to perform on the key-value pairs 1095 | * as they are consumed from the stream 1096 | * @return the new stream 1097 | */ 1098 | public MapStream peek(BiConsumer action) { 1099 | inner = inner.peek(e -> action.accept(e.getKey(), e.getValue())); 1100 | return this; 1101 | } 1102 | 1103 | /** 1104 | * Returns a stream consisting of the elements of this stream, truncated 1105 | * to be no longer than {@code maxSize} in length. 1106 | *

1107 | * This is a short-circuiting stateful intermediate operation. 1108 | * 1109 | *

1110 | * While {@code limit()} is generally a cheap operation on sequential 1111 | * stream pipelines, it can be quite expensive on ordered parallel pipelines, 1112 | * especially for large values of {@code maxSize}, since {@code limit(n)} 1113 | * is constrained to return not just any n elements, but the 1114 | * first n elements in the encounter order. Using an unordered 1115 | * stream source (such as {@link #generate(Supplier)}) or removing the 1116 | * ordering constraint with {@link #unordered()} may result in significant 1117 | * speedups of {@code limit()} in parallel pipelines, if the semantics of 1118 | * your situation permit. If consistency with encounter order is required, 1119 | * and you are experiencing poor performance or memory utilization with 1120 | * {@code limit()} in parallel pipelines, switching to sequential execution 1121 | * with {@link #sequential()} may improve performance. 1122 | * 1123 | * @param maxSize the number of elements the stream should be limited to 1124 | * @return the new stream 1125 | * @throws IllegalArgumentException if {@code maxSize} is negative 1126 | */ 1127 | @Override 1128 | public MapStream limit(long maxSize) { 1129 | inner = inner.limit(maxSize); 1130 | return this; 1131 | } 1132 | 1133 | /** 1134 | * Returns a stream consisting of the remaining elements of this stream 1135 | * after discarding the first {@code n} elements of the stream. 1136 | * If this stream contains fewer than {@code n} elements then an 1137 | * empty stream will be returned. 1138 | *

1139 | * This is a stateful intermediate operation. 1140 | * 1141 | *

1142 | * While {@code skip()} is generally a cheap operation on sequential 1143 | * stream pipelines, it can be quite expensive on ordered parallel pipelines, 1144 | * especially for large values of {@code n}, since {@code skip(n)} 1145 | * is constrained to skip not just any n elements, but the 1146 | * first n elements in the encounter order. Using an unordered 1147 | * stream source (such as {@link #generate(Supplier)}) or removing the 1148 | * ordering constraint with {@link #unordered()} may result in significant 1149 | * speedups of {@code skip()} in parallel pipelines, if the semantics of 1150 | * your situation permit. If consistency with encounter order is required, 1151 | * and you are experiencing poor performance or memory utilization with 1152 | * {@code skip()} in parallel pipelines, switching to sequential execution 1153 | * with {@link #sequential()} may improve performance. 1154 | * 1155 | * @param n the number of leading elements to skip 1156 | * @return the new stream 1157 | * @throws IllegalArgumentException if {@code n} is negative 1158 | */ 1159 | @Override 1160 | public MapStream skip(long n) { 1161 | inner = inner.skip(n); 1162 | return this; 1163 | } 1164 | 1165 | /** 1166 | * Performs an action for each element of this stream. 1167 | *

1168 | * This is a terminal operation. 1169 | *

1170 | * The behavior of this operation is explicitly nondeterministic. 1171 | * For parallel stream pipelines, this operation does not 1172 | * guarantee to respect the encounter order of the stream, as doing so 1173 | * would sacrifice the benefit of parallelism. For any given element, the 1174 | * action may be performed at whatever time and in whatever thread the 1175 | * library chooses. If the action accesses shared state, it is 1176 | * responsible for providing the required synchronization. 1177 | * 1178 | * @param action a non-interfering action to perform on the elements 1179 | */ 1180 | @Override 1181 | public void forEach(Consumer> action) { 1182 | inner.forEach(action); 1183 | } 1184 | 1185 | /** 1186 | * Performs an action for each key-value pair of this stream. 1187 | *

1188 | * This is a terminal operation. 1189 | *

1190 | * The behavior of this operation is explicitly nondeterministic. 1191 | * For parallel stream pipelines, this operation does not 1192 | * guarantee to respect the encounter order of the stream, as doing so 1193 | * would sacrifice the benefit of parallelism. For any given element, the 1194 | * action may be performed at whatever time and in whatever thread the 1195 | * library chooses. If the action accesses shared state, it is 1196 | * responsible for providing the required synchronization. 1197 | * 1198 | * @param action a non-interfering action to perform on the key-value pairs 1199 | */ 1200 | public void forEach(BiConsumer action) { 1201 | inner.forEach(e -> action.accept(e.getKey(), e.getValue())); 1202 | } 1203 | 1204 | /** 1205 | * Performs an action for each element of this stream, in the encounter 1206 | * order of the stream if the stream has a defined encounter order. 1207 | *

1208 | * This is a terminal operation. 1209 | *

1210 | * This operation processes the elements one at a time, in encounter 1211 | * order if one exists. Performing the action for one element 1212 | * happens-before performing the action for subsequent elements, but 1213 | * for any given element, the action may be performed in whatever thread the 1214 | * library chooses. 1215 | * 1216 | * @param action a non-interfering action to perform on the elements 1217 | * @see #forEach(Consumer) 1218 | */ 1219 | @Override 1220 | public void forEachOrdered(Consumer> action) { 1221 | inner.forEachOrdered(action); 1222 | } 1223 | 1224 | /** 1225 | * Performs an action for each key-value pair of this stream, in the 1226 | * encounter order of the stream if the stream has a defined encounter 1227 | * order. 1228 | *

1229 | * This is a terminal operation. 1230 | *

1231 | * This operation processes the key-value pairs one at a time, in encounter 1232 | * order if one exists. Performing the action for one element 1233 | * happens-before performing the action for subsequent key-value 1234 | * pairs, but for any given element, the action may be performed in whatever 1235 | * thread the library chooses. 1236 | * 1237 | * @param action a non-interfering action to perform on the key-value pairs 1238 | * @see #forEach(Consumer) 1239 | */ 1240 | public void forEachOrdered(BiConsumer action) { 1241 | inner.forEachOrdered(e -> action.accept(e.getKey(), e.getValue())); 1242 | } 1243 | 1244 | /** 1245 | * Returns an array containing the elements of this stream. 1246 | *

1247 | * This is a terminal operation. 1248 | * 1249 | * @return an array containing the elements of this stream 1250 | */ 1251 | @Override 1252 | public Object[] toArray() { 1253 | return inner.toArray(); 1254 | } 1255 | 1256 | /** 1257 | * Returns an array containing the elements of this stream, using the 1258 | * provided {@code generator} function to allocate the returned array, as 1259 | * well as any additional arrays that might be required for a partitioned 1260 | * execution or for resizing. 1261 | *

1262 | * This is a terminal operation. 1263 | * 1264 | *

1265 | * The generator function takes an integer, which is the size of the 1266 | * desired array, and produces an array of the desired size. This can be 1267 | * concisely expressed with an array constructor reference: 1268 | *

{@code
1269 |      *     Person[] men = people.stream()
1270 |      *                          .filter(p -> p.getGender() == MALE)
1271 |      *                          .toArray(Person[]::new);
1272 |      * }
1273 | * 1274 | * @param the element type of the resulting array 1275 | * @param generator a function which produces a new array of the desired 1276 | * type and the provided length 1277 | * @return an array containing the elements in this stream 1278 | * @throws ArrayStoreException if the runtime type of the array 1279 | * returned from the array generator is not a supertype of 1280 | * the runtime type of every element in this stream 1281 | */ 1282 | @Override 1283 | public A[] toArray(IntFunction generator) { 1284 | return inner.toArray(generator); 1285 | } 1286 | 1287 | /** 1288 | * Performs a reduction on the elements of this stream, using the provided 1289 | * identity value and an associative accumulation function, and returns the 1290 | * reduced value. This is equivalent to: 1291 | *
{@code
1292 |      *     T result = identity;
1293 |      *     for (T element : this stream)
1294 |      *         result = accumulator.apply(result, element)
1295 |      *     return result;
1296 |      * }
1297 | * 1298 | * but is not constrained to execute sequentially. 1299 | *

1300 | * The {@code identity} value must be an identity for the accumulator 1301 | * function. This means that for all {@code t}, 1302 | * {@code accumulator.apply(identity, t)} is equal to {@code t}. 1303 | * The {@code accumulator} function must be an associative function. 1304 | *

1305 | * This is a terminal operation. 1306 | * 1307 | *

Sum, min, max, average, and string concatenation are all special 1308 | * cases of reduction. Summing a stream of numbers can be expressed as: 1309 | * 1310 | *

{@code
1311 |      *     Integer sum = integers.reduce(0, (a, b) -> a+b);
1312 |      * }
1313 | * 1314 | * or: 1315 | * 1316 | *
{@code
1317 |      *     Integer sum = integers.reduce(0, Integer::sum);
1318 |      * }
1319 | *

1320 | * While this may seem a more roundabout way to perform an aggregation 1321 | * compared to simply mutating a running total in a loop, reduction 1322 | * operations parallelize more gracefully, without needing additional 1323 | * synchronization and with greatly reduced risk of data races. 1324 | * 1325 | * @param identity the identity value for the accumulating function 1326 | * @param accumulator an associative, non-interfering stateless function 1327 | * for combining two values 1328 | * @return the result of the reduction 1329 | */ 1330 | @Override 1331 | public Map.Entry reduce(Map.Entry identity, BinaryOperator> accumulator) { 1332 | return inner.reduce(identity, accumulator); 1333 | } 1334 | 1335 | /** 1336 | * Performs a reduction on the elements of this stream, using an associative 1337 | * accumulation function, and returns an {@code Optional} describing the 1338 | * reduced value, if any. This is equivalent to: 1339 | *

{@code
1340 |      *     boolean foundAny = false;
1341 |      *     T result = null;
1342 |      *     for (T element : this stream) {
1343 |      *         if (!foundAny) {
1344 |      *             foundAny = true;
1345 |      *             result = element;
1346 |      *         }
1347 |      *         else
1348 |      *             result = accumulator.apply(result, element);
1349 |      *     }
1350 |      *     return foundAny ? Optional.of(result) : Optional.empty();
1351 |      * }
1352 | * 1353 | * but is not constrained to execute sequentially. 1354 | *

1355 | * The {@code accumulator} function must be an associative function. 1356 | *

1357 | * This is a terminal operation. 1358 | * 1359 | * @param accumulator an associative, non-interfering, stateless function 1360 | * for combining two values 1361 | * @return an {@link Optional} describing the result of the 1362 | * reduction 1363 | * @throws NullPointerException if the result of the reduction is null 1364 | * 1365 | * @see #reduce(Object, BinaryOperator) 1366 | * @see #min(Comparator) 1367 | * @see #max(Comparator) 1368 | */ 1369 | @Override 1370 | public Optional> reduce(BinaryOperator> accumulator) { 1371 | return inner.reduce(accumulator); 1372 | } 1373 | 1374 | /** 1375 | * Performs a reduction on the elements of this stream, using the provided 1376 | * identity, accumulation and combining functions. This is equivalent to: 1377 | *

{@code
1378 |      *     U result = identity;
1379 |      *     for (T element : this stream)
1380 |      *         result = accumulator.apply(result, element)
1381 |      *     return result;
1382 |      * }
1383 | * 1384 | * but is not constrained to execute sequentially. 1385 | *

1386 | * The {@code identity} value must be an identity for the combiner 1387 | * function. This means that for all {@code u}, {@code combiner(identity, u)} 1388 | * is equal to {@code u}. Additionally, the {@code combiner} function 1389 | * must be compatible with the {@code accumulator} function; for all 1390 | * {@code u} and {@code t}, the following must hold: 1391 | *

{@code
1392 |      *     combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
1393 |      * }
1394 | *

1395 | * This is a terminal operation. 1396 | * 1397 | *

Many reductions using this form can be represented more simply 1398 | * by an explicit combination of {@code map} and {@code reduce} operations. 1399 | * The {@code accumulator} function acts as a fused mapper and accumulator, 1400 | * which can sometimes be more efficient than separate mapping and reduction, 1401 | * such as when knowing the previously reduced value allows you to avoid 1402 | * some computation. 1403 | * 1404 | * @param the type of the result 1405 | * @param identity the identity value for the combiner function 1406 | * @param accumulator an associative, non-interfering, stateless function 1407 | * for incorporating an additional element into a result 1408 | * @param combiner an associative, non-interfering, stateless 1409 | * function for combining two values, which must be 1410 | * compatible with the accumulator function 1411 | * @return the result of the reduction 1412 | * 1413 | * @see #reduce(BinaryOperator) 1414 | * @see #reduce(Object, BinaryOperator) 1415 | */ 1416 | @Override 1417 | public U reduce(U identity, BiFunction, U> accumulator, BinaryOperator combiner) { 1418 | return inner.reduce(identity, accumulator, combiner); 1419 | } 1420 | 1421 | /** 1422 | * Performs a mutable reduction operation on the elements of this stream. A 1423 | * mutable reduction is one in which the reduced value is a mutable result 1424 | * container, such as an {@code ArrayList}, and elements are incorporated by 1425 | * updating the state of the result rather than by replacing the result. 1426 | * This produces a result equivalent to: 1427 | *

{@code
1428 |      *     R result = supplier.get();
1429 |      *     for (T element : this stream)
1430 |      *         accumulator.accept(result, element);
1431 |      *     return result;
1432 |      * }
1433 | *

1434 | * Like {@link #reduce(Object, BinaryOperator)}, {@code collect} operations 1435 | * can be parallelized without requiring additional synchronization. 1436 | *

1437 | * This is a terminal operation. 1438 | * 1439 | *

There are many existing classes in the JDK whose signatures are 1440 | * well-suited for use with method references as arguments to {@code collect()}. 1441 | * For example, the following will accumulate strings into an {@code ArrayList}: 1442 | *

{@code
1443 |      *     List asList = stringStream.collect(ArrayList::new, ArrayList::add,
1444 |      *                                                ArrayList::addAll);
1445 |      * }
1446 | *

1447 | * The following will take a stream of strings and concatenates them into a 1448 | * single string: 1449 | *

{@code
1450 |      *     String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
1451 |      *                                          StringBuilder::append)
1452 |      *                                 .toString();
1453 |      * }
1454 | * 1455 | * @param type of the result 1456 | * @param supplier a function that creates a new result container. For a 1457 | * parallel execution, this function may be called 1458 | * multiple times and must return a fresh value each 1459 | * time. 1460 | * @param accumulator an associative, non-interfering, stateless function 1461 | * for incorporating an additional element into a result 1462 | * @param combiner an associative, non-interfering, stateless function 1463 | * for combining two values, which must be compatible 1464 | * with the accumulator function 1465 | * @return the result of the reduction 1466 | */ 1467 | @Override 1468 | public R collect(Supplier supplier, BiConsumer> accumulator, BiConsumer combiner) { 1469 | return inner.collect(supplier, accumulator, combiner); 1470 | } 1471 | 1472 | /** 1473 | * Performs a mutable reduction operation on the elements of this stream 1474 | * using a {@code Collector}. A {@code Collector} encapsulates the functions 1475 | * used as arguments to {@link #collect(Supplier, BiConsumer, BiConsumer)}, 1476 | * allowing for reuse of collection strategies and composition of collect 1477 | * operations such as multiple-level grouping or partitioning. 1478 | *

1479 | * If the stream is parallel, and the {@code Collector} is 1480 | * {@link Collector.Characteristics#CONCURRENT concurrent}, and either the 1481 | * stream is unordered or the collector is 1482 | * {@link Collector.Characteristics#UNORDERED unordered}, 1483 | * then a concurrent reduction will be performed (see {@link Collector} for 1484 | * details on concurrent reduction.) 1485 | *

1486 | * This is a terminal operation. 1487 | *

1488 | * When executed in parallel, multiple intermediate results may be 1489 | * instantiated, populated, and merged so as to maintain isolation of 1490 | * mutable data structures. Therefore, even when executed in parallel 1491 | * with non-thread-safe data structures (such as {@code ArrayList}), no 1492 | * additional synchronization is needed for a parallel reduction. 1493 | * 1494 | *

1495 | * The following will accumulate strings into an ArrayList: 1496 | *

{@code
1497 |      *     List asList = stringStream.collect(Collectors.toList());
1498 |      * }
1499 | *

1500 | * The following will classify {@code Person} objects by city: 1501 | *

{@code
1502 |      *     Map> peopleByCity
1503 |      *         = personStream.collect(Collectors.groupingBy(Person::getCity));
1504 |      * }
1505 | *

1506 | * The following will classify {@code Person} objects by state and city, 1507 | * cascading two {@code Collector}s together: 1508 | *

{@code
1509 |      *     Map>> peopleByStateAndCity
1510 |      *         = personStream.collect(Collectors.groupingBy(Person::getState,
1511 |      *                                                      Collectors.groupingBy(Person::getCity)));
1512 |      * }
1513 | * 1514 | * @param the type of the result 1515 | * @param
the intermediate accumulation type of the 1516 | * {@code Collector} 1517 | * @param collector the {@code Collector} describing the reduction 1518 | * @return the result of the reduction 1519 | * 1520 | * @see #collect(Supplier, BiConsumer, BiConsumer) 1521 | * @see Collectors 1522 | */ 1523 | @Override 1524 | public R collect(Collector, A, R> collector) { 1525 | return inner.collect(collector); 1526 | } 1527 | 1528 | /** 1529 | * Returns a new {@code MapStream} where the key component is calculated by 1530 | * applying the specified grouper function to the values of this stream and 1531 | * the value is a stream consisting of all the entries that produced the 1532 | * same key. 1533 | *

1534 | * This is a stateful intermediate operation. 1535 | * 1536 | * @param the type of the new key 1537 | * @param grouper the function to use for grouping entries 1538 | * @return the new stream 1539 | */ 1540 | public MapStream> groupingBy(Function grouper) { 1541 | return inner.map(Map.Entry::getValue) 1542 | .collect(CollectorUtil.groupBy(grouper)); 1543 | } 1544 | 1545 | /** 1546 | * Returns the minimum element of this stream according to the provided 1547 | * {@code Comparator}. This is a special case of a reduction. 1548 | *

1549 | * This is a terminal operation. 1550 | * 1551 | * @param comparator a non-interfering, stateless {@code Comparator} to 1552 | * compare elements of this stream 1553 | * @return an {@code Optional} describing the minimum element of 1554 | * this stream, or an empty {@code Optional} if the 1555 | * stream is empty 1556 | * 1557 | * @throws NullPointerException if the minimum element is null 1558 | */ 1559 | @Override 1560 | public Optional> min(Comparator> comparator) { 1561 | return inner.min(comparator); 1562 | } 1563 | 1564 | /** 1565 | * Returns the minimum element of this stream according to the provided 1566 | * {@code Comparator} applied to the key-components of this stream. This is 1567 | * a special case of a reduction. 1568 | *

1569 | * This is a terminal operation. 1570 | * 1571 | * @param comparator a non-interfering, stateless {@code Comparator} to 1572 | * compare keys of this stream 1573 | * @return an {@code Optional} describing the minimum element of 1574 | * this stream, or an empty {@code Optional} if the 1575 | * stream is empty 1576 | * 1577 | * @throws NullPointerException if the minimum element is null 1578 | */ 1579 | public Optional> minByKey(Comparator comparator) { 1580 | return inner.min(byKeyOnly(comparator)); 1581 | } 1582 | 1583 | /** 1584 | * Returns the minimum element of this stream according to the provided 1585 | * {@code Comparator} applied to the value-components of this stream. This 1586 | * is a special case of a reduction. 1587 | *

1588 | * This is a terminal operation. 1589 | * 1590 | * @param comparator a non-interfering, stateless {@code Comparator} to 1591 | * compare values of this stream 1592 | * @return an {@code Optional} describing the minimum element of 1593 | * this stream, or an empty {@code Optional} if the 1594 | * stream is empty 1595 | * 1596 | * @throws NullPointerException if the minimum element is null 1597 | */ 1598 | public Optional> minByValue(Comparator comparator) { 1599 | return inner.min(byValueOnly(comparator)); 1600 | } 1601 | 1602 | /** 1603 | * Returns the maximum element of this stream according to the provided 1604 | * {@code Comparator}. This is a special case of a reduction. 1605 | *

1606 | * This is a terminal operation. 1607 | * 1608 | * @param comparator a non-interfering, stateless {@code Comparator} to 1609 | * compare elements of this stream 1610 | * @return an {@code Optional} describing the maximum element of 1611 | * this stream, or an empty {@code Optional} if the 1612 | * stream is empty 1613 | * 1614 | * @throws NullPointerException if the maximum element is null 1615 | */ 1616 | @Override 1617 | public Optional> max(Comparator> comparator) { 1618 | return inner.max(comparator); 1619 | } 1620 | 1621 | /** 1622 | * Returns the maximum element of this stream according to the provided 1623 | * {@code Comparator} applied to the key-components of this stream. This 1624 | * is a special case of a reduction. 1625 | *

1626 | * This is a terminal operation. 1627 | * 1628 | * @param comparator a non-interfering, stateless {@code Comparator} to 1629 | * compare keys of this stream 1630 | * @return an {@code Optional} describing the maximum element of 1631 | * this stream, or an empty {@code Optional} if the 1632 | * stream is empty 1633 | * 1634 | * @throws NullPointerException if the maximum element is null 1635 | */ 1636 | public Optional> maxByKey(Comparator comparator) { 1637 | return inner.max(byKeyOnly(comparator)); 1638 | } 1639 | 1640 | /** 1641 | * Returns the maximum element of this stream according to the provided 1642 | * {@code Comparator} applied to the value-components of this stream. This 1643 | * is a special case of a reduction. 1644 | *

1645 | * This is a terminal operation. 1646 | * 1647 | * @param comparator a non-interfering, stateless {@code Comparator} to 1648 | * compare values of this stream 1649 | * @return an {@code Optional} describing the maximum element of 1650 | * this stream, or an empty {@code Optional} if the 1651 | * stream is empty 1652 | * 1653 | * @throws NullPointerException if the maximum element is null 1654 | */ 1655 | public Optional> maxByValue(Comparator comparator) { 1656 | return inner.max(byValueOnly(comparator)); 1657 | } 1658 | 1659 | /** 1660 | * Returns the count of elements in this stream. This is a special case of 1661 | * a reduction and is equivalent to: 1662 | *

{@code
1663 |      *     return mapToLong(e -> 1L).sum();
1664 |      * }
1665 | *

1666 | * This is a terminal operation. 1667 | * 1668 | * @return the count of elements in this stream 1669 | */ 1670 | @Override 1671 | public long count() { 1672 | return inner.count(); 1673 | } 1674 | 1675 | /** 1676 | * Returns whether any elements of this stream match the provided 1677 | * predicate. May not evaluate the predicate on all elements if not 1678 | * necessary for determining the result. If the stream is empty then 1679 | * {@code false} is returned and the predicate is not evaluated. 1680 | *

1681 | * This is a short-circuiting terminal operation. 1682 | * 1683 | *

1684 | * This method evaluates the existential quantification of the 1685 | * predicate over the elements of the stream (for some x P(x)). 1686 | * 1687 | * @param predicate a non-interfering, stateless predicate to apply to 1688 | * elements of this stream 1689 | * @return {@code true} if any elements of the stream match the 1690 | * provided predicate, otherwise {@code false} 1691 | */ 1692 | @Override 1693 | public boolean anyMatch(Predicate> predicate) { 1694 | return inner.anyMatch(predicate); 1695 | } 1696 | 1697 | /** 1698 | * Returns whether any key-value pairs of this stream match the provided 1699 | * predicate. May not evaluate the predicate on all elements if not 1700 | * necessary for determining the result. If the stream is empty then 1701 | * {@code false} is returned and the predicate is not evaluated. 1702 | *

1703 | * This is a short-circuiting terminal operation. 1704 | * 1705 | *

1706 | * This method evaluates the existential quantification of the 1707 | * predicate over the elements of the stream (for some x P(x)). 1708 | * 1709 | * @param predicate a non-interfering, stateless predicate to apply to 1710 | * key-value pairs of this stream 1711 | * @return {@code true} if any key-value pairs of the stream match 1712 | * the provided predicate, otherwise {@code false} 1713 | */ 1714 | public boolean anyMatch(BiPredicate predicate) { 1715 | return inner.anyMatch(e -> predicate.test(e.getKey(), e.getValue())); 1716 | } 1717 | 1718 | /** 1719 | * Returns whether all elements of this stream match the provided predicate. 1720 | * May not evaluate the predicate on all elements if not necessary for 1721 | * determining the result. If the stream is empty then {@code true} is 1722 | * returned and the predicate is not evaluated. 1723 | *

1724 | * This is a short-circuiting terminal operation. 1725 | * 1726 | *

1727 | * This method evaluates the universal quantification of the 1728 | * predicate over the elements of the stream (for all x P(x)). If the 1729 | * stream is empty, the quantification is said to be vacuously 1730 | * satisfied and is always {@code true} (regardless of P(x)). 1731 | * 1732 | * @param predicate a non-interfering, stateless predicate to apply to 1733 | * elements of this stream 1734 | * @return {@code true} if either all elements of the stream match 1735 | * the provided predicate or the stream is empty, 1736 | * otherwise {@code false} 1737 | */ 1738 | @Override 1739 | public boolean allMatch(Predicate> predicate) { 1740 | return inner.allMatch(predicate); 1741 | } 1742 | 1743 | /** 1744 | * Returns whether all key-value pairs of this stream match the provided 1745 | * predicate. May not evaluate the predicate on all key-value pairs if not 1746 | * necessary for determining the result. If the stream is empty then 1747 | * {@code true} is returned and the predicate is not evaluated. 1748 | *

1749 | * This is a short-circuiting terminal operation. 1750 | * 1751 | *

1752 | * This method evaluates the universal quantification of the 1753 | * predicate over the elements of the stream (for all x P(x)). If the 1754 | * stream is empty, the quantification is said to be vacuously 1755 | * satisfied and is always {@code true} (regardless of P(x)). 1756 | * 1757 | * @param predicate a non-interfering, stateless predicate to apply to 1758 | * key-value pairs of this stream 1759 | * @return {@code true} if either all key-value pairs of the 1760 | * stream match the provided predicate or the stream is 1761 | * empty, otherwise {@code false} 1762 | */ 1763 | public boolean allMatch(BiPredicate predicate) { 1764 | return inner.allMatch(e -> predicate.test(e.getKey(), e.getValue())); 1765 | } 1766 | 1767 | /** 1768 | * Returns whether no elements of this stream match the provided predicate. 1769 | * May not evaluate the predicate on all elements if not necessary for 1770 | * determining the result. If the stream is empty then {@code true} is 1771 | * returned and the predicate is not evaluated. 1772 | *

1773 | * This is a short-circuiting terminal operation. 1774 | * 1775 | *

1776 | * This method evaluates the universal quantification of the 1777 | * negated predicate over the elements of the stream (for all x ~P(x)). If 1778 | * the stream is empty, the quantification is said to be vacuously satisfied 1779 | * and is always {@code true}, regardless of P(x). 1780 | * 1781 | * @param predicate a non-interfering, stateless predicate to apply to 1782 | * elements of this stream 1783 | * @return {@code true} if either no elements of the stream match 1784 | * the provided predicate or the stream is empty, 1785 | * otherwise {@code false} 1786 | */ 1787 | @Override 1788 | public boolean noneMatch(Predicate> predicate) { 1789 | return inner.noneMatch(predicate); 1790 | } 1791 | 1792 | /** 1793 | * Returns whether no key-value pairs of this stream match the provided 1794 | * predicate. May not evaluate the predicate on all key-value pairs if not 1795 | * necessary for determining the result. If the stream is empty then 1796 | * {@code true} is returned and the predicate is not evaluated. 1797 | *

1798 | * This is a short-circuiting terminal operation. 1799 | * 1800 | *

1801 | * This method evaluates the universal quantification of the 1802 | * negated predicate over the elements of the stream (for all x ~P(x)). If 1803 | * the stream is empty, the quantification is said to be vacuously satisfied 1804 | * and is always {@code true}, regardless of P(x). 1805 | * 1806 | * @param predicate a non-interfering, stateless predicate to apply to 1807 | * key-value pairs of this stream 1808 | * @return {@code true} if either no key-value pairs of the 1809 | * stream match the provided predicate or the stream is 1810 | * empty, otherwise {@code false} 1811 | */ 1812 | public boolean noneMatch(BiPredicate predicate) { 1813 | return inner.noneMatch(e -> predicate.test(e.getKey(), e.getValue())); 1814 | } 1815 | 1816 | /** 1817 | * Returns an {@link Optional} describing the first element of this stream, 1818 | * or an empty {@code Optional} if the stream is empty. If the stream has 1819 | * no encounter order, then any element may be returned. 1820 | *

1821 | * This is a short-circuiting terminal operation. 1822 | * 1823 | * @return an {@code Optional} describing the first element of this stream, 1824 | * or an empty {@code Optional} if the stream is empty 1825 | * 1826 | * @throws NullPointerException if the element selected is null 1827 | */ 1828 | @Override 1829 | public Optional> findFirst() { 1830 | return inner.findFirst(); 1831 | } 1832 | 1833 | /** 1834 | * Returns an {@link Optional} describing some element of the stream, or an 1835 | * empty {@code Optional} if the stream is empty. 1836 | *

1837 | * This is a short-circuiting terminal operation. 1838 | *

1839 | * The behavior of this operation is explicitly nondeterministic; it is 1840 | * free to select any element in the stream. This is to allow for maximal 1841 | * performance in parallel operations; the cost is that multiple invocations 1842 | * on the same source may not return the same result. (If a stable result 1843 | * is desired, use {@link #findFirst()} instead.) 1844 | * 1845 | * @return an {@code Optional} describing some element of this stream, or an 1846 | * empty {@code Optional} if the stream is empty 1847 | * 1848 | * @throws NullPointerException if the element selected is null 1849 | * @see #findFirst() 1850 | */ 1851 | @Override 1852 | public Optional> findAny() { 1853 | return inner.findAny(); 1854 | } 1855 | 1856 | /** 1857 | * Returns an iterator for the elements of this stream. 1858 | *

1859 | * This is a terminal operation. 1860 | * 1861 | * @return the element iterator for this stream 1862 | */ 1863 | @Override 1864 | public Iterator> iterator() { 1865 | return inner.iterator(); 1866 | } 1867 | 1868 | /** 1869 | * Returns a spliterator for the elements of this stream. 1870 | *

1871 | * This is a terminal operation. 1872 | * 1873 | * @return the element spliterator for this stream 1874 | */ 1875 | @Override 1876 | public Spliterator> spliterator() { 1877 | return inner.spliterator(); 1878 | } 1879 | 1880 | /** 1881 | * Returns whether this stream, if a terminal operation were to be executed, 1882 | * would execute in parallel. Calling this method after invoking an 1883 | * terminal stream operation method may yield unpredictable results. 1884 | * 1885 | * @return {@code true} if this stream would execute in parallel if executed 1886 | */ 1887 | @Override 1888 | public boolean isParallel() { 1889 | return inner.isParallel(); 1890 | } 1891 | 1892 | /** 1893 | * Returns an equivalent stream that is sequential. May return 1894 | * itself, either because the stream was already sequential, or because 1895 | * the underlying stream state was modified to be sequential. 1896 | *

1897 | * This is an intermediate operation. 1898 | * 1899 | * @return a sequential stream 1900 | */ 1901 | @Override 1902 | public MapStream sequential() { 1903 | inner = inner.sequential(); 1904 | return this; 1905 | } 1906 | 1907 | /** 1908 | * Returns an equivalent stream that is parallel. May return 1909 | * itself, either because the stream was already parallel, or because 1910 | * the underlying stream state was modified to be parallel. 1911 | *

1912 | * This is an intermediate operation. 1913 | * 1914 | * @return a parallel stream 1915 | */ 1916 | @Override 1917 | public MapStream parallel() { 1918 | inner = inner.parallel(); 1919 | return this; 1920 | } 1921 | 1922 | /** 1923 | * Returns an equivalent stream that is 1924 | * unordered. May return 1925 | * itself, either because the stream was already unordered, or because 1926 | * the underlying stream state was modified to be unordered. 1927 | *

1928 | * This is an intermediate operation. 1929 | * 1930 | * @return an unordered stream 1931 | */ 1932 | @Override 1933 | public MapStream unordered() { 1934 | inner = inner.unordered(); 1935 | return this; 1936 | } 1937 | 1938 | /** 1939 | * Returns an equivalent stream with an additional close handler. Close 1940 | * handlers are run when the {@link #close()} method 1941 | * is called on the stream, and are executed in the order they were 1942 | * added. All close handlers are run, even if earlier close handlers throw 1943 | * exceptions. If any close handler throws an exception, the first 1944 | * exception thrown will be relayed to the caller of {@code close()}, with 1945 | * any remaining exceptions added to that exception as suppressed exceptions 1946 | * (unless one of the remaining exceptions is the same exception as the 1947 | * first exception, since an exception cannot suppress itself.) May 1948 | * return itself. 1949 | *

1950 | * This is an intermediate operation. 1951 | * 1952 | * @param closeHandler a task to execute when the stream is closed 1953 | * @return a stream with a handler that is run if the stream is 1954 | * closed 1955 | */ 1956 | @Override 1957 | public MapStream onClose(Runnable closeHandler) { 1958 | inner = inner.onClose(closeHandler); 1959 | return this; 1960 | } 1961 | 1962 | /** 1963 | * Closes this stream, causing all close handlers for this stream pipeline 1964 | * to be called. 1965 | * 1966 | * @see AutoCloseable#close() 1967 | */ 1968 | @Override 1969 | public void close() { 1970 | inner.close(); 1971 | } 1972 | 1973 | /** 1974 | * Accumulates all key-value pairs of this {@code MapStream} into a {@code Map}. 1975 | *

1976 | * If the mapped keys contains duplicates (according to 1977 | * {@link Object#equals(Object)}), an {@code IllegalStateException} is 1978 | * thrown when the collection operation is performed. If the mapped keys 1979 | * may have duplicates, use {@link #toMap(BinaryOperator)} 1980 | * instead. 1981 | * 1982 | *

1983 | * The returned {@code Map} is not concurrent. For parallel stream 1984 | * pipelines, the {@code combiner} function operates by merging the keys 1985 | * from one map into another, which can be an expensive operation. If it is 1986 | * not required that results are inserted into the {@code Map} in encounter 1987 | * order, using {@link #toConcurrentMap()} 1988 | * may offer better parallel performance. 1989 | * 1990 | * @return a {@code Map} whose keys and values are identical to the entries 1991 | * of this stream 1992 | * 1993 | * @see #toMap(BinaryOperator) 1994 | * @see #toConcurrentMap() 1995 | */ 1996 | public Map toMap() { 1997 | return inner.collect(Collectors.toMap( 1998 | Map.Entry::getKey, 1999 | Map.Entry::getValue 2000 | )); 2001 | } 2002 | 2003 | /** 2004 | * Accumulates all key-value pairs of this {@code MapStream} into a {@code Map}. 2005 | *

2006 | * If the mapped keys contains duplicates (according to 2007 | * {@link Object#equals(Object)}), the values are merged using the provided 2008 | * merging function. 2009 | * 2010 | *

2011 | * There are multiple ways to deal with collisions between multiple elements 2012 | * mapping to the same key. The other forms of {@code toMap} simply use 2013 | * a merge function that throws unconditionally, but you can easily write 2014 | * more flexible merge policies. 2015 | * 2016 | *

2017 | * The returned {@code Map} is not concurrent. For parallel stream 2018 | * pipelines, the {@code combiner} function operates by merging the keys 2019 | * from one map into another, which can be an expensive operation. If it is 2020 | * not required that results are merged into the {@code Map} in encounter 2021 | * order, using {@link #toConcurrentMap(BinaryOperator)} 2022 | * may offer better parallel performance. 2023 | * 2024 | * @param mergeFunction a merge function, used to resolve collisions 2025 | * between values associated with the same key, as 2026 | * supplied to {@link Map#merge(Object, Object, BiFunction)} 2027 | * @return a {@code Map} whose keys and values are identical 2028 | * to the entries of this stream with any collisions 2029 | * handled 2030 | * 2031 | * @see #toMap() 2032 | * @see #toConcurrentMap(BinaryOperator) 2033 | */ 2034 | public Map toMap(BinaryOperator mergeFunction) { 2035 | return inner.collect(Collectors.toMap( 2036 | Map.Entry::getKey, 2037 | Map.Entry::getValue, 2038 | mergeFunction 2039 | )); 2040 | } 2041 | 2042 | /** 2043 | * Accumulates all key-value pairs of this {@code MapStream} into a 2044 | * {@code ConcurrentMap}. 2045 | *

2046 | * If the mapped keys contains duplicates (according to 2047 | * {@link Object#equals(Object)}), an {@code IllegalStateException} is 2048 | * thrown when the collection operation is performed. If the mapped keys 2049 | * may have duplicates, use {@link #toConcurrentMap(BinaryOperator)} instead. 2050 | * 2051 | *

2052 | * It is common for either the key or the value to be the input elements. 2053 | * In this case, the utility method 2054 | * {@link java.util.function.Function#identity()} may be helpful. 2055 | *

2056 | * This is a {@link Collector.Characteristics#CONCURRENT concurrent} and 2057 | * {@link Collector.Characteristics#UNORDERED unordered} Collector. 2058 | * 2059 | * @return a {@code ConcurrentMap} whose keys are taken from this stream 2060 | * 2061 | * @see #toMap() 2062 | * @see #toConcurrentMap(BinaryOperator) 2063 | */ 2064 | public Map toConcurrentMap() { 2065 | return inner.collect(Collectors.toConcurrentMap( 2066 | Map.Entry::getKey, 2067 | Map.Entry::getValue 2068 | )); 2069 | } 2070 | 2071 | /** 2072 | * Accumulates all key-value pairs of this {@code MapStream} into a 2073 | * {@code ConcurrentMap}. 2074 | *

2075 | * If the mapped keys contains duplicates (according to 2076 | * {@link Object#equals(Object)}), the value mapping function is applied to 2077 | * each equal element, and the results are merged using the provided merging 2078 | * function. 2079 | * 2080 | *

2081 | * There are multiple ways to deal with collisions between multiple elements 2082 | * mapping to the same key. The other forms of {@code toConcurrentMap} simply use 2083 | * a merge function that throws unconditionally, but you can easily write 2084 | * more flexible merge policies. 2085 | * 2086 | * @param mergeFunction a merge function, used to resolve collisions between 2087 | * values associated with the same key, as supplied 2088 | * to {@link Map#merge(Object, Object, BiFunction)} 2089 | * @return a {@code ConcurrentMap} whose keys are taken from this stream 2090 | * 2091 | * @see #toConcurrentMap() 2092 | * @see #toMap(BinaryOperator) 2093 | */ 2094 | public Map toConcurrentMap(BinaryOperator mergeFunction) { 2095 | return inner.collect(Collectors.toConcurrentMap( 2096 | Map.Entry::getKey, 2097 | Map.Entry::getValue, 2098 | mergeFunction 2099 | )); 2100 | } 2101 | 2102 | /** 2103 | * Accumulates all key-value pairs of this {@code MapStream} into a 2104 | * {@code SortedMap}. 2105 | *

2106 | * If the mapped keys contains duplicates (according to 2107 | * {@link Object#equals(Object)}), an {@code IllegalStateException} is 2108 | * thrown when the collection operation is performed. If the mapped keys 2109 | * may have duplicates, use {@link #toSortedMap(BinaryOperator)} 2110 | * instead. 2111 | *

2112 | * If the keys are not {@link Comparable}, a 2113 | * {@code java.lang.ClassCastException} may be thrown when the terminal 2114 | * operation is executed. It is therefore better to use 2115 | * {@link #toSortedMapByKey(Comparator)} since it allows you to specify 2116 | * a comparator to use when comparing the keys. 2117 | * 2118 | *

2119 | * The returned {@code Map} is not concurrent. For parallel stream 2120 | * pipelines, use {@link #toConcurrentNavigableMap()} instead. 2121 | * 2122 | * @return a {@code Map} whose keys and values are identical to the entries 2123 | * of this stream 2124 | * 2125 | * @see #toMap(BinaryOperator) 2126 | * @see #toConcurrentMap() 2127 | */ 2128 | public SortedMap toSortedMap() { 2129 | return inner.collect(Collectors.toMap( 2130 | Map.Entry::getKey, 2131 | Map.Entry::getValue, 2132 | throwingMerger(), 2133 | TreeMap::new 2134 | )); 2135 | } 2136 | 2137 | /** 2138 | * Accumulates all key-value pairs of this {@code MapStream} into a 2139 | * {@code SortedMap}, sorting the entries by applying the specified 2140 | * comparator to the keys of the stream. 2141 | *

2142 | * If the mapped keys contains duplicates (according to 2143 | * {@link Object#equals(Object)}), an {@code IllegalStateException} is 2144 | * thrown when the collection operation is performed. If the mapped keys 2145 | * may have duplicates, use {@link #toSortedMap(Comparator, BinaryOperator)} 2146 | * instead. 2147 | * 2148 | *

2149 | * The returned {@code Map} is not concurrent. For parallel stream 2150 | * pipelines, use {@link #toConcurrentNavigableMap()} instead. 2151 | * 2152 | * @param keyComparator the comparator to use when sorting the keys 2153 | * @return a {@code SortedMap} whose keys and values are 2154 | * identical to the entries of this stream 2155 | * 2156 | * @see #toMap(BinaryOperator) 2157 | * @see #toConcurrentMap() 2158 | * @see #toSortedMap() 2159 | */ 2160 | public SortedMap toSortedMapByKey(Comparator keyComparator) { 2161 | return inner.collect(Collectors.toMap( 2162 | Map.Entry::getKey, 2163 | Map.Entry::getValue, 2164 | throwingMerger(), 2165 | () -> new TreeMap<>(keyComparator) 2166 | )); 2167 | } 2168 | 2169 | /** 2170 | * Accumulates all key-value pairs of this {@code MapStream} into a 2171 | * {@code SortedMap}. 2172 | *

2173 | * If the mapped keys contains duplicates (according to 2174 | * {@link Object#equals(Object)}), the values are merged using the provided 2175 | * merging function. 2176 | * 2177 | *

2178 | * There are multiple ways to deal with collisions between multiple elements 2179 | * mapping to the same key. The other forms of {@code toSortedMap} simply 2180 | * use a merge function that throws unconditionally, but you can easily 2181 | * write more flexible merge policies. 2182 | * 2183 | *

2184 | * The returned {@code SortedMap} is not concurrent. For parallel stream 2185 | * pipelines, the {@code combiner} function operates by merging the keys 2186 | * from one map into another, which can be an expensive operation. If it is 2187 | * not required that results are merged into the {@code Map} in encounter 2188 | * order, using {@link #toConcurrentNavigableMap(BinaryOperator)} 2189 | * may offer better parallel performance. 2190 | * 2191 | * @param mergeFunction a merge function, used to resolve collisions 2192 | * between values associated with the same key, as 2193 | * supplied to {@link Map#merge(Object, Object, BiFunction)} 2194 | * @return a {@code SortedMap} whose keys and values are identical 2195 | * to the entries of this stream with any collisions 2196 | * handled 2197 | * 2198 | * @see #toMap() 2199 | * @see #toSortedMap() 2200 | * @see #toConcurrentMap(BinaryOperator) 2201 | */ 2202 | public SortedMap toSortedMap(BinaryOperator mergeFunction) { 2203 | return inner.collect(Collectors.toMap( 2204 | Map.Entry::getKey, 2205 | Map.Entry::getValue, 2206 | mergeFunction, 2207 | TreeMap::new 2208 | )); 2209 | } 2210 | 2211 | /** 2212 | * Accumulates all key-value pairs of this {@code MapStream} into a 2213 | * {@code SortedMap}, sorting the entries by applying the specified 2214 | * comparator to the keys of the stream. 2215 | *

2216 | * If the mapped keys contains duplicates (according to 2217 | * {@link Object#equals(Object)}), the values are merged using the provided 2218 | * merging function. 2219 | * 2220 | *

2221 | * There are multiple ways to deal with collisions between multiple elements 2222 | * mapping to the same key. The other forms of {@code toSortedMap} simply 2223 | * use a merge function that throws unconditionally, but you can easily 2224 | * write more flexible merge policies. 2225 | * 2226 | *

2227 | * The returned {@code SortedMap} is not concurrent. For parallel stream 2228 | * pipelines, the {@code combiner} function operates by merging the keys 2229 | * from one map into another, which can be an expensive operation. If it is 2230 | * not required that results are merged into the {@code Map} in encounter 2231 | * order, using {@link #toConcurrentNavigableMap(Comparator, BinaryOperator)} 2232 | * may offer better parallel performance. 2233 | * 2234 | * @param keyComparator the comparator to use for determining the order of 2235 | * the keys 2236 | * @param mergeFunction a merge function, used to resolve collisions 2237 | * between values associated with the same key, as 2238 | * supplied to {@link Map#merge(Object, Object, BiFunction)} 2239 | * @return a {@code SortedMap} whose keys and values are identical 2240 | * to the entries of this stream with any collisions 2241 | * handled 2242 | * 2243 | * @see #toMap() 2244 | * @see #toSortedMap() 2245 | * @see #toConcurrentMap(BinaryOperator) 2246 | */ 2247 | public SortedMap toSortedMap(Comparator keyComparator, BinaryOperator mergeFunction) { 2248 | return inner.collect(Collectors.toMap( 2249 | Map.Entry::getKey, 2250 | Map.Entry::getValue, 2251 | mergeFunction, 2252 | () -> new TreeMap<>(keyComparator) 2253 | )); 2254 | } 2255 | 2256 | /** 2257 | * Accumulates all key-value pairs of this {@code MapStream} into a 2258 | * {@code ConcurrentNavigableMap}. 2259 | *

2260 | * If the mapped keys contains duplicates (according to 2261 | * {@link Object#equals(Object)}), an {@code IllegalStateException} is 2262 | * thrown when the collection operation is performed. If the mapped keys 2263 | * may have duplicates, use {@link #toConcurrentNavigableMap(BinaryOperator)} 2264 | * instead. 2265 | *

2266 | * If the keys are not {@link Comparable}, a 2267 | * {@code java.lang.ClassCastException} may be thrown when the terminal 2268 | * operation is executed. It is therefore better to use 2269 | * {@link #toConcurrentNavigableMapByKey(Comparator)} since it allows you to specify 2270 | * a comparator to use when comparing the keys. 2271 | * 2272 | * @return a {@code ConcurrentNavigableMap} whose keys and values are 2273 | * identical to the entries of this stream 2274 | * 2275 | * @see #toMap(BinaryOperator) 2276 | * @see #toConcurrentMap() 2277 | */ 2278 | public ConcurrentNavigableMap toConcurrentNavigableMap() { 2279 | return inner.collect(Collectors.toConcurrentMap( 2280 | Map.Entry::getKey, 2281 | Map.Entry::getValue, 2282 | throwingMerger(), 2283 | ConcurrentSkipListMap::new 2284 | )); 2285 | } 2286 | 2287 | /** 2288 | * Accumulates all key-value pairs of this {@code MapStream} into a 2289 | * {@code ConcurrentNavigableMap}, sorting the entries by applying the 2290 | * specified comparator to the keys of the stream. 2291 | *

2292 | * If the mapped keys contains duplicates (according to 2293 | * {@link Object#equals(Object)}), an {@code IllegalStateException} is 2294 | * thrown when the collection operation is performed. If the mapped keys 2295 | * may have duplicates, use {@link #toConcurrentNavigableMap(Comparator, BinaryOperator)} 2296 | * instead. 2297 | * 2298 | * @param keyComparator the comparator to use when sorting the keys 2299 | * @return a {@code ConcurrentNavigableMap} whose keys and 2300 | * values are identical to the entries of this stream 2301 | * 2302 | * @see #toMap(BinaryOperator) 2303 | * @see #toConcurrentMap() 2304 | * @see #toSortedMap() 2305 | */ 2306 | public ConcurrentNavigableMap toConcurrentNavigableMapByKey(Comparator keyComparator) { 2307 | return inner.collect(Collectors.toConcurrentMap( 2308 | Map.Entry::getKey, 2309 | Map.Entry::getValue, 2310 | throwingMerger(), 2311 | () -> new ConcurrentSkipListMap<>(keyComparator) 2312 | )); 2313 | } 2314 | 2315 | /** 2316 | * Accumulates all key-value pairs of this {@code MapStream} into a 2317 | * {@code ConcurrentNavigableMap}. 2318 | *

2319 | * If the mapped keys contains duplicates (according to 2320 | * {@link Object#equals(Object)}), the values are merged using the provided 2321 | * merging function. 2322 | * 2323 | *

2324 | * There are multiple ways to deal with collisions between multiple elements 2325 | * mapping to the same key. The other forms of {@code toConcurrentNavigableMap} simply 2326 | * use a merge function that throws unconditionally, but you can easily 2327 | * write more flexible merge policies. 2328 | * 2329 | * @param mergeFunction a merge function, used to resolve collisions 2330 | * between values associated with the same key, as 2331 | * supplied to {@link Map#merge(Object, Object, BiFunction)} 2332 | * @return a {@code ConcurrentNavigableMap} whose keys and 2333 | * values are identical to the entries of this stream 2334 | * with any collisions handled 2335 | * 2336 | * @see #toMap() 2337 | * @see #toSortedMap() 2338 | * @see #toConcurrentMap(BinaryOperator) 2339 | */ 2340 | public ConcurrentNavigableMap toConcurrentNavigableMap(BinaryOperator mergeFunction) { 2341 | return inner.collect(Collectors.toConcurrentMap( 2342 | Map.Entry::getKey, 2343 | Map.Entry::getValue, 2344 | mergeFunction, 2345 | ConcurrentSkipListMap::new 2346 | )); 2347 | } 2348 | 2349 | /** 2350 | * Accumulates all key-value pairs of this {@code MapStream} into a 2351 | * {@code ConcurrentNavigableMap}, sorting the entries by applying the 2352 | * specified comparator to the keys of the stream. 2353 | *

2354 | * If the mapped keys contains duplicates (according to 2355 | * {@link Object#equals(Object)}), the values are merged using the provided 2356 | * merging function. 2357 | * 2358 | *

2359 | * There are multiple ways to deal with collisions between multiple elements 2360 | * mapping to the same key. The other forms of 2361 | * {@code toConcurrentNavigableMap} simply use a merge function that throws 2362 | * unconditionally, but you can easily write more flexible merge policies. 2363 | * 2364 | * @param keyComparator the comparator to use for determining the order of 2365 | * the keys 2366 | * @param mergeFunction a merge function, used to resolve collisions 2367 | * between values associated with the same key, as 2368 | * supplied to {@link Map#merge(Object, Object, BiFunction)} 2369 | * @return a {@code ConcurrentNavigableMap} whose keys and 2370 | * values are identical to the entries of this stream 2371 | * with any collisions handled 2372 | * 2373 | * @see #toMap() 2374 | * @see #toSortedMap() 2375 | * @see #toConcurrentMap(BinaryOperator) 2376 | */ 2377 | public ConcurrentNavigableMap toConcurrentNavigableMap(Comparator keyComparator, BinaryOperator mergeFunction) { 2378 | return inner.collect(Collectors.toConcurrentMap( 2379 | Map.Entry::getKey, 2380 | Map.Entry::getValue, 2381 | mergeFunction, 2382 | () -> new ConcurrentSkipListMap<>(keyComparator) 2383 | )); 2384 | } 2385 | 2386 | /** 2387 | * Accumulates all entries of this {@code MapStream} into a {@code List}. 2388 | * 2389 | *

2390 | * The returned {@code List} is not concurrent. 2391 | * 2392 | * @return a {@code List} that contains all the entities of the stream 2393 | */ 2394 | public List> toList() { 2395 | return inner.collect(Collectors.toList()); 2396 | } 2397 | 2398 | /** 2399 | * Utility method for creating a composed comparator that begins by 2400 | * comparing the first value and if it is equal, continues to the next one. 2401 | * 2402 | * @param the type of the key to compare 2403 | * @param methods methods for comparing the key ordered by priority 2404 | * @return a composite comparator that checks the key using the 2405 | * supplied methods in order 2406 | */ 2407 | @SuppressWarnings("varargs") 2408 | @SafeVarargs // Iterating over an array is safe. 2409 | public static Comparator comparing(Function>... methods) { 2410 | return (a, b) -> { 2411 | for (Function> method : methods) { 2412 | @SuppressWarnings(value = "unchecked") 2413 | final Function> m 2414 | = (Function>) method; 2415 | 2416 | final Comparable ac = m.apply(a); 2417 | final Comparable bc = m.apply(b); 2418 | final int c = ac.compareTo(bc); 2419 | 2420 | if (c != 0) { 2421 | return c; 2422 | } 2423 | } 2424 | 2425 | return 0; 2426 | }; 2427 | } 2428 | 2429 | private MapStream(Stream> inner) { 2430 | this.inner = inner; 2431 | } 2432 | 2433 | private static Comparator> byKeyOnly(Comparator comparator) { 2434 | return (a, b) -> comparator.compare(a.getKey(), b.getKey()); 2435 | } 2436 | 2437 | private static Comparator> byValueOnly(Comparator comparator) { 2438 | return (a, b) -> comparator.compare(a.getValue(), b.getValue()); 2439 | } 2440 | 2441 | /** 2442 | * Returns a merge function, suitable for use in 2443 | * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or 2444 | * {@link Collectors#toMap(Function, Function, BinaryOperator) toMap()}, 2445 | * which always throws {@code IllegalStateException}. This can be used to 2446 | * enforce the assumption that the elements being collected are distinct. 2447 | * 2448 | * @param the type of input arguments to the merge function 2449 | * @return a merge function which always throw 2450 | * {@code IllegalStateException} 2451 | */ 2452 | public static BinaryOperator throwingMerger() { 2453 | return (u, v) -> { 2454 | throw new IllegalStateException(String.format("Duplicate key %s", u)); 2455 | }; 2456 | } 2457 | } -------------------------------------------------------------------------------- /src/main/java/com/speedment/util/CollectorUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2006-2016, Speedment, Inc. All Rights Reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); You may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | package com.speedment.util; 18 | 19 | import com.speedment.annotation.Api; 20 | import com.speedment.stream.MapStream; 21 | import java.util.ArrayList; 22 | import java.util.Collections; 23 | import java.util.HashMap; 24 | import java.util.List; 25 | import java.util.Map; 26 | import java.util.Set; 27 | import java.util.function.BiConsumer; 28 | import java.util.function.BinaryOperator; 29 | import java.util.function.Function; 30 | import java.util.function.Supplier; 31 | import java.util.stream.Collector; 32 | import static com.speedment.util.StaticClassUtil.instanceNotAllowed; 33 | 34 | /** 35 | * Utility methods for collecting Speedment streams in various ways. 36 | * 37 | * @author pemi 38 | * @author Emil Forslund 39 | * @since 2.1 40 | */ 41 | @Api(version = "2.2") 42 | public final class CollectorUtil { 43 | 44 | /** 45 | * Returns a new {@link MapStream} where the elements have been grouped together using 46 | * the specified function. 47 | * 48 | * @param the stream element type 49 | * @param the type of the key to group by 50 | * @param grouper the function to use for grouping 51 | * @return a {@link MapStream} grouped by key 52 | */ 53 | public static Collector>> groupBy(Function grouper) { 54 | return new CollectorImpl<>( 55 | () -> new GroupHolder<>(grouper), 56 | GroupHolder::add, 57 | GroupHolder::merge, 58 | GroupHolder::finisher, 59 | Collections.emptySet() 60 | ); 61 | } 62 | 63 | private static class GroupHolder { 64 | 65 | private final Function grouper; 66 | private final Map> elements; 67 | 68 | private final Function> createList = c -> new ArrayList<>(); 69 | 70 | public GroupHolder(Function grouper) { 71 | this.grouper = grouper; 72 | this.elements = new HashMap<>(); 73 | } 74 | 75 | public void add(T element) { 76 | final C key = grouper.apply(element); 77 | elements.computeIfAbsent(key, createList) 78 | .add(element); 79 | } 80 | 81 | public GroupHolder merge(GroupHolder holder) { 82 | holder.elements.entrySet().stream() 83 | .forEach(e 84 | -> elements.computeIfAbsent(e.getKey(), createList) 85 | .addAll(e.getValue()) 86 | ); 87 | 88 | return this; 89 | } 90 | 91 | public MapStream> finisher() { 92 | return MapStream.of(elements); 93 | } 94 | } 95 | 96 | /** 97 | * Simple implementation class for {@code Collector}. 98 | * 99 | * @param the type of elements to be collected 100 | * @param the type of the intermediate holder 101 | * @param the type of the result 102 | */ 103 | static class CollectorImpl implements Collector { 104 | 105 | private final Supplier supplier; 106 | private final BiConsumer accumulator; 107 | private final BinaryOperator combiner; 108 | private final Function finisher; 109 | private final Set characteristics; 110 | 111 | CollectorImpl(Supplier supplier, 112 | BiConsumer accumulator, 113 | BinaryOperator combiner, 114 | Function finisher, 115 | Set characteristics) { 116 | this.supplier = supplier; 117 | this.accumulator = accumulator; 118 | this.combiner = combiner; 119 | this.finisher = finisher; 120 | this.characteristics = characteristics; 121 | } 122 | 123 | @SuppressWarnings("unchecked") 124 | CollectorImpl(Supplier supplier, 125 | BiConsumer accumulator, 126 | BinaryOperator combiner, 127 | Set characteristics) { 128 | 129 | this(supplier, accumulator, combiner, i -> (R) i, characteristics); 130 | } 131 | 132 | @Override 133 | public BiConsumer accumulator() { 134 | return accumulator; 135 | } 136 | 137 | @Override 138 | public Supplier supplier() { 139 | return supplier; 140 | } 141 | 142 | @Override 143 | public BinaryOperator combiner() { 144 | return combiner; 145 | } 146 | 147 | @Override 148 | public Function finisher() { 149 | return finisher; 150 | } 151 | 152 | @Override 153 | public Set characteristics() { 154 | return characteristics; 155 | } 156 | } 157 | 158 | /** 159 | * Utility classes should not be instantiated. 160 | */ 161 | private CollectorUtil() { 162 | instanceNotAllowed(getClass()); 163 | } 164 | } -------------------------------------------------------------------------------- /src/main/java/com/speedment/util/StaticClassUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2006-2016, Speedment, Inc. All Rights Reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); You may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | package com.speedment.util; 18 | 19 | import com.speedment.annotation.Api; 20 | 21 | /** 22 | * Support class for classes that only contains static methods and fields. 23 | * This interface can for example be used for various "Util" classes. 24 | * 25 | * @author pemi 26 | */ 27 | @Api(version = "2.2") 28 | public final class StaticClassUtil { 29 | 30 | /** 31 | * Support method that can be used in constructors to throw an 32 | * {@code UnsupportedOperationException} if someone is trying to create an 33 | * instance of the class. 34 | * 35 | * @param caller the class of the instance that called this method 36 | */ 37 | public static void instanceNotAllowed(Class caller) throws UnsupportedOperationException { 38 | throw new UnsupportedOperationException( 39 | "It is not allowed to create instances of the " + 40 | caller.getName() + 41 | " class." 42 | ); 43 | } 44 | 45 | /** 46 | * Utility classes should not be instantiated. 47 | */ 48 | private StaticClassUtil() { instanceNotAllowed(getClass()); } 49 | } --------------------------------------------------------------------------------