1/* 2 * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23package org.graalvm.util; 24 25import java.util.ArrayList; 26import java.util.Arrays; 27import java.util.Collection; 28import java.util.Collections; 29import java.util.Iterator; 30import java.util.List; 31import java.util.Objects; 32import java.util.function.Function; 33import java.util.function.IntFunction; 34import java.util.function.Predicate; 35import java.util.function.Supplier; 36 37/** 38 * This class contains utility methods for commonly used functional patterns for collections. 39 */ 40public class CollectionsUtil { 41 42 /** 43 * Concatenates two iterables into a single iterable. The iterator exposed by the returned 44 * iterable does not support {@link Iterator#remove()} even if the input iterables do. 45 * 46 * @throws NullPointerException if {@code a} or {@code b} is {@code null} 47 */ 48 public static <T> Iterable<T> concat(Iterable<T> a, Iterable<T> b) { 49 List<Iterable<T>> l = Arrays.asList(a, b); 50 return concat(l); 51 } 52 53 /** 54 * Concatenates multiple iterables into a single iterable. The iterator exposed by the returned 55 * iterable does not support {@link Iterator#remove()} even if the input iterables do. 56 * 57 * @throws NullPointerException if {@code iterables} or any of its elements are {@code null} 58 */ 59 public static <T> Iterable<T> concat(List<Iterable<T>> iterables) { 60 for (Iterable<T> iterable : iterables) { 61 Objects.requireNonNull(iterable); 62 } 63 return new Iterable<T>() { 64 @Override 65 public Iterator<T> iterator() { 66 if (iterables.size() == 0) { 67 return Collections.emptyIterator(); 68 } 69 return new Iterator<T>() { 70 Iterator<Iterable<T>> cursor = iterables.iterator(); 71 Iterator<T> currentIterator = cursor.next().iterator(); 72 73 private void advance() { 74 while (!currentIterator.hasNext() && cursor.hasNext()) { 75 currentIterator = cursor.next().iterator(); 76 } 77 } 78 79 @Override 80 public boolean hasNext() { 81 advance(); 82 return currentIterator.hasNext(); 83 } 84 85 @Override 86 public T next() { 87 advance(); 88 return currentIterator.next(); 89 } 90 }; 91 } 92 93 }; 94 } 95 96 public static <T> boolean allMatch(T[] inputs, Predicate<T> predicate) { 97 return allMatch(Arrays.asList(inputs), predicate); 98 } 99 100 public static <T> boolean allMatch(Iterable<T> inputs, Predicate<T> predicate) { 101 for (T t : inputs) { 102 if (!predicate.test(t)) { 103 return false; 104 } 105 } 106 return true; 107 } 108 109 public static <T> boolean anyMatch(T[] inputs, Predicate<T> predicate) { 110 return anyMatch(Arrays.asList(inputs), predicate); 111 } 112 113 public static <T> boolean anyMatch(Iterable<T> inputs, Predicate<T> predicate) { 114 for (T t : inputs) { 115 if (predicate.test(t)) { 116 return true; 117 } 118 } 119 return false; 120 } 121 122 public static <T> List<T> filterToList(List<T> inputs, Predicate<? super T> predicate) { 123 return filterToList(inputs, predicate, ArrayList::new); 124 } 125 126 public static <T> List<T> filterToList(List<T> inputs, Predicate<? super T> predicate, Supplier<List<T>> listGenerator) { 127 List<T> resultList = listGenerator.get(); 128 for (T t : inputs) { 129 if (predicate.test(t)) { 130 resultList.add(t); 131 } 132 } 133 return resultList; 134 } 135 136 /** 137 * Filters the inputs, maps them given the mapping function and adds them in the array provided 138 * by the generator. 139 */ 140 public static <T, R> R[] filterAndMapToArray(T[] inputs, Predicate<? super T> predicate, Function<? super T, ? extends R> mapper, IntFunction<R[]> arrayGenerator) { 141 List<R> resultList = new ArrayList<>(); 142 for (T t : inputs) { 143 if (predicate.test(t)) { 144 resultList.add(mapper.apply(t)); 145 } 146 } 147 return resultList.toArray(arrayGenerator.apply(resultList.size())); 148 } 149 150 /** 151 * Maps the inputs given the mapping function and adds them in the array provided by the 152 * generator. 153 */ 154 public static <T, R> R[] mapToArray(T[] inputs, Function<? super T, ? extends R> mapper, IntFunction<R[]> arrayGenerator) { 155 return mapToArray(Arrays.asList(inputs), mapper, arrayGenerator); 156 } 157 158 public static <T, R> R[] mapToArray(Collection<T> inputs, Function<? super T, ? extends R> mapper, IntFunction<R[]> arrayGenerator) { 159 R[] result = arrayGenerator.apply(inputs.size()); 160 int idx = 0; 161 for (T t : inputs) { 162 result[idx++] = mapper.apply(t); 163 } 164 return result; 165 } 166 167 public static <T, R> String mapAndJoin(T[] inputs, Function<? super T, ? extends R> mapper, String delimiter) { 168 return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, "", ""); 169 } 170 171 public static <T, R> String mapAndJoin(T[] inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix) { 172 return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, prefix, ""); 173 } 174 175 public static <T, R> String mapAndJoin(T[] inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix, String suffix) { 176 return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, prefix, suffix); 177 } 178 179 public static <T, R> String mapAndJoin(Iterable<T> inputs, Function<? super T, ? extends R> mapper, String delimiter) { 180 return mapAndJoin(inputs, mapper, delimiter, "", ""); 181 } 182 183 public static <T, R> String mapAndJoin(Iterable<T> inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix) { 184 return mapAndJoin(inputs, mapper, delimiter, prefix, ""); 185 } 186 187 public static <T, R> String mapAndJoin(Iterable<T> inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix, String suffix) { 188 StringBuilder strb = new StringBuilder(); 189 String sep = ""; 190 for (T t : inputs) { 191 strb.append(sep).append(prefix).append(mapper.apply(t)).append(suffix); 192 sep = delimiter; 193 } 194 return strb.toString(); 195 } 196} 197