• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

javadev / underscore-java / #3262

pending completion
#3262

push

web-flow
Improved tests

4359 of 4359 relevant lines covered (100.0%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/main/java/com/github/underscore/Underscore.java
1
/*
2
 * The MIT License (MIT)
3
 *
4
 * Copyright 2015-2023 Valentyn Kolesnikov
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
package com.github.underscore;
25

26
import java.lang.reflect.Field;
27
import java.lang.reflect.Method;
28
import java.util.ArrayDeque;
29
import java.util.ArrayList;
30
import java.util.Arrays;
31
import java.util.Collection;
32
import java.util.Collections;
33
import java.util.Comparator;
34
import java.util.Date;
35
import java.util.Deque;
36
import java.util.HashMap;
37
import java.util.Iterator;
38
import java.util.LinkedHashMap;
39
import java.util.LinkedHashSet;
40
import java.util.List;
41
import java.util.ListIterator;
42
import java.util.Map;
43
import java.util.Objects;
44
import java.util.Set;
45
import java.util.UUID;
46
import java.util.function.BiConsumer;
47
import java.util.function.BiFunction;
48
import java.util.function.BinaryOperator;
49
import java.util.function.Consumer;
50
import java.util.function.Function;
51
import java.util.function.Predicate;
52
import java.util.function.Supplier;
53
import java.util.function.UnaryOperator;
54

55
/**
56
 * Underscore-java is a java port of Underscore.js.
57
 *
58
 * @author Valentyn Kolesnikov
59
 */
60
@SuppressWarnings({"java:S106", "java:S2189", "java:S2272", "java:S3740", "java:S5852"})
61
public class Underscore<T> {
62
    private static final Map<String, Function<String, String>> FUNCTIONS = newLinkedHashMap();
1✔
63
    private static final Map<String, String> TEMPLATE_SETTINGS = new HashMap<>();
1✔
64
    private static final int MIN_PASSWORD_LENGTH_8 = 8;
65
    private static final long CAPACITY_SIZE_5 = 5L;
66
    private static final long CAPACITY_COEFF_2 = 2L;
67
    private static final long CAPACITY_SIZE_16 = 16L;
68
    private static final java.util.concurrent.atomic.AtomicInteger UNIQUE_ID =
1✔
69
            new java.util.concurrent.atomic.AtomicInteger(0);
70
    private static final String ALL_SYMBOLS = "([\\s\\S]+?)";
71
    private static final String EVALUATE = "evaluate";
72
    private static final String INTERPOLATE = "interpolate";
73
    private static final String ESCAPE = "escape";
74
    private static final String S_Q = "\\s*\\Q";
75
    private static final String E_S = "\\E\\s*";
76
    private static final java.util.regex.Pattern FORMAT_PATTERN =
1✔
77
            java.util.regex.Pattern.compile("\\{\\s*(\\d*)\\s*\\}");
1✔
78
    private static final Map<Character, String> ESCAPES = new HashMap<>();
1✔
79
    private final Iterable<T> iterable;
80
    private final Optional<String> string;
81

82
    static {
83
        TEMPLATE_SETTINGS.put(EVALUATE, "<%([\\s\\S]+?)%>");
1✔
84
        TEMPLATE_SETTINGS.put(INTERPOLATE, "<%=([\\s\\S]+?)%>");
1✔
85
        TEMPLATE_SETTINGS.put(ESCAPE, "<%-([\\s\\S]+?)%>");
1✔
86
        ESCAPES.put('&', "&amp;");
1✔
87
        ESCAPES.put('<', "&lt;");
1✔
88
        ESCAPES.put('>', "&gt;");
1✔
89
        ESCAPES.put('"', "&quot;");
1✔
90
        ESCAPES.put('\'', "&#x27;");
1✔
91
        ESCAPES.put('`', "&#x60;");
1✔
92
    }
1✔
93

94
    public Underscore(final Iterable<T> iterable) {
1✔
95
        this.iterable = iterable;
1✔
96
        this.string = Optional.empty();
1✔
97
    }
1✔
98

99
    public Underscore(final String string) {
1✔
100
        this.iterable = null;
1✔
101
        this.string = Optional.of(string);
1✔
102
    }
1✔
103

104
    private static void setTemplateKey(
105
            final Map<String, String> templateSettings, final String key) {
106
        if (templateSettings.containsKey(key) && templateSettings.get(key).contains(ALL_SYMBOLS)) {
1✔
107
            TEMPLATE_SETTINGS.put(key, templateSettings.get(key));
1✔
108
        }
109
    }
1✔
110

111
    public static void templateSettings(final Map<String, String> templateSettings) {
112
        setTemplateKey(templateSettings, EVALUATE);
1✔
113
        setTemplateKey(templateSettings, INTERPOLATE);
1✔
114
        setTemplateKey(templateSettings, ESCAPE);
1✔
115
    }
1✔
116

117
    private static final class WherePredicate<E, T> implements Predicate<E> {
118
        private final List<Map.Entry<String, T>> properties;
119

120
        private WherePredicate(List<Map.Entry<String, T>> properties) {
1✔
121
            this.properties = properties;
1✔
122
        }
1✔
123

124
        @Override
125
        public boolean test(final E elem) {
126
            for (Map.Entry<String, T> prop : properties) {
1✔
127
                try {
128
                    if (!elem.getClass()
1✔
129
                            .getField(prop.getKey())
1✔
130
                            .get(elem)
1✔
131
                            .equals(prop.getValue())) {
1✔
132
                        return false;
1✔
133
                    }
134
                } catch (Exception ex) {
1✔
135
                    try {
136
                        if (!elem.getClass()
1✔
137
                                .getMethod(prop.getKey())
1✔
138
                                .invoke(elem)
1✔
139
                                .equals(prop.getValue())) {
1✔
140
                            return false;
1✔
141
                        }
142
                    } catch (Exception ignored) {
1✔
143
                        // ignored
144
                    }
1✔
145
                }
1✔
146
            }
1✔
147
            return true;
1✔
148
        }
149
    }
150

151
    private static final class TemplateImpl<K, V> implements Template<Map<K, V>> {
152
        private final String template;
153

154
        private TemplateImpl(String template) {
1✔
155
            this.template = template;
1✔
156
        }
1✔
157

158
        @Override
159
        public String apply(Map<K, V> value) {
160
            final String evaluate = TEMPLATE_SETTINGS.get(EVALUATE);
1✔
161
            final String interpolate = TEMPLATE_SETTINGS.get(INTERPOLATE);
1✔
162
            final String escape = TEMPLATE_SETTINGS.get(ESCAPE);
1✔
163
            String result = template;
1✔
164
            for (final Map.Entry<K, V> element : value.entrySet()) {
1✔
165
                final String value1 =
1✔
166
                        String.valueOf(element.getValue())
1✔
167
                                .replace("\\", "\\\\")
1✔
168
                                .replace("$", "\\$");
1✔
169
                result =
1✔
170
                        java.util.regex.Pattern.compile(
1✔
171
                                        interpolate.replace(
1✔
172
                                                ALL_SYMBOLS, S_Q + element.getKey() + E_S))
1✔
173
                                .matcher(result)
1✔
174
                                .replaceAll(value1);
1✔
175
                result =
1✔
176
                        java.util.regex.Pattern.compile(
1✔
177
                                        escape.replace(ALL_SYMBOLS, S_Q + element.getKey() + E_S))
1✔
178
                                .matcher(result)
1✔
179
                                .replaceAll(escape(value1));
1✔
180
                result =
1✔
181
                        java.util.regex.Pattern.compile(
1✔
182
                                        evaluate.replace(ALL_SYMBOLS, S_Q + element.getKey() + E_S))
1✔
183
                                .matcher(result)
1✔
184
                                .replaceAll(value1);
1✔
185
            }
1✔
186
            return result;
1✔
187
        }
188

189
        @Override
190
        public List<String> check(Map<K, V> value) {
191
            final String evaluate = TEMPLATE_SETTINGS.get(EVALUATE);
1✔
192
            final String interpolate = TEMPLATE_SETTINGS.get(INTERPOLATE);
1✔
193
            final String escape = TEMPLATE_SETTINGS.get(ESCAPE);
1✔
194
            String result = template;
1✔
195
            final List<String> notFound = new ArrayList<>();
1✔
196
            final List<String> valueKeys = new ArrayList<>();
1✔
197
            for (final Map.Entry<K, V> element : value.entrySet()) {
1✔
198
                final String key = "" + element.getKey();
1✔
199
                java.util.regex.Matcher matcher =
1✔
200
                        java.util.regex.Pattern.compile(
1✔
201
                                        interpolate.replace(ALL_SYMBOLS, S_Q + key + E_S))
1✔
202
                                .matcher(result);
1✔
203
                boolean isFound = matcher.find();
1✔
204
                result = matcher.replaceAll(String.valueOf(element.getValue()));
1✔
205
                matcher =
1✔
206
                        java.util.regex.Pattern.compile(
1✔
207
                                        escape.replace(ALL_SYMBOLS, S_Q + key + E_S))
1✔
208
                                .matcher(result);
1✔
209
                isFound |= matcher.find();
1✔
210
                result = matcher.replaceAll(escape(String.valueOf(element.getValue())));
1✔
211
                matcher =
1✔
212
                        java.util.regex.Pattern.compile(
1✔
213
                                        evaluate.replace(ALL_SYMBOLS, S_Q + key + E_S))
1✔
214
                                .matcher(result);
1✔
215
                isFound |= matcher.find();
1✔
216
                result = matcher.replaceAll(String.valueOf(element.getValue()));
1✔
217
                if (!isFound) {
1✔
218
                    notFound.add(key);
1✔
219
                }
220
                valueKeys.add(key);
1✔
221
            }
1✔
222
            final List<String> templateVars = new ArrayList<>();
1✔
223
            java.util.regex.Matcher matcher =
1✔
224
                    java.util.regex.Pattern.compile(interpolate).matcher(result);
1✔
225
            while (matcher.find()) {
1✔
226
                templateVars.add(matcher.group(1).trim());
1✔
227
            }
228
            result = matcher.replaceAll("");
1✔
229
            matcher = java.util.regex.Pattern.compile(escape).matcher(result);
1✔
230
            while (matcher.find()) {
1✔
231
                templateVars.add(matcher.group(1).trim());
1✔
232
            }
233
            result = matcher.replaceAll("");
1✔
234
            matcher = java.util.regex.Pattern.compile(evaluate).matcher(result);
1✔
235
            while (matcher.find()) {
1✔
236
                templateVars.add(matcher.group(1).trim());
1✔
237
            }
238
            notFound.addAll(difference(templateVars, valueKeys));
1✔
239
            return notFound;
1✔
240
        }
241
    }
242

243
    private static final class MyIterable<T> implements Iterable<T> {
244
        private final UnaryOperator<T> unaryOperator;
245
        private boolean firstRun = true;
1✔
246
        private T value;
247

248
        MyIterable(final T seed, final UnaryOperator<T> unaryOperator) {
1✔
249
            this.value = seed;
1✔
250
            this.unaryOperator = unaryOperator;
1✔
251
        }
1✔
252

253
        public Iterator<T> iterator() {
254
            return new Iterator<>() {
1✔
255
                @Override
256
                public boolean hasNext() {
257
                    return true;
1✔
258
                }
259

260
                @Override
261
                public T next() {
262
                    if (firstRun) {
1✔
263
                        firstRun = false;
1✔
264
                    } else {
265
                        value = unaryOperator.apply(value);
1✔
266
                    }
267
                    return value;
1✔
268
                }
269

270
                @Override
271
                public void remove() {
272
                    // ignored
273
                }
1✔
274
            };
275
        }
276
    }
277

278
    public static <K, V> Function<Map<K, V>, V> iteratee(final K key) {
279
        return item -> item.get(key);
1✔
280
    }
281

282
    /*
283
     * Documented, #each
284
     */
285
    public static <T> void each(final Iterable<T> iterable, final Consumer<? super T> func) {
286
        for (T element : iterable) {
1✔
287
            func.accept(element);
1✔
288
        }
1✔
289
    }
1✔
290

291
    public static <T> void eachIndexed(
292
            final Iterable<T> iterable, final BiConsumer<Integer, ? super T> func) {
293
        int index = 0;
1✔
294
        for (T element : iterable) {
1✔
295
            func.accept(index, element);
1✔
296
            index += 1;
1✔
297
        }
1✔
298
    }
1✔
299

300
    public void each(final Consumer<? super T> func) {
301
        each(iterable, func);
1✔
302
    }
1✔
303

304
    public static <T> void eachRight(final Iterable<T> iterable, final Consumer<? super T> func) {
305
        each(reverse(iterable), func);
1✔
306
    }
1✔
307

308
    public void eachRight(final Consumer<? super T> func) {
309
        eachRight(iterable, func);
1✔
310
    }
1✔
311

312
    public static <T> void forEach(final Iterable<T> iterable, final Consumer<? super T> func) {
313
        each(iterable, func);
1✔
314
    }
1✔
315

316
    public static <T> void forEachIndexed(
317
            final Iterable<T> iterable, final BiConsumer<Integer, ? super T> func) {
318
        eachIndexed(iterable, func);
1✔
319
    }
1✔
320

321
    public void forEach(final Consumer<? super T> func) {
322
        each(iterable, func);
1✔
323
    }
1✔
324

325
    public void forEachIndexed(final BiConsumer<Integer, ? super T> func) {
326
        eachIndexed(iterable, func);
1✔
327
    }
1✔
328

329
    public static <T> void forEachRight(
330
            final Iterable<T> iterable, final Consumer<? super T> func) {
331
        eachRight(iterable, func);
1✔
332
    }
1✔
333

334
    public void forEachRight(final Consumer<? super T> func) {
335
        eachRight(iterable, func);
1✔
336
    }
1✔
337

338
    /*
339
     * Documented, #map
340
     */
341
    public static <T, E> List<T> map(final List<E> list, final Function<? super E, T> func) {
342
        final List<T> transformed = newArrayListWithExpectedSize(list.size());
1✔
343
        for (E element : list) {
1✔
344
            transformed.add(func.apply(element));
1✔
345
        }
1✔
346
        return transformed;
1✔
347
    }
348

349
    public static <T, E> List<T> mapMulti(
350
            final List<E> list, final BiConsumer<? super E, ? super Consumer<T>> mapper) {
351
        final List<T> transformed = newArrayListWithExpectedSize(list.size());
1✔
352
        for (E element : list) {
1✔
353
            Consumer<T> value = transformed::add;
1✔
354
            mapper.accept(element, value);
1✔
355
        }
1✔
356
        return transformed;
1✔
357
    }
358

359
    public <F> List<F> map(final Function<? super T, F> func) {
360
        return map(newArrayList(iterable), func);
1✔
361
    }
362

363
    public static <T> List<T> map(final int[] array, final Function<? super Integer, T> func) {
364
        final List<T> transformed = newArrayListWithExpectedSize(array.length);
1✔
365
        for (int element : array) {
1✔
366
            transformed.add(func.apply(element));
1✔
367
        }
368
        return transformed;
1✔
369
    }
370

371
    public static <T, E> Set<T> map(final Set<E> set, final Function<? super E, T> func) {
372
        final Set<T> transformed = newLinkedHashSetWithExpectedSize(set.size());
1✔
373
        for (E element : set) {
1✔
374
            transformed.add(func.apply(element));
1✔
375
        }
1✔
376
        return transformed;
1✔
377
    }
378

379
    public static <T, E> List<T> mapIndexed(
380
            final List<E> list, final BiFunction<Integer, ? super E, T> func) {
381
        final List<T> transformed = newArrayListWithExpectedSize(list.size());
1✔
382
        int index = 0;
1✔
383
        for (E element : list) {
1✔
384
            transformed.add(func.apply(index, element));
1✔
385
            index += 1;
1✔
386
        }
1✔
387
        return transformed;
1✔
388
    }
389

390
    public static <T> List<T> replace(
391
            final Iterable<T> iter, final Predicate<T> pred, final T value) {
392
        List<T> list = newArrayList(iter);
1✔
393
        if (pred == null) {
1✔
394
            return list;
1✔
395
        }
396
        ListIterator<T> itera = list.listIterator();
1✔
397
        while (itera.hasNext()) {
1✔
398
            if (pred.test(itera.next())) {
1✔
399
                itera.set(value);
1✔
400
            }
401
        }
402
        return list;
1✔
403
    }
404

405
    public List<T> replace(final Predicate<T> pred, final T value) {
406
        return replace(value(), pred, value);
1✔
407
    }
408

409
    public static <T> List<T> replaceIndexed(
410
            final Iterable<T> iter, final PredicateIndexed<T> pred, final T value) {
411
        List<T> list = newArrayList(iter);
1✔
412
        if (pred == null) {
1✔
413
            return list;
1✔
414
        }
415
        ListIterator<T> itera = list.listIterator();
1✔
416
        int index = 0;
1✔
417
        while (itera.hasNext()) {
1✔
418
            if (pred.test(index, itera.next())) {
1✔
419
                itera.set(value);
1✔
420
            }
421
            index++;
1✔
422
        }
423
        return list;
1✔
424
    }
425

426
    public List<T> replaceIndexed(final PredicateIndexed<T> pred, final T value) {
427
        return replaceIndexed(value(), pred, value);
1✔
428
    }
429

430
    public <F> List<F> mapIndexed(final BiFunction<Integer, ? super T, F> func) {
431
        return mapIndexed(newArrayList(iterable), func);
1✔
432
    }
433

434
    public static <T, E> List<T> collect(final List<E> list, final Function<? super E, T> func) {
435
        return map(list, func);
1✔
436
    }
437

438
    public static <T, E> Set<T> collect(final Set<E> set, final Function<? super E, T> func) {
439
        return map(set, func);
1✔
440
    }
441

442
    /*
443
     * Documented, #reduce
444
     */
445
    public static <T, E> E reduce(
446
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
447
        E accum = zeroElem;
1✔
448
        for (T element : iterable) {
1✔
449
            accum = func.apply(accum, element);
1✔
450
        }
1✔
451
        return accum;
1✔
452
    }
453

454
    public static <T> Optional<T> reduce(final Iterable<T> iterable, final BinaryOperator<T> func) {
455
        boolean foundAny = false;
1✔
456
        T accum = null;
1✔
457
        for (T element : iterable) {
1✔
458
            if (foundAny) {
1✔
459
                accum = func.apply(accum, element);
1✔
460
            } else {
461
                foundAny = true;
1✔
462
                accum = element;
1✔
463
            }
464
        }
1✔
465
        return foundAny ? Optional.of(accum) : Optional.empty();
1✔
466
    }
467

468
    public static <E> E reduce(
469
            final int[] array, final BiFunction<E, ? super Integer, E> func, final E zeroElem) {
470
        E accum = zeroElem;
1✔
471
        for (int element : array) {
1✔
472
            accum = func.apply(accum, element);
1✔
473
        }
474
        return accum;
1✔
475
    }
476

477
    public static <T, E> E reduce(
478
            final T[] array, final BiFunction<E, T, E> func, final E zeroElem) {
479
        E accum = zeroElem;
1✔
480
        for (T element : array) {
1✔
481
            accum = func.apply(accum, element);
1✔
482
        }
483
        return accum;
1✔
484
    }
485

486
    public static <T, E> E foldl(
487
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
488
        return reduce(iterable, func, zeroElem);
1✔
489
    }
490

491
    public static <T, E> E inject(
492
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
493
        return reduce(iterable, func, zeroElem);
1✔
494
    }
495

496
    /*
497
     * Documented, #reduceRight
498
     */
499
    public static <T, E> E reduceRight(
500
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
501
        return reduce(reverse(iterable), func, zeroElem);
1✔
502
    }
503

504
    public static <T> Optional<T> reduceRight(
505
            final Iterable<T> iterable, final BinaryOperator<T> func) {
506
        return reduce(reverse(iterable), func);
1✔
507
    }
508

509
    public static <E> E reduceRight(
510
            final int[] array, final BiFunction<E, ? super Integer, E> func, final E zeroElem) {
511
        E accum = zeroElem;
1✔
512
        for (Integer element : reverse(array)) {
1✔
513
            accum = func.apply(accum, element);
1✔
514
        }
1✔
515
        return accum;
1✔
516
    }
517

518
    public static <T, E> E reduceRight(
519
            final T[] array, final BiFunction<E, T, E> func, final E zeroElem) {
520
        return reduce(reverse(array), func, zeroElem);
1✔
521
    }
522

523
    public static <T, E> E foldr(
524
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
525
        return reduceRight(iterable, func, zeroElem);
1✔
526
    }
527

528
    /*
529
     * Documented, #find
530
     */
531
    public static <E> Optional<E> find(final Iterable<E> iterable, final Predicate<E> pred) {
532
        for (E element : iterable) {
1✔
533
            if (pred.test(element)) {
1✔
534
                return Optional.of(element);
1✔
535
            }
536
        }
1✔
537
        return Optional.empty();
1✔
538
    }
539

540
    public static <E> Optional<E> detect(final Iterable<E> iterable, final Predicate<E> pred) {
541
        return find(iterable, pred);
1✔
542
    }
543

544
    public static <E> Optional<E> findLast(final Iterable<E> iterable, final Predicate<E> pred) {
545
        return find(reverse(iterable), pred);
1✔
546
    }
547

548
    /*
549
     * Documented, #filter
550
     */
551
    public static <E> List<E> filter(final Iterable<E> iterable, final Predicate<E> pred) {
552
        final List<E> filtered = newArrayList();
1✔
553
        for (E element : iterable) {
1✔
554
            if (pred.test(element)) {
1✔
555
                filtered.add(element);
1✔
556
            }
557
        }
1✔
558
        return filtered;
1✔
559
    }
560

561
    public static <E> List<E> filter(final List<E> list, final Predicate<E> pred) {
562
        final List<E> filtered = newArrayList();
1✔
563
        for (E element : list) {
1✔
564
            if (pred.test(element)) {
1✔
565
                filtered.add(element);
1✔
566
            }
567
        }
1✔
568
        return filtered;
1✔
569
    }
570

571
    public List<T> filter(final Predicate<T> pred) {
572
        final List<T> filtered = newArrayList();
1✔
573
        for (final T element : value()) {
1✔
574
            if (pred.test(element)) {
1✔
575
                filtered.add(element);
1✔
576
            }
577
        }
1✔
578
        return filtered;
1✔
579
    }
580

581
    public static <E> List<E> filterIndexed(final List<E> list, final PredicateIndexed<E> pred) {
582
        final List<E> filtered = newArrayList();
1✔
583
        int index = 0;
1✔
584
        for (E element : list) {
1✔
585
            if (pred.test(index, element)) {
1✔
586
                filtered.add(element);
1✔
587
            }
588
            index += 1;
1✔
589
        }
1✔
590
        return filtered;
1✔
591
    }
592

593
    public static <E> Set<E> filter(final Set<E> set, final Predicate<E> pred) {
594
        final Set<E> filtered = newLinkedHashSet();
1✔
595
        for (E element : set) {
1✔
596
            if (pred.test(element)) {
1✔
597
                filtered.add(element);
1✔
598
            }
599
        }
1✔
600
        return filtered;
1✔
601
    }
602

603
    public static <E> List<E> select(final List<E> list, final Predicate<E> pred) {
604
        return filter(list, pred);
1✔
605
    }
606

607
    public static <E> Set<E> select(final Set<E> set, final Predicate<E> pred) {
608
        return filter(set, pred);
1✔
609
    }
610

611
    /*
612
     * Documented, #reject
613
     */
614
    public static <E> List<E> reject(final List<E> list, final Predicate<E> pred) {
615
        return filter(list, input -> !pred.test(input));
1✔
616
    }
617

618
    public List<T> reject(final Predicate<T> pred) {
619
        return filter(input -> !pred.test(input));
1✔
620
    }
621

622
    public static <E> List<E> rejectIndexed(final List<E> list, final PredicateIndexed<E> pred) {
623
        return filterIndexed(list, (index, input) -> !pred.test(index, input));
1✔
624
    }
625

626
    public static <E> Set<E> reject(final Set<E> set, final Predicate<E> pred) {
627
        return filter(set, input -> !pred.test(input));
1✔
628
    }
629

630
    public static <E> List<E> filterFalse(final List<E> list, final Predicate<E> pred) {
631
        return reject(list, pred);
1✔
632
    }
633

634
    public List<T> filterFalse(final Predicate<T> pred) {
635
        return reject(pred);
1✔
636
    }
637

638
    public static <E> Set<E> filterFalse(final Set<E> set, final Predicate<E> pred) {
639
        return reject(set, pred);
1✔
640
    }
641

642
    public static <E> boolean every(final Iterable<E> iterable, final Predicate<E> pred) {
643
        for (E item : iterable) {
1✔
644
            if (!pred.test(item)) {
1✔
645
                return false;
1✔
646
            }
647
        }
1✔
648
        return true;
1✔
649
    }
650

651
    public boolean every(final Predicate<T> pred) {
652
        return every(iterable, pred);
1✔
653
    }
654

655
    /*
656
     * Documented, #all
657
     */
658
    public static <E> boolean all(final Iterable<E> iterable, final Predicate<E> pred) {
659
        return every(iterable, pred);
1✔
660
    }
661

662
    public boolean all(final Predicate<T> pred) {
663
        return every(iterable, pred);
1✔
664
    }
665

666
    public static <E> boolean some(final Iterable<E> iterable, final Predicate<E> pred) {
667
        return find(iterable, pred).isPresent();
1✔
668
    }
669

670
    public boolean some(final Predicate<T> pred) {
671
        return some(iterable, pred);
1✔
672
    }
673

674
    /*
675
     * Documented, #any
676
     */
677
    public static <E> boolean any(final Iterable<E> iterable, final Predicate<E> pred) {
678
        return some(iterable, pred);
1✔
679
    }
680

681
    public boolean any(final Predicate<T> pred) {
682
        return some(iterable, pred);
1✔
683
    }
684

685
    public static <E> int count(final Iterable<E> iterable, final Predicate<E> pred) {
686
        int result = 0;
1✔
687
        for (E item : iterable) {
1✔
688
            if (pred.test(item)) {
1✔
689
                result += 1;
1✔
690
            }
691
        }
1✔
692
        return result;
1✔
693
    }
694

695
    public int count(final Predicate<T> pred) {
696
        return count(iterable, pred);
1✔
697
    }
698

699
    public static <E> boolean contains(final Iterable<E> iterable, final E elem) {
700
        return some(iterable, e -> Objects.equals(elem, e));
1✔
701
    }
702

703
    public boolean contains(final T elem) {
704
        return contains(iterable, elem);
1✔
705
    }
706

707
    public static <E> boolean containsWith(final Iterable<E> iterable, final E elem) {
708
        return some(
1✔
709
                iterable,
710
                e -> elem == null ? e == null : String.valueOf(e).contains(String.valueOf(elem)));
1✔
711
    }
712

713
    public boolean containsWith(final T elem) {
714
        return containsWith(iterable, elem);
1✔
715
    }
716

717
    public static <E> boolean contains(
718
            final Iterable<E> iterable, final E elem, final int fromIndex) {
719
        final List<E> list = newArrayList(iterable);
1✔
720
        return contains(list.subList(fromIndex, list.size()), elem);
1✔
721
    }
722

723
    public boolean containsAtLeast(final T value, final int count) {
724
        return Underscore.containsAtLeast(this.iterable, value, count);
1✔
725
    }
726

727
    public boolean containsAtMost(final T value, final int count) {
728
        return Underscore.containsAtMost(this.iterable, value, count);
1✔
729
    }
730

731
    public static <E> boolean containsAtLeast(
732
            final Iterable<E> iterable, final E value, final int count) {
733
        int foundItems = 0;
1✔
734
        for (E element : iterable) {
1✔
735
            if (Objects.equals(element, value)) {
1✔
736
                foundItems += 1;
1✔
737
            }
738
            if (foundItems >= count) {
1✔
739
                break;
1✔
740
            }
741
        }
1✔
742
        return foundItems >= count;
1✔
743
    }
744

745
    public static <E> boolean containsAtMost(
746
            final Iterable<E> iterable, final E value, final int count) {
747
        int foundItems = size(iterable);
1✔
748
        for (E element : iterable) {
1✔
749
            if (!(Objects.equals(element, value))) {
1✔
750
                foundItems -= 1;
1✔
751
            }
752
            if (foundItems <= count) {
1✔
753
                break;
1✔
754
            }
755
        }
1✔
756
        return foundItems <= count;
1✔
757
    }
758

759
    /*
760
     * Documented, #include
761
     */
762
    public static <E> boolean include(final Iterable<E> iterable, final E elem) {
763
        return contains(iterable, elem);
1✔
764
    }
765

766
    /*
767
     * Documented, #invoke
768
     */
769
    @SuppressWarnings("unchecked")
770
    public static <E> List<E> invoke(
771
            final Iterable<E> iterable, final String methodName, final List<Object> args) {
772
        final List<E> result = newArrayList();
1✔
773
        final List<Class<?>> argTypes = map(args, Object::getClass);
1✔
774
        try {
775
            final Method method =
1✔
776
                    iterable.iterator()
1✔
777
                            .next()
1✔
778
                            .getClass()
1✔
779
                            .getMethod(methodName, argTypes.toArray(new Class[0]));
1✔
780
            for (E arg : iterable) {
1✔
781
                doInvoke(args, result, method, arg);
1✔
782
            }
1✔
783
        } catch (NoSuchMethodException e) {
1✔
784
            throw new IllegalArgumentException(e);
1✔
785
        }
1✔
786
        return result;
1✔
787
    }
788

789
    @SuppressWarnings("unchecked")
790
    private static <E> void doInvoke(List<Object> args, List<E> result, Method method, E arg) {
791
        try {
792
            result.add((E) method.invoke(arg, args.toArray(new Object[0])));
1✔
793
        } catch (Exception e) {
1✔
794
            throw new IllegalArgumentException(e);
1✔
795
        }
1✔
796
    }
1✔
797

798
    public List<T> invoke(final String methodName, final List<Object> args) {
799
        return invoke(iterable, methodName, args);
1✔
800
    }
801

802
    public static <E> List<E> invoke(final Iterable<E> iterable, final String methodName) {
803
        return invoke(iterable, methodName, Collections.emptyList());
1✔
804
    }
805

806
    public List<T> invoke(final String methodName) {
807
        return invoke(iterable, methodName);
1✔
808
    }
809

810
    /*
811
     * Documented, #pluck
812
     */
813
    public static <E> List<Object> pluck(final List<E> list, final String propertyName) {
814
        if (list.isEmpty()) {
1✔
815
            return Collections.emptyList();
1✔
816
        }
817
        return map(
1✔
818
                list,
819
                elem -> {
820
                    try {
821
                        return elem.getClass().getField(propertyName).get(elem);
1✔
822
                    } catch (Exception e) {
1✔
823
                        try {
824
                            return elem.getClass().getMethod(propertyName).invoke(elem);
1✔
825
                        } catch (Exception ex) {
1✔
826
                            throw new IllegalArgumentException(ex);
1✔
827
                        }
828
                    }
829
                });
830
    }
831

832
    public List<Object> pluck(final String propertyName) {
833
        return pluck(newArrayList(iterable), propertyName);
1✔
834
    }
835

836
    public static <E> Set<Object> pluck(final Set<E> set, final String propertyName) {
837
        if (set.isEmpty()) {
1✔
838
            return Collections.emptySet();
1✔
839
        }
840
        return map(
1✔
841
                set,
842
                elem -> {
843
                    try {
844
                        return elem.getClass().getField(propertyName).get(elem);
1✔
845
                    } catch (Exception e) {
1✔
846
                        try {
847
                            return elem.getClass().getMethod(propertyName).invoke(elem);
1✔
848
                        } catch (Exception ex) {
1✔
849
                            throw new IllegalArgumentException(ex);
1✔
850
                        }
851
                    }
852
                });
853
    }
854

855
    /*
856
     * Documented, #where
857
     */
858
    public static <T, E> List<E> where(
859
            final List<E> list, final List<Map.Entry<String, T>> properties) {
860
        return filter(list, new WherePredicate<>(properties));
1✔
861
    }
862

863
    public <E> List<T> where(final List<Map.Entry<String, E>> properties) {
864
        return where(newArrayList(iterable), properties);
1✔
865
    }
866

867
    public static <T, E> Set<E> where(
868
            final Set<E> set, final List<Map.Entry<String, T>> properties) {
869
        return filter(set, new WherePredicate<>(properties));
1✔
870
    }
871

872
    /*
873
     * Documented, #findWhere
874
     */
875
    public static <T, E> Optional<E> findWhere(
876
            final Iterable<E> iterable, final List<Map.Entry<String, T>> properties) {
877
        return find(iterable, new WherePredicate<>(properties));
1✔
878
    }
879

880
    public <E> Optional<T> findWhere(final List<Map.Entry<String, E>> properties) {
881
        return findWhere(iterable, properties);
1✔
882
    }
883

884
    /*
885
     * Documented, #max
886
     */
887
    public static <E extends Comparable<? super E>> E max(final Collection<E> collection) {
888
        return Collections.max(collection);
1✔
889
    }
890

891
    @SuppressWarnings("unchecked")
892
    public T max() {
893
        return (T) max((Collection) iterable);
1✔
894
    }
895

896
    @SuppressWarnings("unchecked")
897
    public static <E, F extends Comparable> E max(
898
            final Collection<E> collection, final Function<E, F> func) {
899
        return Collections.max(collection, (o1, o2) -> func.apply(o1).compareTo(func.apply(o2)));
1✔
900
    }
901

902
    @SuppressWarnings("unchecked")
903
    public <F extends Comparable<? super F>> T max(final Function<T, F> func) {
904
        return (T) max((Collection) iterable, func);
1✔
905
    }
906

907
    /*
908
     * Documented, #min
909
     */
910
    public static <E extends Comparable<? super E>> E min(final Collection<E> collection) {
911
        return Collections.min(collection);
1✔
912
    }
913

914
    @SuppressWarnings("unchecked")
915
    public T min() {
916
        return (T) min((Collection) iterable);
1✔
917
    }
918

919
    @SuppressWarnings("unchecked")
920
    public static <E, F extends Comparable> E min(
921
            final Collection<E> collection, final Function<E, F> func) {
922
        return Collections.min(collection, (o1, o2) -> func.apply(o1).compareTo(func.apply(o2)));
1✔
923
    }
924

925
    @SuppressWarnings("unchecked")
926
    public <F extends Comparable<? super F>> T min(final Function<T, F> func) {
927
        return (T) min((Collection) iterable, func);
1✔
928
    }
929

930
    /*
931
     * Documented, #shuffle
932
     */
933
    public static <E> List<E> shuffle(final Iterable<E> iterable) {
934
        final List<E> shuffled = newArrayList(iterable);
1✔
935
        Collections.shuffle(shuffled);
1✔
936
        return shuffled;
1✔
937
    }
938

939
    public List<T> shuffle() {
940
        return shuffle(iterable);
1✔
941
    }
942

943
    /*
944
     * Documented, #sample
945
     */
946
    public static <E> E sample(final Iterable<E> iterable) {
947
        return newArrayList(iterable).get(new java.security.SecureRandom().nextInt(size(iterable)));
1✔
948
    }
949

950
    public T sample() {
951
        return sample(iterable);
1✔
952
    }
953

954
    public static <E> Set<E> sample(final List<E> list, final int howMany) {
955
        final int size = Math.min(howMany, list.size());
1✔
956
        final Set<E> samples = newLinkedHashSetWithExpectedSize(size);
1✔
957
        while (samples.size() < size) {
1✔
958
            E sample = sample(list);
1✔
959
            samples.add(sample);
1✔
960
        }
1✔
961
        return samples;
1✔
962
    }
963

964
    public static <T extends Comparable<? super T>> List<T> sortWith(
965
            final Iterable<T> iterable, final Comparator<T> comparator) {
966
        final List<T> sortedList = newArrayList(iterable);
1✔
967
        sortedList.sort(comparator);
1✔
968
        return sortedList;
1✔
969
    }
970

971
    @SuppressWarnings("unchecked")
972
    public <E extends Comparable<? super E>> List<E> sortWith(final Comparator<E> comparator) {
973
        return sortWith((Iterable<E>) iterable, comparator);
1✔
974
    }
975

976
    /*
977
     * Documented, #sortBy
978
     */
979
    public static <E, T extends Comparable<? super T>> List<E> sortBy(
980
            final Iterable<E> iterable, final Function<E, T> func) {
981
        final List<E> sortedList = newArrayList(iterable);
1✔
982
        sortedList.sort(Comparator.comparing(func));
1✔
983
        return sortedList;
1✔
984
    }
985

986
    @SuppressWarnings("unchecked")
987
    public <E, V extends Comparable<? super V>> List<E> sortBy(final Function<E, V> func) {
988
        return sortBy((Iterable<E>) iterable, func);
1✔
989
    }
990

991
    public static <K, V extends Comparable<? super V>> List<Map<K, V>> sortBy(
992
            final Iterable<Map<K, V>> iterable, final K key) {
993
        final List<Map<K, V>> sortedList = newArrayList(iterable);
1✔
994
        sortedList.sort(Comparator.comparing(o -> o.get(key)));
1✔
995
        return sortedList;
1✔
996
    }
997

998
    /*
999
     * Documented, #groupBy
1000
     */
1001
    public static <K, E> Map<K, List<E>> groupBy(
1002
            final Iterable<E> iterable, final Function<E, K> func) {
1003
        final Map<K, List<E>> retVal = newLinkedHashMap();
1✔
1004
        for (E e : iterable) {
1✔
1005
            final K key = func.apply(e);
1✔
1006
            List<E> val;
1007
            if (retVal.containsKey(key)) {
1✔
1008
                val = retVal.get(key);
1✔
1009
            } else {
1010
                val = newArrayList();
1✔
1011
            }
1012
            val.add(e);
1✔
1013
            retVal.put(key, val);
1✔
1014
        }
1✔
1015
        return retVal;
1✔
1016
    }
1017

1018
    @SuppressWarnings("unchecked")
1019
    public <K, E> Map<K, List<E>> groupBy(final Function<E, K> func) {
1020
        return groupBy((Iterable<E>) iterable, func);
1✔
1021
    }
1022

1023
    public static <K, E> Map<K, Optional<E>> groupBy(
1024
            final Iterable<E> iterable,
1025
            final Function<E, K> func,
1026
            final BinaryOperator<E> binaryOperator) {
1027
        final Map<K, Optional<E>> retVal = newLinkedHashMap();
1✔
1028
        for (Map.Entry<K, List<E>> entry : groupBy(iterable, func).entrySet()) {
1✔
1029
            retVal.put(entry.getKey(), reduce(entry.getValue(), binaryOperator));
1✔
1030
        }
1✔
1031
        return retVal;
1✔
1032
    }
1033

1034
    @SuppressWarnings("unchecked")
1035
    public <K, E> Map<K, Optional<E>> groupBy(
1036
            final Function<E, K> func, final BinaryOperator<E> binaryOperator) {
1037
        return groupBy((Iterable<E>) iterable, func, binaryOperator);
1✔
1038
    }
1039

1040
    @SuppressWarnings("unchecked")
1041
    public static <K, E> Map<K, List<E>> indexBy(
1042
            final Iterable<E> iterable, final String property) {
1043
        return groupBy(
1✔
1044
                iterable,
1045
                elem -> {
1046
                    try {
1047
                        return (K) elem.getClass().getField(property).get(elem);
1✔
1048
                    } catch (Exception e) {
1✔
1049
                        return null;
1✔
1050
                    }
1051
                });
1052
    }
1053

1054
    @SuppressWarnings("unchecked")
1055
    public <K, E> Map<K, List<E>> indexBy(final String property) {
1056
        return indexBy((Iterable<E>) iterable, property);
1✔
1057
    }
1058

1059
    /*
1060
     * Documented, #countBy
1061
     */
1062
    public static <K, E> Map<K, Integer> countBy(final Iterable<E> iterable, Function<E, K> func) {
1063
        final Map<K, Integer> retVal = newLinkedHashMap();
1✔
1064
        for (E e : iterable) {
1✔
1065
            final K key = func.apply(e);
1✔
1066
            if (retVal.containsKey(key)) {
1✔
1067
                retVal.put(key, 1 + retVal.get(key));
1✔
1068
            } else {
1069
                retVal.put(key, 1);
1✔
1070
            }
1071
        }
1✔
1072
        return retVal;
1✔
1073
    }
1074

1075
    public static <K> Map<K, Integer> countBy(final Iterable<K> iterable) {
1076
        final Map<K, Integer> retVal = newLinkedHashMap();
1✔
1077
        for (K key : iterable) {
1✔
1078
            if (retVal.containsKey(key)) {
1✔
1079
                retVal.put(key, 1 + retVal.get(key));
1✔
1080
            } else {
1081
                retVal.put(key, 1);
1✔
1082
            }
1083
        }
1✔
1084
        return retVal;
1✔
1085
    }
1086

1087
    @SuppressWarnings("unchecked")
1088
    public <K, E> Map<K, Integer> countBy(Function<E, K> func) {
1089
        return countBy((Iterable<E>) iterable, func);
1✔
1090
    }
1091

1092
    @SuppressWarnings("unchecked")
1093
    public <K> Map<K, Integer> countBy() {
1094
        return countBy((Iterable<K>) iterable);
1✔
1095
    }
1096

1097
    /*
1098
     * Documented, #toArray
1099
     */
1100
    @SuppressWarnings("unchecked")
1101
    public static <E> E[] toArray(final Iterable<E> iterable) {
1102
        return (E[]) newArrayList(iterable).toArray();
1✔
1103
    }
1104

1105
    @SuppressWarnings("unchecked")
1106
    public <E> E[] toArray() {
1107
        return toArray((Iterable<E>) iterable);
1✔
1108
    }
1109

1110
    /*
1111
     * Documented, #toMap
1112
     */
1113
    public static <K, V> Map<K, V> toMap(final Iterable<Map.Entry<K, V>> iterable) {
1114
        final Map<K, V> result = newLinkedHashMap();
1✔
1115
        for (Map.Entry<K, V> entry : iterable) {
1✔
1116
            result.put(entry.getKey(), entry.getValue());
1✔
1117
        }
1✔
1118
        return result;
1✔
1119
    }
1120

1121
    @SuppressWarnings("unchecked")
1122
    public <K, V> Map<K, V> toMap() {
1123
        return toMap((Iterable<Map.Entry<K, V>>) iterable);
1✔
1124
    }
1125

1126
    public static <K, V> Map<K, V> toMap(final List<Map.Entry<K, V>> tuples) {
1127
        final Map<K, V> result = newLinkedHashMap();
1✔
1128
        for (final Map.Entry<K, V> entry : tuples) {
1✔
1129
            result.put(entry.getKey(), entry.getValue());
1✔
1130
        }
1✔
1131
        return result;
1✔
1132
    }
1133

1134
    public Map<T, Integer> toCardinalityMap() {
1135
        return toCardinalityMap(iterable);
1✔
1136
    }
1137

1138
    public static <K> Map<K, Integer> toCardinalityMap(final Iterable<K> iterable) {
1139
        Iterator<K> iterator = iterable.iterator();
1✔
1140
        Map<K, Integer> result = newLinkedHashMap();
1✔
1141

1142
        while (iterator.hasNext()) {
1✔
1143
            K item = iterator.next();
1✔
1144

1145
            if (result.containsKey(item)) {
1✔
1146
                result.put(item, result.get(item) + 1);
1✔
1147
            } else {
1148
                result.put(item, 1);
1✔
1149
            }
1150
        }
1✔
1151
        return result;
1✔
1152
    }
1153

1154
    /*
1155
     * Documented, #size
1156
     */
1157
    public static int size(final Iterable<?> iterable) {
1158
        if (iterable instanceof Collection) {
1✔
1159
            return ((Collection) iterable).size();
1✔
1160
        }
1161
        int size;
1162
        final Iterator<?> iterator = iterable.iterator();
1✔
1163
        for (size = 0; iterator.hasNext(); size += 1) {
1✔
1164
            iterator.next();
1✔
1165
        }
1166
        return size;
1✔
1167
    }
1168

1169
    public int size() {
1170
        return size(iterable);
1✔
1171
    }
1172

1173
    @SuppressWarnings("unchecked")
1174
    public static <E> int size(final E... array) {
1175
        return array.length;
1✔
1176
    }
1177

1178
    public static <E> List<List<E>> partition(final Iterable<E> iterable, final Predicate<E> pred) {
1179
        final List<E> retVal1 = newArrayList();
1✔
1180
        final List<E> retVal2 = newArrayList();
1✔
1181
        for (final E e : iterable) {
1✔
1182
            if (pred.test(e)) {
1✔
1183
                retVal1.add(e);
1✔
1184
            } else {
1185
                retVal2.add(e);
1✔
1186
            }
1187
        }
1✔
1188
        return Arrays.asList(retVal1, retVal2);
1✔
1189
    }
1190

1191
    @SuppressWarnings("unchecked")
1192
    public static <E> List<E>[] partition(final E[] iterable, final Predicate<E> pred) {
1193
        return partition(Arrays.asList(iterable), pred).toArray(new ArrayList[0]);
1✔
1194
    }
1195

1196
    public T singleOrNull() {
1197
        return singleOrNull(iterable);
1✔
1198
    }
1199

1200
    public T singleOrNull(Predicate<T> pred) {
1201
        return singleOrNull(iterable, pred);
1✔
1202
    }
1203

1204
    public static <E> E singleOrNull(final Iterable<E> iterable) {
1205
        Iterator<E> iterator = iterable.iterator();
1✔
1206
        if (!iterator.hasNext()) {
1✔
1207
            return null;
1✔
1208
        }
1209
        E result = iterator.next();
1✔
1210

1211
        if (iterator.hasNext()) {
1✔
1212
            result = null;
1✔
1213
        }
1214
        return result;
1✔
1215
    }
1216

1217
    public static <E> E singleOrNull(final Iterable<E> iterable, Predicate<E> pred) {
1218
        return singleOrNull(filter(iterable, pred));
1✔
1219
    }
1220

1221
    /*
1222
     * Documented, #first
1223
     */
1224
    public static <E> E first(final Iterable<E> iterable) {
1225
        return iterable.iterator().next();
1✔
1226
    }
1227

1228
    @SuppressWarnings("unchecked")
1229
    public static <E> E first(final E... array) {
1230
        return array[0];
1✔
1231
    }
1232

1233
    public static <E> List<E> first(final List<E> list, final int n) {
1234
        return list.subList(0, Math.min(n < 0 ? 0 : n, list.size()));
1✔
1235
    }
1236

1237
    public T first() {
1238
        return first(iterable);
1✔
1239
    }
1240

1241
    public List<T> first(final int n) {
1242
        return first(newArrayList(iterable), n);
1✔
1243
    }
1244

1245
    public static <E> E first(final Iterable<E> iterable, final Predicate<E> pred) {
1246
        return filter(newArrayList(iterable), pred).iterator().next();
1✔
1247
    }
1248

1249
    public static <E> List<E> first(
1250
            final Iterable<E> iterable, final Predicate<E> pred, final int n) {
1251
        List<E> list = filter(newArrayList(iterable), pred);
1✔
1252
        return list.subList(0, Math.min(n < 0 ? 0 : n, list.size()));
1✔
1253
    }
1254

1255
    public T first(final Predicate<T> pred) {
1256
        return first(newArrayList(iterable), pred);
1✔
1257
    }
1258

1259
    public List<T> first(final Predicate<T> pred, final int n) {
1260
        return first(newArrayList(iterable), pred, n);
1✔
1261
    }
1262

1263
    public static <E> E firstOrNull(final Iterable<E> iterable) {
1264
        final Iterator<E> iterator = iterable.iterator();
1✔
1265
        return iterator.hasNext() ? iterator.next() : null;
1✔
1266
    }
1267

1268
    public T firstOrNull() {
1269
        return firstOrNull(iterable);
1✔
1270
    }
1271

1272
    public static <E> E firstOrNull(final Iterable<E> iterable, final Predicate<E> pred) {
1273
        final Iterator<E> iterator = filter(newArrayList(iterable), pred).iterator();
1✔
1274
        return iterator.hasNext() ? iterator.next() : null;
1✔
1275
    }
1276

1277
    public T firstOrNull(final Predicate<T> pred) {
1278
        return firstOrNull(iterable, pred);
1✔
1279
    }
1280

1281
    public static <E> E head(final Iterable<E> iterable) {
1282
        return first(iterable);
1✔
1283
    }
1284

1285
    @SuppressWarnings("unchecked")
1286
    public static <E> E head(final E... array) {
1287
        return first(array);
1✔
1288
    }
1289

1290
    public static <E> List<E> head(final List<E> list, final int n) {
1291
        return first(list, n);
1✔
1292
    }
1293

1294
    public T head() {
1295
        return first();
1✔
1296
    }
1297

1298
    public List<T> head(final int n) {
1299
        return first(n);
1✔
1300
    }
1301

1302
    /*
1303
     * Documented, #initial
1304
     */
1305
    public static <E> List<E> initial(final List<E> list) {
1306
        return initial(list, 1);
1✔
1307
    }
1308

1309
    public static <E> List<E> initial(final List<E> list, final int n) {
1310
        return list.subList(0, Math.max(0, list.size() - n));
1✔
1311
    }
1312

1313
    @SuppressWarnings("unchecked")
1314
    public static <E> E[] initial(final E... array) {
1315
        return initial(array, 1);
1✔
1316
    }
1317

1318
    public static <E> E[] initial(final E[] array, final int n) {
1319
        return Arrays.copyOf(array, array.length - n);
1✔
1320
    }
1321

1322
    public List<T> initial() {
1323
        return initial((List<T>) iterable, 1);
1✔
1324
    }
1325

1326
    public List<T> initial(final int n) {
1327
        return initial((List<T>) iterable, n);
1✔
1328
    }
1329

1330
    @SuppressWarnings("unchecked")
1331
    public static <E> E last(final E... array) {
1332
        return array[array.length - 1];
1✔
1333
    }
1334

1335
    /*
1336
     * Documented, #last
1337
     */
1338
    public static <E> E last(final List<E> list) {
1339
        return list.get(list.size() - 1);
1✔
1340
    }
1341

1342
    public static <E> List<E> last(final List<E> list, final int n) {
1343
        return list.subList(Math.max(0, list.size() - n), list.size());
1✔
1344
    }
1345

1346
    public T last() {
1347
        return last((List<T>) iterable);
1✔
1348
    }
1349

1350
    public List<T> last(final int n) {
1351
        return last((List<T>) iterable, n);
1✔
1352
    }
1353

1354
    public static <E> E last(final List<E> list, final Predicate<E> pred) {
1355
        final List<E> filteredList = filter(list, pred);
1✔
1356
        return filteredList.get(filteredList.size() - 1);
1✔
1357
    }
1358

1359
    public T last(final Predicate<T> pred) {
1360
        return last((List<T>) iterable, pred);
1✔
1361
    }
1362

1363
    public static <E> E lastOrNull(final List<E> list) {
1364
        return list.isEmpty() ? null : list.get(list.size() - 1);
1✔
1365
    }
1366

1367
    public T lastOrNull() {
1368
        return lastOrNull((List<T>) iterable);
1✔
1369
    }
1370

1371
    public static <E> E lastOrNull(final List<E> list, final Predicate<E> pred) {
1372
        final List<E> filteredList = filter(list, pred);
1✔
1373
        return filteredList.isEmpty() ? null : filteredList.get(filteredList.size() - 1);
1✔
1374
    }
1375

1376
    public T lastOrNull(final Predicate<T> pred) {
1377
        return lastOrNull((List<T>) iterable, pred);
1✔
1378
    }
1379

1380
    /*
1381
     * Documented, #rest
1382
     */
1383
    public static <E> List<E> rest(final List<E> list) {
1384
        return rest(list, 1);
1✔
1385
    }
1386

1387
    public static <E> List<E> rest(final List<E> list, int n) {
1388
        return list.subList(Math.min(n, list.size()), list.size());
1✔
1389
    }
1390

1391
    @SuppressWarnings("unchecked")
1392
    public static <E> E[] rest(final E... array) {
1393
        return rest(array, 1);
1✔
1394
    }
1395

1396
    @SuppressWarnings("unchecked")
1397
    public static <E> E[] rest(final E[] array, final int n) {
1398
        return (E[]) rest(Arrays.asList(array), n).toArray();
1✔
1399
    }
1400

1401
    public List<T> rest() {
1402
        return rest((List<T>) iterable);
1✔
1403
    }
1404

1405
    public List<T> rest(int n) {
1406
        return rest((List<T>) iterable, n);
1✔
1407
    }
1408

1409
    public static <E> List<E> tail(final List<E> list) {
1410
        return rest(list);
1✔
1411
    }
1412

1413
    public static <E> List<E> tail(final List<E> list, final int n) {
1414
        return rest(list, n);
1✔
1415
    }
1416

1417
    @SuppressWarnings("unchecked")
1418
    public static <E> E[] tail(final E... array) {
1419
        return rest(array);
1✔
1420
    }
1421

1422
    public static <E> E[] tail(final E[] array, final int n) {
1423
        return rest(array, n);
1✔
1424
    }
1425

1426
    public List<T> tail() {
1427
        return rest();
1✔
1428
    }
1429

1430
    public List<T> tail(final int n) {
1431
        return rest(n);
1✔
1432
    }
1433

1434
    public static <E> List<E> drop(final List<E> list) {
1435
        return rest(list);
1✔
1436
    }
1437

1438
    public static <E> List<E> drop(final List<E> list, final int n) {
1439
        return rest(list, n);
1✔
1440
    }
1441

1442
    @SuppressWarnings("unchecked")
1443
    public static <E> E[] drop(final E... array) {
1444
        return rest(array);
1✔
1445
    }
1446

1447
    public static <E> E[] drop(final E[] array, final int n) {
1448
        return rest(array, n);
1✔
1449
    }
1450

1451
    /*
1452
     * Documented, #compact
1453
     */
1454
    public static <E> List<E> compact(final List<E> list) {
1455
        return filter(
1✔
1456
                list,
1457
                arg ->
1458
                        !String.valueOf(arg).equals("null")
1✔
1459
                                && !String.valueOf(arg).equals("0")
1✔
1460
                                && !String.valueOf(arg).equals("false")
1✔
1461
                                && !String.valueOf(arg).equals(""));
1✔
1462
    }
1463

1464
    @SuppressWarnings("unchecked")
1465
    public static <E> E[] compact(final E... array) {
1466
        return (E[]) compact(Arrays.asList(array)).toArray();
1✔
1467
    }
1468

1469
    public static <E> List<E> compact(final List<E> list, final E falsyValue) {
1470
        return filter(list, arg -> !(Objects.equals(arg, falsyValue)));
1✔
1471
    }
1472

1473
    @SuppressWarnings("unchecked")
1474
    public static <E> E[] compact(final E[] array, final E falsyValue) {
1475
        return (E[]) compact(Arrays.asList(array), falsyValue).toArray();
1✔
1476
    }
1477

1478
    public List<T> compact() {
1479
        return compact((List<T>) iterable);
1✔
1480
    }
1481

1482
    public List<T> compact(final T falsyValue) {
1483
        return compact((List<T>) iterable, falsyValue);
1✔
1484
    }
1485

1486
    /*
1487
     * Documented, #flatten
1488
     */
1489
    public static <E> List<E> flatten(final List<?> list) {
1490
        List<E> flattened = newArrayList();
1✔
1491
        flatten(list, flattened, -1);
1✔
1492
        return flattened;
1✔
1493
    }
1494

1495
    public static <E> List<E> flatten(final List<?> list, final boolean shallow) {
1496
        List<E> flattened = newArrayList();
1✔
1497
        flatten(list, flattened, shallow ? 1 : -1);
1✔
1498
        return flattened;
1✔
1499
    }
1500

1501
    @SuppressWarnings("unchecked")
1502
    private static <E> void flatten(
1503
            final List<?> fromTreeList, final List<E> toFlatList, final int shallowLevel) {
1504
        for (Object item : fromTreeList) {
1✔
1505
            if (item instanceof List<?> && shallowLevel != 0) {
1✔
1506
                flatten((List<?>) item, toFlatList, shallowLevel - 1);
1✔
1507
            } else {
1508
                toFlatList.add((E) item);
1✔
1509
            }
1510
        }
1✔
1511
    }
1✔
1512

1513
    public List<T> flatten() {
1514
        return flatten((List<T>) iterable);
1✔
1515
    }
1516

1517
    public List<T> flatten(final boolean shallow) {
1518
        return flatten((List<T>) iterable, shallow);
1✔
1519
    }
1520

1521
    /*
1522
     * Documented, #without
1523
     */
1524
    @SuppressWarnings("unchecked")
1525
    public static <E> List<E> without(final List<E> list, E... values) {
1526
        final List<E> valuesList = Arrays.asList(values);
1✔
1527
        return filter(list, elem -> !contains(valuesList, elem));
1✔
1528
    }
1529

1530
    @SuppressWarnings("unchecked")
1531
    public static <E> E[] without(final E[] array, final E... values) {
1532
        return (E[]) without(Arrays.asList(array), values).toArray();
1✔
1533
    }
1534

1535
    /*
1536
     * Documented, #uniq
1537
     */
1538
    public static <E> List<E> uniq(final List<E> list) {
1539
        return newArrayList(newLinkedHashSet(list));
1✔
1540
    }
1541

1542
    @SuppressWarnings("unchecked")
1543
    public static <E> E[] uniq(final E... array) {
1544
        return (E[]) uniq(Arrays.asList(array)).toArray();
1✔
1545
    }
1546

1547
    public static <K, E> Collection<E> uniq(final Iterable<E> iterable, final Function<E, K> func) {
1548
        final Map<K, E> retVal = newLinkedHashMap();
1✔
1549
        for (final E e : iterable) {
1✔
1550
            final K key = func.apply(e);
1✔
1551
            retVal.put(key, e);
1✔
1552
        }
1✔
1553
        return retVal.values();
1✔
1554
    }
1555

1556
    @SuppressWarnings("unchecked")
1557
    public static <K, E> E[] uniq(final E[] array, final Function<E, K> func) {
1558
        return (E[]) uniq(Arrays.asList(array), func).toArray();
1✔
1559
    }
1560

1561
    public static <E> List<E> distinct(final List<E> list) {
1562
        return uniq(list);
1✔
1563
    }
1564

1565
    @SuppressWarnings("unchecked")
1566
    public static <E> E[] distinct(final E... array) {
1567
        return uniq(array);
1✔
1568
    }
1569

1570
    public static <K, E> Collection<E> distinctBy(
1571
            final Iterable<E> iterable, final Function<E, K> func) {
1572
        return uniq(iterable, func);
1✔
1573
    }
1574

1575
    public static <K, E> E[] distinctBy(final E[] array, final Function<E, K> func) {
1576
        return uniq(array, func);
1✔
1577
    }
1578

1579
    /*
1580
     * Documented, #union
1581
     */
1582
    @SuppressWarnings("unchecked")
1583
    public static <E> List<E> union(final List<E> list, final List<E>... lists) {
1584
        final Set<E> union = newLinkedHashSet();
1✔
1585
        union.addAll(list);
1✔
1586
        for (List<E> localList : lists) {
1✔
1587
            union.addAll(localList);
1✔
1588
        }
1589
        return newArrayList(union);
1✔
1590
    }
1591

1592
    @SuppressWarnings("unchecked")
1593
    public List<T> unionWith(final List<T>... lists) {
1594
        return union(newArrayList(iterable), lists);
1✔
1595
    }
1596

1597
    @SuppressWarnings("unchecked")
1598
    public static <E> E[] union(final E[]... arrays) {
1599
        final Set<E> union = newLinkedHashSet();
1✔
1600
        for (E[] array : arrays) {
1✔
1601
            union.addAll(Arrays.asList(array));
1✔
1602
        }
1603
        return (E[]) newArrayList(union).toArray();
1✔
1604
    }
1605

1606
    /*
1607
     * Documented, #intersection
1608
     */
1609
    public static <E> List<E> intersection(final List<E> list1, final List<E> list2) {
1610
        final List<E> result = newArrayList();
1✔
1611
        for (final E item : list1) {
1✔
1612
            if (list2.contains(item)) {
1✔
1613
                result.add(item);
1✔
1614
            }
1615
        }
1✔
1616
        return result;
1✔
1617
    }
1618

1619
    @SuppressWarnings("unchecked")
1620
    public static <E> List<E> intersection(final List<E> list, final List<E>... lists) {
1621
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1622
        stack.push(list);
1✔
1623
        for (List<E> es : lists) {
1✔
1624
            stack.push(intersection(stack.peek(), es));
1✔
1625
        }
1626
        return stack.peek();
1✔
1627
    }
1628

1629
    @SuppressWarnings("unchecked")
1630
    public List<T> intersectionWith(final List<T>... lists) {
1631
        return intersection(newArrayList(iterable), lists);
1✔
1632
    }
1633

1634
    @SuppressWarnings("unchecked")
1635
    public static <E> E[] intersection(final E[]... arrays) {
1636
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1637
        stack.push(Arrays.asList(arrays[0]));
1✔
1638
        for (int index = 1; index < arrays.length; index += 1) {
1✔
1639
            stack.push(intersection(stack.peek(), Arrays.asList(arrays[index])));
1✔
1640
        }
1641
        return (E[]) stack.peek().toArray();
1✔
1642
    }
1643

1644
    /*
1645
     * Documented, #difference
1646
     */
1647
    public static <E> List<E> difference(final List<E> list1, final List<E> list2) {
1648
        final List<E> result = newArrayList();
1✔
1649
        for (final E item : list1) {
1✔
1650
            if (!list2.contains(item)) {
1✔
1651
                result.add(item);
1✔
1652
            }
1653
        }
1✔
1654
        return result;
1✔
1655
    }
1656

1657
    @SuppressWarnings("unchecked")
1658
    public static <E> List<E> difference(final List<E> list, final List<E>... lists) {
1659
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1660
        stack.push(list);
1✔
1661
        for (List<E> es : lists) {
1✔
1662
            stack.push(difference(stack.peek(), es));
1✔
1663
        }
1664
        return stack.peek();
1✔
1665
    }
1666

1667
    @SuppressWarnings("unchecked")
1668
    public List<T> differenceWith(final List<T>... lists) {
1669
        return difference(newArrayList(iterable), lists);
1✔
1670
    }
1671

1672
    @SuppressWarnings("unchecked")
1673
    public static <E> E[] difference(final E[]... arrays) {
1674
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1675
        stack.push(Arrays.asList(arrays[0]));
1✔
1676
        for (int index = 1; index < arrays.length; index += 1) {
1✔
1677
            stack.push(difference(stack.peek(), Arrays.asList(arrays[index])));
1✔
1678
        }
1679
        return (E[]) stack.peek().toArray();
1✔
1680
    }
1681

1682
    /*
1683
     * Documented, #zip
1684
     */
1685
    @SuppressWarnings("unchecked")
1686
    public static <T> List<List<T>> zip(final List<T>... lists) {
1687
        final List<List<T>> zipped = newArrayList();
1✔
1688
        each(
1✔
1689
                Arrays.asList(lists),
1✔
1690
                list -> {
1691
                    int index = 0;
1✔
1692
                    for (T elem : list) {
1✔
1693
                        final List<T> nTuple =
1694
                                index >= zipped.size()
1✔
1695
                                        ? Underscore.newArrayList()
1✔
1696
                                        : zipped.get(index);
1✔
1697
                        if (index >= zipped.size()) {
1✔
1698
                            zipped.add(nTuple);
1✔
1699
                        }
1700
                        index += 1;
1✔
1701
                        nTuple.add(elem);
1✔
1702
                    }
1✔
1703
                });
1✔
1704
        return zipped;
1✔
1705
    }
1706

1707
    @SuppressWarnings("unchecked")
1708
    public static <T> List<List<T>> unzip(final List<T>... lists) {
1709
        final List<List<T>> unzipped = newArrayList();
1✔
1710
        for (int index = 0; index < lists[0].size(); index += 1) {
1✔
1711
            final List<T> nTuple = newArrayList();
1✔
1712
            for (List<T> list : lists) {
1✔
1713
                nTuple.add(list.get(index));
1✔
1714
            }
1715
            unzipped.add(nTuple);
1✔
1716
        }
1717
        return unzipped;
1✔
1718
    }
1719

1720
    /*
1721
     * Documented, #object
1722
     */
1723
    public static <K, V> List<Map.Entry<K, V>> object(final List<K> keys, final List<V> values) {
1724
        return map(
1✔
1725
                keys,
1726
                new Function<>() {
1✔
1727
                    private int index;
1728

1729
                    @Override
1730
                    public Map.Entry<K, V> apply(K key) {
1731
                        return Map.entry(key, values.get(index++));
1✔
1732
                    }
1733
                });
1734
    }
1735

1736
    public static <E> int findIndex(final List<E> list, final Predicate<E> pred) {
1737
        for (int index = 0; index < list.size(); index++) {
1✔
1738
            if (pred.test(list.get(index))) {
1✔
1739
                return index;
1✔
1740
            }
1741
        }
1742
        return -1;
1✔
1743
    }
1744

1745
    public static <E> int findIndex(final E[] array, final Predicate<E> pred) {
1746
        return findIndex(Arrays.asList(array), pred);
1✔
1747
    }
1748

1749
    public static <E> int findLastIndex(final List<E> list, final Predicate<E> pred) {
1750
        for (int index = list.size() - 1; index >= 0; index--) {
1✔
1751
            if (pred.test(list.get(index))) {
1✔
1752
                return index;
1✔
1753
            }
1754
        }
1755
        return -1;
1✔
1756
    }
1757

1758
    public static <E> int findLastIndex(final E[] array, final Predicate<E> pred) {
1759
        return findLastIndex(Arrays.asList(array), pred);
1✔
1760
    }
1761

1762
    public static <E extends Comparable<E>> int binarySearch(
1763
            final Iterable<E> iterable, final E key) {
1764
        if (key == null) {
1✔
1765
            return first(iterable) == null ? 0 : -1;
1✔
1766
        }
1767
        int begin = 0;
1✔
1768
        int end = size(iterable) - 1;
1✔
1769
        int numberOfNullValues = 0;
1✔
1770
        List<E> list = new ArrayList<>();
1✔
1771
        for (E item : iterable) {
1✔
1772
            if (item == null) {
1✔
1773
                numberOfNullValues++;
1✔
1774
                end--;
1✔
1775
            } else {
1776
                list.add(item);
1✔
1777
            }
1778
        }
1✔
1779
        while (begin <= end) {
1✔
1780
            int middle = begin + (end - begin) / 2;
1✔
1781
            if (key.compareTo(list.get(middle)) < 0) {
1✔
1782
                end = middle - 1;
1✔
1783
            } else if (key.compareTo(list.get(middle)) > 0) {
1✔
1784
                begin = middle + 1;
1✔
1785
            } else {
1786
                return middle + numberOfNullValues;
1✔
1787
            }
1788
        }
1✔
1789
        return -(begin + numberOfNullValues + 1);
1✔
1790
    }
1791

1792
    public static <E extends Comparable<E>> int binarySearch(final E[] array, final E key) {
1793
        return binarySearch(Arrays.asList(array), key);
1✔
1794
    }
1795

1796
    /*
1797
     * Documented, #sortedIndex
1798
     */
1799
    public static <E extends Comparable<E>> int sortedIndex(final List<E> list, final E value) {
1800
        int index = 0;
1✔
1801
        for (E elem : list) {
1✔
1802
            if (elem.compareTo(value) >= 0) {
1✔
1803
                return index;
1✔
1804
            }
1805
            index += 1;
1✔
1806
        }
1✔
1807
        return -1;
1✔
1808
    }
1809

1810
    public static <E extends Comparable<E>> int sortedIndex(final E[] array, final E value) {
1811
        return sortedIndex(Arrays.asList(array), value);
1✔
1812
    }
1813

1814
    @SuppressWarnings("unchecked")
1815
    public static <E extends Comparable<E>> int sortedIndex(
1816
            final List<E> list, final E value, final String propertyName) {
1817
        try {
1818
            final Field property = value.getClass().getField(propertyName);
1✔
1819
            final Object valueProperty = property.get(value);
1✔
1820
            int index = 0;
1✔
1821
            for (E elem : list) {
1✔
1822
                if (((Comparable) property.get(elem)).compareTo(valueProperty) >= 0) {
1✔
1823
                    return index;
1✔
1824
                }
1825
                index += 1;
1✔
1826
            }
1✔
1827
            return -1;
1✔
1828
        } catch (Exception e) {
1✔
1829
            throw new IllegalArgumentException(e);
1✔
1830
        }
1831
    }
1832

1833
    public static <E extends Comparable<E>> int sortedIndex(
1834
            final E[] array, final E value, final String propertyName) {
1835
        return sortedIndex(Arrays.asList(array), value, propertyName);
1✔
1836
    }
1837

1838
    /*
1839
     * Documented, #indexOf
1840
     */
1841
    public static <E> int indexOf(final List<E> list, final E value) {
1842
        return list.indexOf(value);
1✔
1843
    }
1844

1845
    public static <E> int indexOf(final E[] array, final E value) {
1846
        return indexOf(Arrays.asList(array), value);
1✔
1847
    }
1848

1849
    /*
1850
     * Documented, #lastIndexOf
1851
     */
1852
    public static <E> int lastIndexOf(final List<E> list, final E value) {
1853
        return list.lastIndexOf(value);
1✔
1854
    }
1855

1856
    public static <E> int lastIndexOf(final E[] array, final E value) {
1857
        return lastIndexOf(Arrays.asList(array), value);
1✔
1858
    }
1859

1860
    /*
1861
     * Documented, #range
1862
     */
1863
    public static List<Integer> range(int stop) {
1864
        return range(0, stop, 1);
1✔
1865
    }
1866

1867
    public static List<Integer> range(int start, int stop) {
1868
        return range(start, stop, start < stop ? 1 : -1);
1✔
1869
    }
1870

1871
    public static List<Integer> range(int start, int stop, int step) {
1872
        List<Integer> list = Underscore.newArrayList();
1✔
1873
        if (step == 0) {
1✔
1874
            return list;
1✔
1875
        }
1876
        if (start < stop) {
1✔
1877
            for (int value = start; value < stop; value += step) {
1✔
1878
                list.add(value);
1✔
1879
            }
1880
        } else {
1881
            for (int value = start; value > stop; value += step) {
1✔
1882
                list.add(value);
1✔
1883
            }
1884
        }
1885
        return list;
1✔
1886
    }
1887

1888
    public static List<Character> range(char stop) {
1889
        return range('a', stop, 1);
1✔
1890
    }
1891

1892
    public static List<Character> range(char start, char stop) {
1893
        return range(start, stop, start < stop ? 1 : -1);
1✔
1894
    }
1895

1896
    public static List<Character> range(char start, char stop, int step) {
1897
        List<Character> list = Underscore.newArrayList();
1✔
1898
        if (step == 0) {
1✔
1899
            return list;
1✔
1900
        }
1901
        if (start < stop) {
1✔
1902
            for (char value = start; value < stop; value += step) {
1✔
1903
                list.add(value);
1✔
1904
            }
1905
        } else {
1906
            for (char value = start; value > stop; value += step) {
1✔
1907
                list.add(value);
1✔
1908
            }
1909
        }
1910
        return list;
1✔
1911
    }
1912

1913
    public static <T> List<List<T>> chunk(final Iterable<T> iterable, final int size) {
1914
        if (size <= 0) {
1✔
1915
            return newArrayList();
1✔
1916
        }
1917
        return chunk(iterable, size, size);
1✔
1918
    }
1919

1920
    public static <T> List<List<T>> chunk(
1921
            final Iterable<T> iterable, final int size, final int step) {
1922
        if (step <= 0 || size < 0) {
1✔
1923
            return newArrayList();
1✔
1924
        }
1925
        int index = 0;
1✔
1926
        int length = size(iterable);
1✔
1927
        final List<List<T>> result = new ArrayList<>(size == 0 ? size : (length / size) + 1);
1✔
1928
        while (index < length) {
1✔
1929
            result.add(newArrayList(iterable).subList(index, Math.min(length, index + size)));
1✔
1930
            index += step;
1✔
1931
        }
1932
        return result;
1✔
1933
    }
1934

1935
    public static <T> List<List<T>> chunkFill(
1936
            final Iterable<T> iterable, final int size, final T fillValue) {
1937
        if (size <= 0) {
1✔
1938
            return newArrayList();
1✔
1939
        }
1940
        return chunkFill(iterable, size, size, fillValue);
1✔
1941
    }
1942

1943
    public static <T> List<List<T>> chunkFill(
1944
            final Iterable<T> iterable, final int size, final int step, final T fillValue) {
1945
        if (step <= 0 || size < 0) {
1✔
1946
            return newArrayList();
1✔
1947
        }
1948
        final List<List<T>> result = chunk(iterable, size, step);
1✔
1949
        int difference = size - result.get(result.size() - 1).size();
1✔
1950
        for (int i = difference; 0 < i; i--) {
1✔
1951
            result.get(result.size() - 1).add(fillValue);
1✔
1952
        }
1953
        return result;
1✔
1954
    }
1955

1956
    public List<List<T>> chunk(final int size) {
1957
        return chunk(getIterable(), size, size);
1✔
1958
    }
1959

1960
    public List<List<T>> chunk(final int size, final int step) {
1961
        return chunk(getIterable(), size, step);
1✔
1962
    }
1963

1964
    public List<List<T>> chunkFill(final int size, final T fillvalue) {
1965
        return chunkFill(getIterable(), size, size, fillvalue);
1✔
1966
    }
1967

1968
    public List<List<T>> chunkFill(final int size, final int step, T fillvalue) {
1969
        return chunkFill(getIterable(), size, step, fillvalue);
1✔
1970
    }
1971

1972
    public static <T> List<T> cycle(final Iterable<T> iterable, final int times) {
1973
        int size = Math.abs(size(iterable) * times);
1✔
1974
        if (size == 0) {
1✔
1975
            return newArrayList();
1✔
1976
        }
1977
        List<T> list = newArrayListWithExpectedSize(size);
1✔
1978
        int round = 0;
1✔
1979
        if (times > 0) {
1✔
1980
            while (round < times) {
1✔
1981
                for (T element : iterable) {
1✔
1982
                    list.add(element);
1✔
1983
                }
1✔
1984
                round++;
1✔
1985
            }
1986
        } else {
1987
            list = cycle(Underscore.reverse(iterable), -times);
1✔
1988
        }
1989
        return list;
1✔
1990
    }
1991

1992
    public List<T> cycle(final int times) {
1993
        return cycle(value(), times);
1✔
1994
    }
1995

1996
    public static <T> List<T> repeat(final T element, final int times) {
1997
        if (times <= 0) {
1✔
1998
            return newArrayList();
1✔
1999
        }
2000
        List<T> result = newArrayListWithExpectedSize(times);
1✔
2001
        for (int i = 0; i < times; i++) {
1✔
2002
            result.add(element);
1✔
2003
        }
2004
        return result;
1✔
2005
    }
2006

2007
    public static <T> List<T> interpose(final Iterable<T> iterable, final T interElement) {
2008
        if (interElement == null) {
1✔
2009
            return newArrayList(iterable);
1✔
2010
        }
2011
        int size = size(iterable);
1✔
2012
        int index = 0;
1✔
2013
        List<T> array = newArrayListWithExpectedSize(size * 2);
1✔
2014
        for (T elem : iterable) {
1✔
2015
            array.add(elem);
1✔
2016
            if (index + 1 < size) {
1✔
2017
                array.add(interElement);
1✔
2018
                index++;
1✔
2019
            }
2020
        }
1✔
2021
        return array;
1✔
2022
    }
2023

2024
    public static <T> List<T> interposeByList(
2025
            final Iterable<T> iterable, final Iterable<T> interIter) {
2026
        if (interIter == null) {
1✔
2027
            return newArrayList(iterable);
1✔
2028
        }
2029
        List<T> interList = newArrayList(interIter);
1✔
2030
        if (isEmpty(interIter)) {
1✔
2031
            return newArrayList(iterable);
1✔
2032
        }
2033
        int size = size(iterable);
1✔
2034
        List<T> array = newArrayListWithExpectedSize(size + interList.size());
1✔
2035
        int index = 0;
1✔
2036
        for (T element : iterable) {
1✔
2037
            array.add(element);
1✔
2038
            if (index < interList.size() && index + 1 < size) {
1✔
2039
                array.add(interList.get(index));
1✔
2040
                index++;
1✔
2041
            }
2042
        }
1✔
2043
        return array;
1✔
2044
    }
2045

2046
    public List<T> interpose(final T element) {
2047
        return interpose(value(), element);
1✔
2048
    }
2049

2050
    public List<T> interposeByList(final Iterable<T> interIter) {
2051
        return interposeByList(value(), interIter);
1✔
2052
    }
2053

2054
    /*
2055
     * Documented, #bind
2056
     */
2057
    public static <T, F> Function<F, T> bind(final Function<F, T> function) {
2058
        return function;
1✔
2059
    }
2060

2061
    /*
2062
     * Documented, #memoize
2063
     */
2064
    public static <T, F> Function<F, T> memoize(final Function<F, T> function) {
2065
        return new MemoizeFunction<>() {
1✔
2066
            @Override
2067
            public T calc(F arg) {
2068
                return function.apply(arg);
1✔
2069
            }
2070
        };
2071
    }
2072

2073
    /*
2074
     * Documented, #delay
2075
     */
2076
    public static <T> java.util.concurrent.ScheduledFuture<T> delay(
2077
            final Supplier<T> function, final int delayMilliseconds) {
2078
        final java.util.concurrent.ScheduledExecutorService scheduler =
2079
                java.util.concurrent.Executors.newSingleThreadScheduledExecutor();
1✔
2080
        final java.util.concurrent.ScheduledFuture<T> future =
1✔
2081
                scheduler.schedule(
1✔
2082
                        function::get,
1✔
2083
                        delayMilliseconds,
2084
                        java.util.concurrent.TimeUnit.MILLISECONDS);
2085
        scheduler.shutdown();
1✔
2086
        return future;
1✔
2087
    }
2088

2089
    public static <T> java.util.concurrent.ScheduledFuture<T> defer(final Supplier<T> function) {
2090
        return delay(function, 0);
1✔
2091
    }
2092

2093
    public static java.util.concurrent.ScheduledFuture<Void> defer(final Runnable runnable) {
2094
        return delay(
1✔
2095
                () -> {
2096
                    runnable.run();
1✔
2097
                    return null;
1✔
2098
                },
2099
                0);
2100
    }
2101

2102
    public static <T> Supplier<T> throttle(final Supplier<T> function, final int waitMilliseconds) {
2103
        class ThrottleLater implements Supplier<T> {
2104
            private final Supplier<T> localFunction;
2105
            private java.util.concurrent.ScheduledFuture<T> timeout;
2106
            private long previous;
2107

2108
            ThrottleLater(final Supplier<T> function) {
1✔
2109
                this.localFunction = function;
1✔
2110
            }
1✔
2111

2112
            @Override
2113
            public T get() {
2114
                previous = now();
1✔
2115
                timeout = null;
1✔
2116
                return localFunction.get();
1✔
2117
            }
2118

2119
            java.util.concurrent.ScheduledFuture<T> getTimeout() {
2120
                return timeout;
1✔
2121
            }
2122

2123
            void setTimeout(java.util.concurrent.ScheduledFuture<T> timeout) {
2124
                this.timeout = timeout;
1✔
2125
            }
1✔
2126

2127
            long getPrevious() {
2128
                return previous;
1✔
2129
            }
2130

2131
            void setPrevious(long previous) {
2132
                this.previous = previous;
1✔
2133
            }
1✔
2134
        }
2135

2136
        class ThrottleFunction implements Supplier<T> {
2137
            private final Supplier<T> localFunction;
2138
            private final ThrottleLater throttleLater;
2139

2140
            ThrottleFunction(final Supplier<T> function) {
1✔
2141
                this.localFunction = function;
1✔
2142
                this.throttleLater = new ThrottleLater(function);
1✔
2143
            }
1✔
2144

2145
            @Override
2146
            public T get() {
2147
                final long now = now();
1✔
2148
                if (throttleLater.getPrevious() == 0L) {
1✔
2149
                    throttleLater.setPrevious(now);
1✔
2150
                }
2151
                final long remaining = waitMilliseconds - (now - throttleLater.getPrevious());
1✔
2152
                T result = null;
1✔
2153
                if (remaining <= 0) {
1✔
2154
                    throttleLater.setPrevious(now);
1✔
2155
                    result = localFunction.get();
1✔
2156
                } else if (throttleLater.getTimeout() == null) {
1✔
2157
                    throttleLater.setTimeout(delay(throttleLater, waitMilliseconds));
1✔
2158
                }
2159
                return result;
1✔
2160
            }
2161
        }
2162
        return new ThrottleFunction(function);
1✔
2163
    }
2164

2165
    /*
2166
     * Documented, #debounce
2167
     */
2168
    public static <T> Supplier<T> debounce(
2169
            final Supplier<T> function, final int delayMilliseconds) {
2170
        return new Supplier<>() {
1✔
2171
            private java.util.concurrent.ScheduledFuture<T> timeout;
2172

2173
            @Override
2174
            public T get() {
2175
                clearTimeout(timeout);
1✔
2176
                timeout = delay(function, delayMilliseconds);
1✔
2177
                return null;
1✔
2178
            }
2179
        };
2180
    }
2181

2182
    /*
2183
     * Documented, #wrap
2184
     */
2185
    public static <T> Function<Void, T> wrap(
2186
            final UnaryOperator<T> function, final Function<UnaryOperator<T>, T> wrapper) {
2187
        return arg -> wrapper.apply(function);
1✔
2188
    }
2189

2190
    public static <E> Predicate<E> negate(final Predicate<E> pred) {
2191
        return item -> !pred.test(item);
1✔
2192
    }
2193

2194
    /*
2195
     * Documented, #compose
2196
     */
2197
    @SuppressWarnings("unchecked")
2198
    public static <T> Function<T, T> compose(final Function<T, T>... func) {
2199
        return arg -> {
1✔
2200
            T result = arg;
1✔
2201
            for (int index = func.length - 1; index >= 0; index -= 1) {
1✔
2202
                result = func[index].apply(result);
1✔
2203
            }
2204
            return result;
1✔
2205
        };
2206
    }
2207

2208
    /*
2209
     * Documented, #after
2210
     */
2211
    public static <E> Supplier<E> after(final int count, final Supplier<E> function) {
2212
        class AfterFunction implements Supplier<E> {
2213
            private final int count;
2214
            private final Supplier<E> localFunction;
2215
            private int index;
2216
            private E result;
2217

2218
            AfterFunction(final int count, final Supplier<E> function) {
1✔
2219
                this.count = count;
1✔
2220
                this.localFunction = function;
1✔
2221
            }
1✔
2222

2223
            public E get() {
2224
                if (++index >= count) {
1✔
2225
                    result = localFunction.get();
1✔
2226
                }
2227
                return result;
1✔
2228
            }
2229
        }
2230
        return new AfterFunction(count, function);
1✔
2231
    }
2232

2233
    /*
2234
     * Documented, #before
2235
     */
2236
    public static <E> Supplier<E> before(final int count, final Supplier<E> function) {
2237
        class BeforeFunction implements Supplier<E> {
2238
            private final int count;
2239
            private final Supplier<E> localFunction;
2240
            private int index;
2241
            private E result;
2242

2243
            BeforeFunction(final int count, final Supplier<E> function) {
1✔
2244
                this.count = count;
1✔
2245
                this.localFunction = function;
1✔
2246
            }
1✔
2247

2248
            public E get() {
2249
                if (++index <= count) {
1✔
2250
                    result = localFunction.get();
1✔
2251
                }
2252
                return result;
1✔
2253
            }
2254
        }
2255
        return new BeforeFunction(count, function);
1✔
2256
    }
2257

2258
    /*
2259
     * Documented, #once
2260
     */
2261
    public static <T> Supplier<T> once(final Supplier<T> function) {
2262
        return new Supplier<>() {
1✔
2263
            private volatile boolean executed;
2264
            private T result;
2265

2266
            @Override
2267
            public T get() {
2268
                if (!executed) {
1✔
2269
                    executed = true;
1✔
2270
                    result = function.get();
1✔
2271
                }
2272
                return result;
1✔
2273
            }
2274
        };
2275
    }
2276

2277
    /*
2278
     * Documented, #keys
2279
     */
2280
    public static <K, V> Set<K> keys(final Map<K, V> object) {
2281
        return object.keySet();
1✔
2282
    }
2283

2284
    /*
2285
     * Documented, #values
2286
     */
2287
    public static <K, V> Collection<V> values(final Map<K, V> object) {
2288
        return object.values();
1✔
2289
    }
2290

2291
    public static <K, V> List<Map.Entry<K, V>> mapObject(
2292
            final Map<K, V> object, final Function<? super V, V> func) {
2293
        return map(
1✔
2294
                newArrayList(object.entrySet()),
1✔
2295
                entry -> Map.entry(entry.getKey(), func.apply(entry.getValue())));
1✔
2296
    }
2297

2298
    /*
2299
     * Documented, #pairs
2300
     */
2301
    public static <K, V> List<Map.Entry<K, V>> pairs(final Map<K, V> object) {
2302
        return map(
1✔
2303
                newArrayList(object.entrySet()),
1✔
2304
                entry -> Map.entry(entry.getKey(), entry.getValue()));
1✔
2305
    }
2306

2307
    /*
2308
     * Documented, #invert
2309
     */
2310
    public static <K, V> List<Map.Entry<V, K>> invert(final Map<K, V> object) {
2311
        return map(
1✔
2312
                newArrayList(object.entrySet()),
1✔
2313
                entry -> Map.entry(entry.getValue(), entry.getKey()));
1✔
2314
    }
2315

2316
    /*
2317
     * Documented, #functions
2318
     */
2319
    public static List<String> functions(final Object object) {
2320
        final List<String> result = newArrayList();
1✔
2321
        for (final Method method : object.getClass().getDeclaredMethods()) {
1✔
2322
            result.add(method.getName());
1✔
2323
        }
2324
        return sort(uniq(result));
1✔
2325
    }
2326

2327
    public static List<String> methods(final Object object) {
2328
        return functions(object);
1✔
2329
    }
2330

2331
    /*
2332
     * Documented, #extend
2333
     */
2334
    @SuppressWarnings("unchecked")
2335
    public static <K, V> Map<K, V> extend(final Map<K, V> destination, final Map<K, V>... sources) {
2336
        final Map<K, V> result = newLinkedHashMap();
1✔
2337
        result.putAll(destination);
1✔
2338
        for (final Map<K, V> source : sources) {
1✔
2339
            result.putAll(source);
1✔
2340
        }
2341
        return result;
1✔
2342
    }
2343

2344
    public static <E> E findKey(final List<E> list, final Predicate<E> pred) {
2345
        for (E e : list) {
1✔
2346
            if (pred.test(e)) {
1✔
2347
                return e;
1✔
2348
            }
2349
        }
1✔
2350
        return null;
1✔
2351
    }
2352

2353
    public static <E> E findKey(final E[] array, final Predicate<E> pred) {
2354
        return findKey(Arrays.asList(array), pred);
1✔
2355
    }
2356

2357
    public static <E> E findLastKey(final List<E> list, final Predicate<E> pred) {
2358
        for (int index = list.size() - 1; index >= 0; index--) {
1✔
2359
            if (pred.test(list.get(index))) {
1✔
2360
                return list.get(index);
1✔
2361
            }
2362
        }
2363
        return null;
1✔
2364
    }
2365

2366
    public static <E> E findLastKey(final E[] array, final Predicate<E> pred) {
2367
        return findLastKey(Arrays.asList(array), pred);
1✔
2368
    }
2369

2370
    /*
2371
     * Documented, #pick
2372
     */
2373
    @SuppressWarnings("unchecked")
2374
    public static <K, V> List<Map.Entry<K, V>> pick(final Map<K, V> object, final K... keys) {
2375
        return without(
1✔
2376
                map(
1✔
2377
                        newArrayList(object.entrySet()),
1✔
2378
                        entry -> {
2379
                            if (Arrays.asList(keys).contains(entry.getKey())) {
1✔
2380
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2381
                            } else {
2382
                                return null;
1✔
2383
                            }
2384
                        }),
2385
                (Map.Entry<K, V>) null);
2386
    }
2387

2388
    @SuppressWarnings("unchecked")
2389
    public static <K, V> List<Map.Entry<K, V>> pick(
2390
            final Map<K, V> object, final Predicate<V> pred) {
2391
        return without(
1✔
2392
                map(
1✔
2393
                        newArrayList(object.entrySet()),
1✔
2394
                        entry -> {
2395
                            if (pred.test(object.get(entry.getKey()))) {
1✔
2396
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2397
                            } else {
2398
                                return null;
1✔
2399
                            }
2400
                        }),
2401
                (Map.Entry<K, V>) null);
2402
    }
2403

2404
    /*
2405
     * Documented, #omit
2406
     */
2407
    @SuppressWarnings("unchecked")
2408
    public static <K, V> List<Map.Entry<K, V>> omit(final Map<K, V> object, final K... keys) {
2409
        return without(
1✔
2410
                map(
1✔
2411
                        newArrayList(object.entrySet()),
1✔
2412
                        entry -> {
2413
                            if (Arrays.asList(keys).contains(entry.getKey())) {
1✔
2414
                                return null;
1✔
2415
                            } else {
2416
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2417
                            }
2418
                        }),
2419
                (Map.Entry<K, V>) null);
2420
    }
2421

2422
    @SuppressWarnings("unchecked")
2423
    public static <K, V> List<Map.Entry<K, V>> omit(
2424
            final Map<K, V> object, final Predicate<V> pred) {
2425
        return without(
1✔
2426
                map(
1✔
2427
                        newArrayList(object.entrySet()),
1✔
2428
                        entry -> {
2429
                            if (pred.test(entry.getValue())) {
1✔
2430
                                return null;
1✔
2431
                            } else {
2432
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2433
                            }
2434
                        }),
2435
                (Map.Entry<K, V>) null);
2436
    }
2437

2438
    /*
2439
     * Documented, #defaults
2440
     */
2441
    public static <K, V> Map<K, V> defaults(final Map<K, V> object, final Map<K, V> defaults) {
2442
        final Map<K, V> result = newLinkedHashMap();
1✔
2443
        result.putAll(defaults);
1✔
2444
        result.putAll(object);
1✔
2445
        return result;
1✔
2446
    }
2447

2448
    /*
2449
     * Documented, #clone
2450
     */
2451
    public static Object clone(final Object obj) {
2452
        try {
2453
            if (obj instanceof Cloneable) {
1✔
2454
                for (final Method method : obj.getClass().getMethods()) {
1✔
2455
                    if (method.getName().equals("clone")
1✔
2456
                            && method.getParameterTypes().length == 0) {
1✔
2457
                        return method.invoke(obj);
1✔
2458
                    }
2459
                }
2460
            }
2461
        } catch (Exception e) {
1✔
2462
            throw new IllegalArgumentException(e);
1✔
2463
        }
1✔
2464
        throw new IllegalArgumentException("Cannot clone object");
1✔
2465
    }
2466

2467
    @SuppressWarnings("unchecked")
2468
    public static <E> E[] clone(final E... iterable) {
2469
        return Arrays.copyOf(iterable, iterable.length);
1✔
2470
    }
2471

2472
    public static <T> void tap(final Iterable<T> iterable, final Consumer<? super T> func) {
2473
        each(iterable, func);
1✔
2474
    }
1✔
2475

2476
    public static <K, V> boolean isMatch(final Map<K, V> object, final Map<K, V> properties) {
2477
        for (final K key : keys(properties)) {
1✔
2478
            if (!object.containsKey(key) || !object.get(key).equals(properties.get(key))) {
1✔
2479
                return false;
1✔
2480
            }
2481
        }
1✔
2482
        return true;
1✔
2483
    }
2484

2485
    /*
2486
     * Documented, #isEqual
2487
     */
2488
    public static boolean isEqual(final Object object, final Object other) {
2489
        return Objects.equals(object, other);
1✔
2490
    }
2491

2492
    public static <K, V> boolean isEmpty(final Map<K, V> object) {
2493
        return object == null || object.isEmpty();
1✔
2494
    }
2495

2496
    /*
2497
     * Documented, #isEmpty
2498
     */
2499
    public static <T> boolean isEmpty(final Iterable<T> iterable) {
2500
        return iterable == null || !iterable.iterator().hasNext();
1✔
2501
    }
2502

2503
    public boolean isEmpty() {
2504
        return iterable == null || !iterable.iterator().hasNext();
1✔
2505
    }
2506

2507
    public static <K, V> boolean isNotEmpty(final Map<K, V> object) {
2508
        return object != null && !object.isEmpty();
1✔
2509
    }
2510

2511
    public static <T> boolean isNotEmpty(final Iterable<T> iterable) {
2512
        return iterable != null && iterable.iterator().hasNext();
1✔
2513
    }
2514

2515
    public boolean isNotEmpty() {
2516
        return iterable != null && iterable.iterator().hasNext();
1✔
2517
    }
2518

2519
    /*
2520
     * Documented, #isArray
2521
     */
2522
    public static boolean isArray(final Object object) {
2523
        return object != null && object.getClass().isArray();
1✔
2524
    }
2525

2526
    /*
2527
     * Documented, #isObject
2528
     */
2529
    public static boolean isObject(final Object object) {
2530
        return object instanceof Map;
1✔
2531
    }
2532

2533
    /*
2534
     * Documented, #isFunction
2535
     */
2536
    public static boolean isFunction(final Object object) {
2537
        return object instanceof Function;
1✔
2538
    }
2539

2540
    /*
2541
     * Documented, #isString
2542
     */
2543
    public static boolean isString(final Object object) {
2544
        return object instanceof String;
1✔
2545
    }
2546

2547
    /*
2548
     * Documented, #isNumber
2549
     */
2550
    public static boolean isNumber(final Object object) {
2551
        return object instanceof Number;
1✔
2552
    }
2553

2554
    /*
2555
     * Documented, #isDate
2556
     */
2557
    public static boolean isDate(final Object object) {
2558
        return object instanceof Date;
1✔
2559
    }
2560

2561
    public static boolean isRegExp(final Object object) {
2562
        return object instanceof java.util.regex.Pattern;
1✔
2563
    }
2564

2565
    public static boolean isError(final Object object) {
2566
        return object instanceof Throwable;
1✔
2567
    }
2568

2569
    /*
2570
     * Documented, #isBoolean
2571
     */
2572
    public static boolean isBoolean(final Object object) {
2573
        return object instanceof Boolean;
1✔
2574
    }
2575

2576
    public static boolean isNull(final Object object) {
2577
        return object == null;
1✔
2578
    }
2579

2580
    /*
2581
     * Documented, #has
2582
     */
2583
    public static <K, V> boolean has(final Map<K, V> object, final K key) {
2584
        return object.containsKey(key);
1✔
2585
    }
2586

2587
    public static <E> E identity(final E value) {
2588
        return value;
1✔
2589
    }
2590

2591
    public static <E> Supplier<E> constant(final E value) {
2592
        return () -> value;
1✔
2593
    }
2594

2595
    public static <K, V> Function<Map<K, V>, V> property(final K key) {
2596
        return object -> object.get(key);
1✔
2597
    }
2598

2599
    public static <K, V> Function<K, V> propertyOf(final Map<K, V> object) {
2600
        return object::get;
1✔
2601
    }
2602

2603
    public static <K, V> Predicate<Map<K, V>> matcher(final Map<K, V> object) {
2604
        return item -> {
1✔
2605
            for (final K key : keys(object)) {
1✔
2606
                if (!item.containsKey(key) || !item.get(key).equals(object.get(key))) {
1✔
2607
                    return false;
1✔
2608
                }
2609
            }
1✔
2610
            return true;
1✔
2611
        };
2612
    }
2613

2614
    /*
2615
     * Documented, #times
2616
     */
2617
    public static void times(final int count, final Runnable runnable) {
2618
        for (int index = 0; index < count; index += 1) {
1✔
2619
            runnable.run();
1✔
2620
        }
2621
    }
1✔
2622

2623
    /*
2624
     * Documented, #random
2625
     */
2626
    public static int random(final int min, final int max) {
2627
        return min + new java.security.SecureRandom().nextInt(max - min + 1);
1✔
2628
    }
2629

2630
    public static int random(final int max) {
2631
        return new java.security.SecureRandom().nextInt(max + 1);
1✔
2632
    }
2633

2634
    public static long now() {
2635
        return new Date().getTime();
1✔
2636
    }
2637

2638
    /*
2639
     * Documented, #escape
2640
     */
2641
    public static String escape(final String value) {
2642
        final StringBuilder builder = new StringBuilder();
1✔
2643
        for (final char ch : value.toCharArray()) {
1✔
2644
            builder.append(ESCAPES.containsKey(ch) ? ESCAPES.get(ch) : ch);
1✔
2645
        }
2646
        return builder.toString();
1✔
2647
    }
2648

2649
    public static String unescape(final String value) {
2650
        return value.replace("&#x60;", "`")
1✔
2651
                .replace("&#x27;", "'")
1✔
2652
                .replace("&lt;", "<")
1✔
2653
                .replace("&gt;", ">")
1✔
2654
                .replace("&quot;", "\"")
1✔
2655
                .replace("&amp;", "&");
1✔
2656
    }
2657

2658
    /*
2659
     * Documented, #result
2660
     */
2661
    public static <E> Object result(final Iterable<E> iterable, final Predicate<E> pred) {
2662
        for (E element : iterable) {
1✔
2663
            if (pred.test(element)) {
1✔
2664
                if (element instanceof Map.Entry) {
1✔
2665
                    if (((Map.Entry) element).getValue() instanceof Supplier) {
1✔
2666
                        return ((Supplier) ((Map.Entry) element).getValue()).get();
1✔
2667
                    }
2668
                    return ((Map.Entry) element).getValue();
1✔
2669
                }
2670
                return element;
1✔
2671
            }
2672
        }
1✔
2673
        return null;
1✔
2674
    }
2675

2676
    /*
2677
     * Documented, #uniqueId
2678
     */
2679
    public static String uniqueId(final String prefix) {
2680
        return (prefix == null ? "" : prefix) + UNIQUE_ID.incrementAndGet();
1✔
2681
    }
2682

2683
    /*
2684
     * Documented, #uniquePassword
2685
     */
2686
    public static String uniquePassword() {
2687
        final String[] passwords =
1✔
2688
                new String[] {
2689
                    "ALKJVBPIQYTUIWEBVPQALZVKQRWORTUYOYISHFLKAJMZNXBVMNFGAHKJSDFALAPOQIERIUYTGSFGKMZNXBVJAHGFAKX",
2690
                    "1234567890",
2691
                    "qpowiealksdjzmxnvbfghsdjtreiuowiruksfhksajmzxncbvlaksjdhgqwetytopskjhfgvbcnmzxalksjdfhgbvzm",
2692
                    ".@,-+/()#$%^&*!"
2693
                };
2694
        final StringBuilder result = new StringBuilder();
1✔
2695
        final long passwordLength =
2696
                Math.abs(UUID.randomUUID().getLeastSignificantBits() % MIN_PASSWORD_LENGTH_8)
1✔
2697
                        + MIN_PASSWORD_LENGTH_8;
2698
        for (int index = 0; index < passwordLength; index += 1) {
1✔
2699
            final int passIndex = (int) (passwords.length * (long) index / passwordLength);
1✔
2700
            final int charIndex =
2701
                    (int)
2702
                            Math.abs(
1✔
2703
                                    UUID.randomUUID().getLeastSignificantBits()
1✔
2704
                                            % passwords[passIndex].length());
1✔
2705
            result.append(passwords[passIndex].charAt(charIndex));
1✔
2706
        }
2707
        return result.toString();
1✔
2708
    }
2709

2710
    public static <K, V> Template<Map<K, V>> template(final String template) {
2711
        return new TemplateImpl<>(template);
1✔
2712
    }
2713

2714
    public static String format(final String template, final Object... params) {
2715
        final java.util.regex.Matcher matcher = FORMAT_PATTERN.matcher(template);
1✔
2716
        final StringBuffer buffer = new StringBuffer();
1✔
2717
        int index = 0;
1✔
2718
        while (matcher.find()) {
1✔
2719
            if (matcher.group(1).isEmpty()) {
1✔
2720
                matcher.appendReplacement(buffer, "<%" + index++ + "%>");
1✔
2721
            } else {
2722
                matcher.appendReplacement(buffer, "<%" + matcher.group(1) + "%>");
1✔
2723
            }
2724
        }
2725
        matcher.appendTail(buffer);
1✔
2726
        final String newTemplate = buffer.toString();
1✔
2727
        final Map<Integer, String> args = newLinkedHashMap();
1✔
2728
        index = 0;
1✔
2729
        for (Object param : params) {
1✔
2730
            args.put(index, param.toString());
1✔
2731
            index += 1;
1✔
2732
        }
2733
        return new TemplateImpl<Integer, String>(newTemplate).apply(args);
1✔
2734
    }
2735

2736
    public static <T> Iterable<T> iterate(final T seed, final UnaryOperator<T> unaryOperator) {
2737
        return new MyIterable<>(seed, unaryOperator);
1✔
2738
    }
2739

2740
    /*
2741
     * Documented, #chain
2742
     */
2743
    public static <T> Chain<T> chain(final List<T> list) {
2744
        return new Underscore.Chain<>(list);
1✔
2745
    }
2746

2747
    public static Chain<Map<String, Object>> chain(final Map<String, Object> map) {
2748
        return new Underscore.Chain<>(map);
1✔
2749
    }
2750

2751
    public static <T> Chain<T> chain(final Iterable<T> iterable) {
2752
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2753
    }
2754

2755
    public static <T> Chain<T> chain(final Iterable<T> iterable, int size) {
2756
        return new Underscore.Chain<>(newArrayList(iterable, size));
1✔
2757
    }
2758

2759
    @SuppressWarnings("unchecked")
2760
    public static <T> Chain<T> chain(final T... array) {
2761
        return new Underscore.Chain<>(Arrays.asList(array));
1✔
2762
    }
2763

2764
    public static Chain<Integer> chain(final int[] array) {
2765
        return new Underscore.Chain<>(newIntegerList(array));
1✔
2766
    }
2767

2768
    public Chain<T> chain() {
2769
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2770
    }
2771

2772
    public static <T> Chain<T> of(final List<T> list) {
2773
        return new Underscore.Chain<>(list);
1✔
2774
    }
2775

2776
    public static <T> Chain<T> of(final Iterable<T> iterable) {
2777
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2778
    }
2779

2780
    public static <T> Chain<T> of(final Iterable<T> iterable, int size) {
2781
        return new Underscore.Chain<>(newArrayList(iterable, size));
1✔
2782
    }
2783

2784
    @SuppressWarnings("unchecked")
2785
    public static <T> Chain<T> of(final T... array) {
2786
        return new Underscore.Chain<>(Arrays.asList(array));
1✔
2787
    }
2788

2789
    public static Chain<Integer> of(final int[] array) {
2790
        return new Underscore.Chain<>(newIntegerList(array));
1✔
2791
    }
2792

2793
    public Chain<T> of() {
2794
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2795
    }
2796

2797
    public static class Chain<T> {
2798
        private final T item;
2799
        private final List<T> list;
2800
        private final Map<String, Object> map;
2801

2802
        public Chain(final T item) {
1✔
2803
            this.item = item;
1✔
2804
            this.list = null;
1✔
2805
            this.map = null;
1✔
2806
        }
1✔
2807

2808
        public Chain(final List<T> list) {
1✔
2809
            this.item = null;
1✔
2810
            this.list = list;
1✔
2811
            this.map = null;
1✔
2812
        }
1✔
2813

2814
        public Chain(final Map<String, Object> map) {
1✔
2815
            this.item = null;
1✔
2816
            this.list = null;
1✔
2817
            this.map = map;
1✔
2818
        }
1✔
2819

2820
        public Chain<T> first() {
2821
            return new Chain<>(Underscore.first(list));
1✔
2822
        }
2823

2824
        public Chain<T> first(int n) {
2825
            return new Chain<>(Underscore.first(list, n));
1✔
2826
        }
2827

2828
        public Chain<T> first(final Predicate<T> pred) {
2829
            return new Chain<>(Underscore.first(list, pred));
1✔
2830
        }
2831

2832
        public Chain<T> first(final Predicate<T> pred, int n) {
2833
            return new Chain<>(Underscore.first(list, pred, n));
1✔
2834
        }
2835

2836
        public Chain<T> firstOrNull() {
2837
            return new Chain<>(Underscore.firstOrNull(list));
1✔
2838
        }
2839

2840
        public Chain<T> firstOrNull(final Predicate<T> pred) {
2841
            return new Chain<>(Underscore.firstOrNull(list, pred));
1✔
2842
        }
2843

2844
        public Chain<T> initial() {
2845
            return new Chain<>(Underscore.initial(list));
1✔
2846
        }
2847

2848
        public Chain<T> initial(int n) {
2849
            return new Chain<>(Underscore.initial(list, n));
1✔
2850
        }
2851

2852
        public Chain<T> last() {
2853
            return new Chain<>(Underscore.last(list));
1✔
2854
        }
2855

2856
        public Chain<T> last(int n) {
2857
            return new Chain<>(Underscore.last(list, n));
1✔
2858
        }
2859

2860
        public Chain<T> lastOrNull() {
2861
            return new Chain<>(Underscore.lastOrNull(list));
1✔
2862
        }
2863

2864
        public Chain<T> lastOrNull(final Predicate<T> pred) {
2865
            return new Chain<>(Underscore.lastOrNull(list, pred));
1✔
2866
        }
2867

2868
        public Chain<T> rest() {
2869
            return new Chain<>(Underscore.rest(list));
1✔
2870
        }
2871

2872
        public Chain<T> rest(int n) {
2873
            return new Chain<>(Underscore.rest(list, n));
1✔
2874
        }
2875

2876
        public Chain<T> compact() {
2877
            return new Chain<>(Underscore.compact(list));
1✔
2878
        }
2879

2880
        public Chain<T> compact(final T falsyValue) {
2881
            return new Chain<>(Underscore.compact(list, falsyValue));
1✔
2882
        }
2883

2884
        @SuppressWarnings("unchecked")
2885
        public Chain flatten() {
2886
            return new Chain<>(Underscore.flatten(list));
1✔
2887
        }
2888

2889
        public <F> Chain<F> map(final Function<? super T, F> func) {
2890
            return new Chain<>(Underscore.map(list, func));
1✔
2891
        }
2892

2893
        public <F> Chain<F> mapMulti(final BiConsumer<? super T, ? super Consumer<F>> mapper) {
2894
            return new Chain<>(Underscore.mapMulti(list, mapper));
1✔
2895
        }
2896

2897
        public <F> Chain<F> mapIndexed(final BiFunction<Integer, ? super T, F> func) {
2898
            return new Chain<>(Underscore.mapIndexed(list, func));
1✔
2899
        }
2900

2901
        public Chain<T> replace(final Predicate<T> pred, final T value) {
2902
            return new Chain<>(Underscore.replace(list, pred, value));
1✔
2903
        }
2904

2905
        public Chain<T> replaceIndexed(final PredicateIndexed<T> pred, final T value) {
2906
            return new Chain<>(Underscore.replaceIndexed(list, pred, value));
1✔
2907
        }
2908

2909
        public Chain<T> filter(final Predicate<T> pred) {
2910
            return new Chain<>(Underscore.filter(list, pred));
1✔
2911
        }
2912

2913
        public Chain<T> filterIndexed(final PredicateIndexed<T> pred) {
2914
            return new Chain<>(Underscore.filterIndexed(list, pred));
1✔
2915
        }
2916

2917
        public Chain<T> reject(final Predicate<T> pred) {
2918
            return new Chain<>(Underscore.reject(list, pred));
1✔
2919
        }
2920

2921
        public Chain<T> rejectIndexed(final PredicateIndexed<T> pred) {
2922
            return new Chain<>(Underscore.rejectIndexed(list, pred));
1✔
2923
        }
2924

2925
        public Chain<T> filterFalse(final Predicate<T> pred) {
2926
            return new Chain<>(Underscore.reject(list, pred));
1✔
2927
        }
2928

2929
        public <F> Chain<F> reduce(final BiFunction<F, T, F> func, final F zeroElem) {
2930
            return new Chain<>(Underscore.reduce(list, func, zeroElem));
1✔
2931
        }
2932

2933
        public Chain<Optional<T>> reduce(final BinaryOperator<T> func) {
2934
            return new Chain<>(Underscore.reduce(list, func));
1✔
2935
        }
2936

2937
        public <F> Chain<F> reduceRight(final BiFunction<F, T, F> func, final F zeroElem) {
2938
            return new Chain<>(Underscore.reduceRight(list, func, zeroElem));
1✔
2939
        }
2940

2941
        public Chain<Optional<T>> reduceRight(final BinaryOperator<T> func) {
2942
            return new Chain<>(Underscore.reduceRight(list, func));
1✔
2943
        }
2944

2945
        public Chain<Optional<T>> find(final Predicate<T> pred) {
2946
            return new Chain<>(Underscore.find(list, pred));
1✔
2947
        }
2948

2949
        public Chain<Optional<T>> findLast(final Predicate<T> pred) {
2950
            return new Chain<>(Underscore.findLast(list, pred));
1✔
2951
        }
2952

2953
        @SuppressWarnings("unchecked")
2954
        public Chain<Comparable> max() {
2955
            return new Chain<>(Underscore.max((Collection) list));
1✔
2956
        }
2957

2958
        public <F extends Comparable<? super F>> Chain<T> max(final Function<T, F> func) {
2959
            return new Chain<>(Underscore.max(list, func));
1✔
2960
        }
2961

2962
        @SuppressWarnings("unchecked")
2963
        public Chain<Comparable> min() {
2964
            return new Chain<>(Underscore.min((Collection) list));
1✔
2965
        }
2966

2967
        public <F extends Comparable<? super F>> Chain<T> min(final Function<T, F> func) {
2968
            return new Chain<>(Underscore.min(list, func));
1✔
2969
        }
2970

2971
        @SuppressWarnings("unchecked")
2972
        public Chain<Comparable> sort() {
2973
            return new Chain<>(Underscore.sort((List<Comparable>) list));
1✔
2974
        }
2975

2976
        @SuppressWarnings("unchecked")
2977
        public <F extends Comparable<? super F>> Chain<F> sortWith(final Comparator<F> comparator) {
2978
            return new Chain<>(Underscore.sortWith((List<F>) list, comparator));
1✔
2979
        }
2980

2981
        public <F extends Comparable<? super F>> Chain<T> sortBy(final Function<T, F> func) {
2982
            return new Chain<>(Underscore.sortBy(list, func));
1✔
2983
        }
2984

2985
        @SuppressWarnings("unchecked")
2986
        public <K> Chain<Map<K, Comparable>> sortBy(final K key) {
2987
            return new Chain<>(Underscore.sortBy((List<Map<K, Comparable>>) list, key));
1✔
2988
        }
2989

2990
        public <F> Chain<Map<F, List<T>>> groupBy(final Function<T, F> func) {
2991
            return new Chain<>(Underscore.groupBy(list, func));
1✔
2992
        }
2993

2994
        public <F> Chain<Map<F, Optional<T>>> groupBy(
2995
                final Function<T, F> func, final BinaryOperator<T> binaryOperator) {
2996
            return new Chain<>(Underscore.groupBy(list, func, binaryOperator));
1✔
2997
        }
2998

2999
        public Chain<Map<Object, List<T>>> indexBy(final String property) {
3000
            return new Chain<>(Underscore.indexBy(list, property));
1✔
3001
        }
3002

3003
        public <F> Chain<Map<F, Integer>> countBy(final Function<T, F> func) {
3004
            return new Chain<>(Underscore.countBy(list, func));
1✔
3005
        }
3006

3007
        public Chain<Map<T, Integer>> countBy() {
3008
            return new Chain<>(Underscore.countBy(list));
1✔
3009
        }
3010

3011
        public Chain<T> shuffle() {
3012
            return new Chain<>(Underscore.shuffle(list));
1✔
3013
        }
3014

3015
        public Chain<T> sample() {
3016
            return new Chain<>(Underscore.sample(list));
1✔
3017
        }
3018

3019
        public Chain<T> sample(final int howMany) {
3020
            return new Chain<>(Underscore.newArrayList(Underscore.sample(list, howMany)));
1✔
3021
        }
3022

3023
        public Chain<T> tap(final Consumer<T> func) {
3024
            Underscore.each(list, func);
1✔
3025
            return new Chain<>(list);
1✔
3026
        }
3027

3028
        public Chain<T> forEach(final Consumer<T> func) {
3029
            return tap(func);
1✔
3030
        }
3031

3032
        public Chain<T> forEachRight(final Consumer<T> func) {
3033
            Underscore.eachRight(list, func);
1✔
3034
            return new Chain<>(list);
1✔
3035
        }
3036

3037
        public Chain<Boolean> every(final Predicate<T> pred) {
3038
            return new Chain<>(Underscore.every(list, pred));
1✔
3039
        }
3040

3041
        public Chain<Boolean> some(final Predicate<T> pred) {
3042
            return new Chain<>(Underscore.some(list, pred));
1✔
3043
        }
3044

3045
        public Chain<Integer> count(final Predicate<T> pred) {
3046
            return new Chain<>(Underscore.count(list, pred));
1✔
3047
        }
3048

3049
        public Chain<Boolean> contains(final T elem) {
3050
            return new Chain<>(Underscore.contains(list, elem));
1✔
3051
        }
3052

3053
        public Chain<Boolean> containsWith(final T elem) {
3054
            return new Chain<>(Underscore.containsWith(list, elem));
1✔
3055
        }
3056

3057
        public Chain<T> invoke(final String methodName, final List<Object> args) {
3058
            return new Chain<>(Underscore.invoke(list, methodName, args));
1✔
3059
        }
3060

3061
        public Chain<T> invoke(final String methodName) {
3062
            return new Chain<>(Underscore.invoke(list, methodName));
1✔
3063
        }
3064

3065
        public Chain<Object> pluck(final String propertyName) {
3066
            return new Chain<>(Underscore.pluck(list, propertyName));
1✔
3067
        }
3068

3069
        public <E> Chain<T> where(final List<Map.Entry<String, E>> properties) {
3070
            return new Chain<>(Underscore.where(list, properties));
1✔
3071
        }
3072

3073
        public <E> Chain<Optional<T>> findWhere(final List<Map.Entry<String, E>> properties) {
3074
            return new Chain<>(Underscore.findWhere(list, properties));
1✔
3075
        }
3076

3077
        public Chain<T> uniq() {
3078
            return new Chain<>(Underscore.uniq(list));
1✔
3079
        }
3080

3081
        public <F> Chain<T> uniq(final Function<T, F> func) {
3082
            return new Chain<>(Underscore.newArrayList(Underscore.uniq(list, func)));
1✔
3083
        }
3084

3085
        public Chain<T> distinct() {
3086
            return new Chain<>(Underscore.uniq(list));
1✔
3087
        }
3088

3089
        @SuppressWarnings("unchecked")
3090
        public <F> Chain<F> distinctBy(final Function<T, F> func) {
3091
            return new Chain<>(Underscore.newArrayList((Iterable<F>) Underscore.uniq(list, func)));
1✔
3092
        }
3093

3094
        @SuppressWarnings("unchecked")
3095
        public Chain<T> union(final List<T>... lists) {
3096
            return new Chain<>(Underscore.union(list, lists));
1✔
3097
        }
3098

3099
        @SuppressWarnings("unchecked")
3100
        public Chain<T> intersection(final List<T>... lists) {
3101
            return new Chain<>(Underscore.intersection(list, lists));
1✔
3102
        }
3103

3104
        @SuppressWarnings("unchecked")
3105
        public Chain<T> difference(final List<T>... lists) {
3106
            return new Chain<>(Underscore.difference(list, lists));
1✔
3107
        }
3108

3109
        public Chain<Integer> range(final int stop) {
3110
            return new Chain<>(Underscore.range(stop));
1✔
3111
        }
3112

3113
        public Chain<Integer> range(final int start, final int stop) {
3114
            return new Chain<>(Underscore.range(start, stop));
1✔
3115
        }
3116

3117
        public Chain<Integer> range(final int start, final int stop, final int step) {
3118
            return new Chain<>(Underscore.range(start, stop, step));
1✔
3119
        }
3120

3121
        public Chain<List<T>> chunk(final int size) {
3122
            return new Chain<>(Underscore.chunk(value(), size, size));
1✔
3123
        }
3124

3125
        public Chain<List<T>> chunk(final int size, final int step) {
3126
            return new Chain<>(Underscore.chunk(value(), size, step));
1✔
3127
        }
3128

3129
        public Chain<List<T>> chunkFill(final int size, final T fillValue) {
3130
            return new Chain<>(Underscore.chunkFill(value(), size, size, fillValue));
1✔
3131
        }
3132

3133
        public Chain<List<T>> chunkFill(final int size, final int step, final T fillValue) {
3134
            return new Chain<>(Underscore.chunkFill(value(), size, step, fillValue));
1✔
3135
        }
3136

3137
        public Chain<T> cycle(final int times) {
3138
            return new Chain<>(Underscore.cycle(value(), times));
1✔
3139
        }
3140

3141
        public Chain<T> interpose(final T element) {
3142
            return new Chain<>(Underscore.interpose(value(), element));
1✔
3143
        }
3144

3145
        public Chain<T> interposeByList(final Iterable<T> interIter) {
3146
            return new Chain<>(Underscore.interposeByList(value(), interIter));
1✔
3147
        }
3148

3149
        @SuppressWarnings("unchecked")
3150
        public Chain<T> concat(final List<T>... lists) {
3151
            return new Chain<>(Underscore.concat(list, lists));
1✔
3152
        }
3153

3154
        public Chain<T> slice(final int start) {
3155
            return new Chain<>(Underscore.slice(list, start));
1✔
3156
        }
3157

3158
        public Chain<T> slice(final int start, final int end) {
3159
            return new Chain<>(Underscore.slice(list, start, end));
1✔
3160
        }
3161

3162
        public Chain<List<T>> splitAt(final int position) {
3163
            return new Chain<>(Underscore.splitAt(list, position));
1✔
3164
        }
3165

3166
        public Chain<T> takeSkipping(final int stepSize) {
3167
            return new Chain<>(Underscore.takeSkipping(list, stepSize));
1✔
3168
        }
3169

3170
        public Chain<T> reverse() {
3171
            return new Chain<>(Underscore.reverse(list));
1✔
3172
        }
3173

3174
        public Chain<String> join() {
3175
            return new Chain<>(Underscore.join(list));
1✔
3176
        }
3177

3178
        public Chain<String> join(final String separator) {
3179
            return new Chain<>(Underscore.join(list, separator));
1✔
3180
        }
3181

3182
        @SuppressWarnings("unchecked")
3183
        public Chain<T> push(final T... values) {
3184
            return new Chain<>(Underscore.push(value(), values));
1✔
3185
        }
3186

3187
        public Chain<Map.Entry<T, List<T>>> pop() {
3188
            return new Chain<>(Underscore.pop(value()));
1✔
3189
        }
3190

3191
        public Chain<Map.Entry<T, List<T>>> shift() {
3192
            return new Chain<>(Underscore.shift(value()));
1✔
3193
        }
3194

3195
        @SuppressWarnings("unchecked")
3196
        public Chain<T> unshift(final T... values) {
3197
            return new Chain<>(Underscore.unshift(value(), values));
1✔
3198
        }
3199

3200
        public Chain<T> skip(final int numberToSkip) {
3201
            return new Chain<>(list.subList(numberToSkip, list.size()));
1✔
3202
        }
3203

3204
        public Chain<T> limit(final int size) {
3205
            return new Chain<>(Underscore.first(list, size));
1✔
3206
        }
3207

3208
        @SuppressWarnings("unchecked")
3209
        public <K, V> Chain<Map<K, V>> toMap() {
3210
            return new Chain<>(Underscore.toMap((Iterable<Map.Entry<K, V>>) list));
1✔
3211
        }
3212

3213
        public boolean isEmpty() {
3214
            return Underscore.isEmpty(list);
1✔
3215
        }
3216

3217
        public boolean isNotEmpty() {
3218
            return Underscore.isNotEmpty(list);
1✔
3219
        }
3220

3221
        public int size() {
3222
            return Underscore.size(list);
1✔
3223
        }
3224

3225
        public T item() {
3226
            return item;
1✔
3227
        }
3228

3229
        /*
3230
         * Documented, #value
3231
         */
3232
        public List<T> value() {
3233
            return list;
1✔
3234
        }
3235

3236
        public Map<String, Object> map() {
3237
            return map;
1✔
3238
        }
3239

3240
        public List<T> toList() {
3241
            return list;
1✔
3242
        }
3243

3244
        public String toString() {
3245
            return String.valueOf(list);
1✔
3246
        }
3247
    }
3248

3249
    /*
3250
     * Documented, #mixin
3251
     */
3252
    public static void mixin(final String funcName, final UnaryOperator<String> func) {
3253
        FUNCTIONS.put(funcName, func);
1✔
3254
    }
1✔
3255

3256
    public Optional<String> call(final String funcName) {
3257
        if (string.isPresent() && FUNCTIONS.containsKey(funcName)) {
1✔
3258
            return Optional.of(FUNCTIONS.get(funcName).apply(string.get()));
1✔
3259
        }
3260
        return Optional.empty();
1✔
3261
    }
3262

3263
    public static <T extends Comparable<T>> List<T> sort(final Iterable<T> iterable) {
3264
        final List<T> localList = newArrayList(iterable);
1✔
3265
        Collections.sort(localList);
1✔
3266
        return localList;
1✔
3267
    }
3268

3269
    @SuppressWarnings("unchecked")
3270
    public static <T extends Comparable<T>> T[] sort(final T... array) {
3271
        final T[] localArray = array.clone();
1✔
3272
        Arrays.sort(localArray);
1✔
3273
        return localArray;
1✔
3274
    }
3275

3276
    @SuppressWarnings("unchecked")
3277
    public List<Comparable> sort() {
3278
        return sort((Iterable<Comparable>) iterable);
1✔
3279
    }
3280

3281
    /*
3282
     * Documented, #join
3283
     */
3284
    public static <T> String join(final Iterable<T> iterable, final String separator) {
3285
        final StringBuilder sb = new StringBuilder();
1✔
3286
        int index = 0;
1✔
3287
        for (final T item : iterable) {
1✔
3288
            if (index > 0) {
1✔
3289
                sb.append(separator);
1✔
3290
            }
3291
            sb.append(item.toString());
1✔
3292
            index += 1;
1✔
3293
        }
1✔
3294
        return sb.toString();
1✔
3295
    }
3296

3297
    public static <T> String join(final Iterable<T> iterable) {
3298
        return join(iterable, " ");
1✔
3299
    }
3300

3301
    public static <T> String join(final T[] array, final String separator) {
3302
        return join(Arrays.asList(array), separator);
1✔
3303
    }
3304

3305
    public static <T> String join(final T[] array) {
3306
        return join(array, " ");
1✔
3307
    }
3308

3309
    public String join(final String separator) {
3310
        return join(iterable, separator);
1✔
3311
    }
3312

3313
    public String join() {
3314
        return join(iterable);
1✔
3315
    }
3316

3317
    @SuppressWarnings("unchecked")
3318
    public static <T> List<T> push(final List<T> list, final T... values) {
3319
        final List<T> result = newArrayList(list);
1✔
3320
        Collections.addAll(result, values);
1✔
3321
        return result;
1✔
3322
    }
3323

3324
    @SuppressWarnings("unchecked")
3325
    public List<T> push(final T... values) {
3326
        return push((List<T>) getIterable(), values);
1✔
3327
    }
3328

3329
    public static <T> Map.Entry<T, List<T>> pop(final List<T> list) {
3330
        return Map.entry(last(list), initial(list));
1✔
3331
    }
3332

3333
    public Map.Entry<T, List<T>> pop() {
3334
        return pop((List<T>) getIterable());
1✔
3335
    }
3336

3337
    @SuppressWarnings("unchecked")
3338
    public static <T> List<T> unshift(final List<T> list, final T... values) {
3339
        final List<T> result = newArrayList(list);
1✔
3340
        int index = 0;
1✔
3341
        for (T value : values) {
1✔
3342
            result.add(index, value);
1✔
3343
            index += 1;
1✔
3344
        }
3345
        return result;
1✔
3346
    }
3347

3348
    @SuppressWarnings("unchecked")
3349
    public List<T> unshift(final T... values) {
3350
        return unshift((List<T>) getIterable(), values);
1✔
3351
    }
3352

3353
    public static <T> Map.Entry<T, List<T>> shift(final List<T> list) {
3354
        return Map.entry(first(list), rest(list));
1✔
3355
    }
3356

3357
    public Map.Entry<T, List<T>> shift() {
3358
        return shift((List<T>) getIterable());
1✔
3359
    }
3360

3361
    @SuppressWarnings("unchecked")
3362
    public static <T> T[] concat(final T[] first, final T[]... other) {
3363
        int length = 0;
1✔
3364
        for (T[] otherItem : other) {
1✔
3365
            length += otherItem.length;
1✔
3366
        }
3367
        final T[] result = Arrays.copyOf(first, first.length + length);
1✔
3368
        int index = 0;
1✔
3369
        for (T[] otherItem : other) {
1✔
3370
            System.arraycopy(otherItem, 0, result, first.length + index, otherItem.length);
1✔
3371
            index += otherItem.length;
1✔
3372
        }
3373
        return result;
1✔
3374
    }
3375

3376
    /*
3377
     * Documented, #concat
3378
     */
3379
    @SuppressWarnings("unchecked")
3380
    public static <T> List<T> concat(final Iterable<T> first, final Iterable<T>... other) {
3381
        List<T> list = newArrayList(first);
1✔
3382
        for (Iterable<T> iter : other) {
1✔
3383
            list.addAll(newArrayList(iter));
1✔
3384
        }
3385
        return list;
1✔
3386
    }
3387

3388
    @SuppressWarnings("unchecked")
3389
    public List<T> concatWith(final Iterable<T>... other) {
3390
        return concat(iterable, other);
1✔
3391
    }
3392

3393
    /*
3394
     * Documented, #slice
3395
     */
3396
    public static <T> List<T> slice(final Iterable<T> iterable, final int start) {
3397
        final List<T> result;
3398
        if (start >= 0) {
1✔
3399
            result = newArrayList(iterable).subList(start, size(iterable));
1✔
3400
        } else {
3401
            result = newArrayList(iterable).subList(size(iterable) + start, size(iterable));
1✔
3402
        }
3403
        return result;
1✔
3404
    }
3405

3406
    public static <T> T[] slice(final T[] array, final int start) {
3407
        final T[] result;
3408
        if (start >= 0) {
1✔
3409
            result = Arrays.copyOfRange(array, start, array.length);
1✔
3410
        } else {
3411
            result = Arrays.copyOfRange(array, array.length + start, array.length);
1✔
3412
        }
3413
        return result;
1✔
3414
    }
3415

3416
    public List<T> slice(final int start) {
3417
        return slice(iterable, start);
1✔
3418
    }
3419

3420
    public static <T> List<T> slice(final Iterable<T> iterable, final int start, final int end) {
3421
        final List<T> result;
3422
        if (start >= 0) {
1✔
3423
            if (end > 0) {
1✔
3424
                result = newArrayList(iterable).subList(start, end);
1✔
3425
            } else {
3426
                result = newArrayList(iterable).subList(start, size(iterable) + end);
1✔
3427
            }
3428
        } else {
3429
            if (end > 0) {
1✔
3430
                result = newArrayList(iterable).subList(size(iterable) + start, end);
1✔
3431
            } else {
3432
                result =
1✔
3433
                        newArrayList(iterable)
1✔
3434
                                .subList(size(iterable) + start, size(iterable) + end);
1✔
3435
            }
3436
        }
3437
        return result;
1✔
3438
    }
3439

3440
    public static <T> T[] slice(final T[] array, final int start, final int end) {
3441
        final T[] result;
3442
        if (start >= 0) {
1✔
3443
            if (end > 0) {
1✔
3444
                result = Arrays.copyOfRange(array, start, end);
1✔
3445
            } else {
3446
                result = Arrays.copyOfRange(array, start, array.length + end);
1✔
3447
            }
3448
        } else {
3449
            if (end > 0) {
1✔
3450
                result = Arrays.copyOfRange(array, array.length + start, end);
1✔
3451
            } else {
3452
                result = Arrays.copyOfRange(array, array.length + start, array.length + end);
1✔
3453
            }
3454
        }
3455
        return result;
1✔
3456
    }
3457

3458
    public List<T> slice(final int start, final int end) {
3459
        return slice(iterable, start, end);
1✔
3460
    }
3461

3462
    public static <T> List<List<T>> splitAt(final Iterable<T> iterable, final int position) {
3463
        List<List<T>> result = newArrayList();
1✔
3464
        int size = size(iterable);
1✔
3465
        final int index;
3466
        if (position < 0) {
1✔
3467
            index = 0;
1✔
3468
        } else {
3469
            index = position > size ? size : position;
1✔
3470
        }
3471
        result.add(newArrayList(iterable).subList(0, index));
1✔
3472
        result.add(newArrayList(iterable).subList(index, size));
1✔
3473
        return result;
1✔
3474
    }
3475

3476
    public static <T> List<List<T>> splitAt(final T[] array, final int position) {
3477
        return splitAt(Arrays.asList(array), position);
1✔
3478
    }
3479

3480
    public List<List<T>> splitAt(final int position) {
3481
        return splitAt(iterable, position);
1✔
3482
    }
3483

3484
    public static <T> List<T> takeSkipping(final Iterable<T> iterable, final int stepSize) {
3485
        List<T> result = newArrayList();
1✔
3486
        if (stepSize <= 0) {
1✔
3487
            return result;
1✔
3488
        }
3489
        int size = size(iterable);
1✔
3490
        if (stepSize > size) {
1✔
3491
            result.add(first(iterable));
1✔
3492
            return result;
1✔
3493
        }
3494
        int i = 0;
1✔
3495
        for (T element : iterable) {
1✔
3496
            if (i++ % stepSize == 0) {
1✔
3497
                result.add(element);
1✔
3498
            }
3499
        }
1✔
3500
        return result;
1✔
3501
    }
3502

3503
    public static <T> List<T> takeSkipping(final T[] array, final int stepSize) {
3504
        return takeSkipping(Arrays.asList(array), stepSize);
1✔
3505
    }
3506

3507
    public List<T> takeSkipping(final int stepSize) {
3508
        return takeSkipping(iterable, stepSize);
1✔
3509
    }
3510

3511
    /*
3512
     * Documented, #reverse
3513
     */
3514
    public static <T> List<T> reverse(final Iterable<T> iterable) {
3515
        final List<T> result = newArrayList(iterable);
1✔
3516
        Collections.reverse(result);
1✔
3517
        return result;
1✔
3518
    }
3519

3520
    @SuppressWarnings("unchecked")
3521
    public static <T> T[] reverse(final T... array) {
3522
        T temp;
3523
        final T[] newArray = array.clone();
1✔
3524
        for (int index = 0; index < array.length / 2; index += 1) {
1✔
3525
            temp = newArray[index];
1✔
3526
            newArray[index] = newArray[array.length - 1 - index];
1✔
3527
            newArray[array.length - 1 - index] = temp;
1✔
3528
        }
3529
        return newArray;
1✔
3530
    }
3531

3532
    public static List<Integer> reverse(final int[] array) {
3533
        final List<Integer> result = newIntegerList(array);
1✔
3534
        Collections.reverse(result);
1✔
3535
        return result;
1✔
3536
    }
3537

3538
    public List<T> reverse() {
3539
        return reverse(iterable);
1✔
3540
    }
3541

3542
    public Iterable<T> getIterable() {
3543
        return iterable;
1✔
3544
    }
3545

3546
    public Iterable<T> value() {
3547
        return iterable;
1✔
3548
    }
3549

3550
    public Optional<String> getString() {
3551
        return string;
1✔
3552
    }
3553

3554
    public static <T> java.util.concurrent.ScheduledFuture<T> setTimeout(
3555
            final Supplier<T> function, final int delayMilliseconds) {
3556
        return delay(function, delayMilliseconds);
1✔
3557
    }
3558

3559
    public static void clearTimeout(java.util.concurrent.ScheduledFuture<?> scheduledFuture) {
3560
        if (scheduledFuture != null) {
1✔
3561
            scheduledFuture.cancel(true);
1✔
3562
        }
3563
    }
1✔
3564

3565
    public static <T> java.util.concurrent.ScheduledFuture setInterval(
3566
            final Supplier<T> function, final int delayMilliseconds) {
3567
        final java.util.concurrent.ScheduledExecutorService scheduler =
3568
                java.util.concurrent.Executors.newSingleThreadScheduledExecutor();
1✔
3569
        return scheduler.scheduleAtFixedRate(
1✔
3570
                function::get,
1✔
3571
                delayMilliseconds,
3572
                delayMilliseconds,
3573
                java.util.concurrent.TimeUnit.MILLISECONDS);
3574
    }
3575

3576
    public static void clearInterval(java.util.concurrent.ScheduledFuture scheduledFuture) {
3577
        clearTimeout(scheduledFuture);
1✔
3578
    }
1✔
3579

3580
    public static <T> List<T> copyOf(final Iterable<T> iterable) {
3581
        return newArrayList(iterable);
1✔
3582
    }
3583

3584
    public List<T> copyOf() {
3585
        return newArrayList(value());
1✔
3586
    }
3587

3588
    public static <T> List<T> copyOfRange(
3589
            final Iterable<T> iterable, final int start, final int end) {
3590
        return slice(iterable, start, end);
1✔
3591
    }
3592

3593
    public List<T> copyOfRange(final int start, final int end) {
3594
        return slice(value(), start, end);
1✔
3595
    }
3596

3597
    public static <T> T elementAt(final List<T> list, final int index) {
3598
        return list.get(index);
1✔
3599
    }
3600

3601
    public T elementAt(final int index) {
3602
        return elementAt((List<T>) value(), index);
1✔
3603
    }
3604

3605
    public static <T> T get(final List<T> list, final int index) {
3606
        return elementAt(list, index);
1✔
3607
    }
3608

3609
    public T get(final int index) {
3610
        return elementAt((List<T>) value(), index);
1✔
3611
    }
3612

3613
    public static <T> Map.Entry<T, List<T>> set(
3614
            final List<T> list, final int index, final T value) {
3615
        final List<T> newList = newArrayList(list);
1✔
3616
        return Map.entry(newList.set(index, value), newList);
1✔
3617
    }
3618

3619
    public Map.Entry<T, List<T>> set(final int index, final T value) {
3620
        return set((List<T>) value(), index, value);
1✔
3621
    }
3622

3623
    public static <T> T elementAtOrElse(final List<T> list, final int index, T defaultValue) {
3624
        try {
3625
            return list.get(index);
1✔
3626
        } catch (IndexOutOfBoundsException ex) {
1✔
3627
            return defaultValue;
1✔
3628
        }
3629
    }
3630

3631
    public T elementAtOrElse(final int index, T defaultValue) {
3632
        return elementAtOrElse((List<T>) value(), index, defaultValue);
1✔
3633
    }
3634

3635
    public static <T> T elementAtOrNull(final List<T> list, final int index) {
3636
        try {
3637
            return list.get(index);
1✔
3638
        } catch (IndexOutOfBoundsException ex) {
1✔
3639
            return null;
1✔
3640
        }
3641
    }
3642

3643
    public T elementAtOrNull(final int index) {
3644
        return elementAtOrNull((List<T>) value(), index);
1✔
3645
    }
3646

3647
    public static <T> int lastIndex(final Iterable<T> iterable) {
3648
        return size(iterable) - 1;
1✔
3649
    }
3650

3651
    public static <T> int lastIndex(final T[] array) {
3652
        return array.length - 1;
1✔
3653
    }
3654

3655
    public static int lastIndex(final int[] array) {
3656
        return array.length - 1;
1✔
3657
    }
3658

3659
    public static <T> T checkNotNull(T reference) {
3660
        if (reference == null) {
1✔
3661
            throw new NullPointerException();
1✔
3662
        }
3663
        return reference;
1✔
3664
    }
3665

3666
    public static <T> List<T> checkNotNullElements(List<T> references) {
3667
        if (references == null) {
1✔
3668
            throw new NullPointerException();
1✔
3669
        }
3670
        for (T reference : references) {
1✔
3671
            checkNotNull(reference);
1✔
3672
        }
1✔
3673
        return references;
1✔
3674
    }
3675

3676
    public static <T> T checkNotNull(T reference, Object errorMessage) {
3677
        if (reference == null) {
1✔
3678
            throw new NullPointerException(String.valueOf(errorMessage));
1✔
3679
        }
3680
        return reference;
1✔
3681
    }
3682

3683
    public static boolean nonNull(Object obj) {
3684
        return obj != null;
1✔
3685
    }
3686

3687
    public static <T> T defaultTo(T value, T defaultValue) {
3688
        if (value == null) {
1✔
3689
            return defaultValue;
1✔
3690
        }
3691
        return value;
1✔
3692
    }
3693

3694
    protected static <T> List<T> newArrayList() {
3695
        return new ArrayList<>();
1✔
3696
    }
3697

3698
    protected static <T> List<T> newArrayList(final Iterable<T> iterable) {
3699
        final List<T> result;
3700
        if (iterable instanceof Collection) {
1✔
3701
            result = new ArrayList<>((Collection<T>) iterable);
1✔
3702
        } else {
3703
            result = new ArrayList<>();
1✔
3704
            for (final T item : iterable) {
1✔
3705
                result.add(item);
1✔
3706
            }
1✔
3707
        }
3708
        return result;
1✔
3709
    }
3710

3711
    protected static <T> List<T> newArrayList(final T object) {
3712
        final List<T> result = new ArrayList<>();
1✔
3713
        result.add(object);
1✔
3714
        return result;
1✔
3715
    }
3716

3717
    protected static <T> List<T> newArrayList(final Iterable<T> iterable, final int size) {
3718
        final List<T> result = new ArrayList<>();
1✔
3719
        for (int index = 0; iterable.iterator().hasNext() && index < size; index += 1) {
1✔
3720
            result.add(iterable.iterator().next());
1✔
3721
        }
3722
        return result;
1✔
3723
    }
3724

3725
    protected static List<Integer> newIntegerList(int... array) {
3726
        final List<Integer> result = new ArrayList<>(array.length);
1✔
3727
        for (final int item : array) {
1✔
3728
            result.add(item);
1✔
3729
        }
3730
        return result;
1✔
3731
    }
3732

3733
    protected static <T> List<T> newArrayListWithExpectedSize(int size) {
3734
        return new ArrayList<>((int) (CAPACITY_SIZE_5 + size + (size / 10)));
1✔
3735
    }
3736

3737
    protected static <T> Set<T> newLinkedHashSet() {
3738
        return new LinkedHashSet<>();
1✔
3739
    }
3740

3741
    protected static <T> Set<T> newLinkedHashSet(Iterable<T> iterable) {
3742
        final Set<T> result = new LinkedHashSet<>();
1✔
3743
        for (final T item : iterable) {
1✔
3744
            result.add(item);
1✔
3745
        }
1✔
3746
        return result;
1✔
3747
    }
3748

3749
    protected static <T> Set<T> newLinkedHashSetWithExpectedSize(int size) {
3750
        return new LinkedHashSet<>((int) Math.max(size * CAPACITY_COEFF_2, CAPACITY_SIZE_16));
1✔
3751
    }
3752

3753
    protected static <K, E> Map<K, E> newLinkedHashMap() {
3754
        return new LinkedHashMap<>();
1✔
3755
    }
3756

3757
    @SuppressWarnings("unchecked")
3758
    public static <T> Predicate<T> and(
3759
            final Predicate<? super T> pred1,
3760
            final Predicate<? super T> pred2,
3761
            final Predicate<? super T>... rest) {
3762
        checkNotNull(pred1);
1✔
3763
        checkNotNull(pred2);
1✔
3764
        checkNotNullElements(Arrays.asList(rest));
1✔
3765
        return value -> {
1✔
3766
            boolean result = pred1.test(value) && pred2.test(value);
1✔
3767
            if (!result) {
1✔
3768
                return false;
1✔
3769
            }
3770
            for (Predicate<? super T> predicate : rest) {
1✔
3771
                if (!predicate.test(value)) {
1✔
3772
                    return false;
1✔
3773
                }
3774
            }
3775
            return true;
1✔
3776
        };
3777
    }
3778

3779
    @SuppressWarnings("unchecked")
3780
    public static <T> Predicate<T> or(
3781
            final Predicate<? super T> pred1,
3782
            final Predicate<? super T> pred2,
3783
            final Predicate<? super T>... rest) {
3784
        checkNotNull(pred1);
1✔
3785
        checkNotNull(pred2);
1✔
3786
        checkNotNullElements(Arrays.asList(rest));
1✔
3787
        return value -> {
1✔
3788
            boolean result = pred1.test(value) || pred2.test(value);
1✔
3789
            if (result) {
1✔
3790
                return true;
1✔
3791
            }
3792
            for (Predicate<? super T> predicate : rest) {
1✔
3793
                if (predicate.test(value)) {
1✔
3794
                    return true;
1✔
3795
                }
3796
            }
3797
            return false;
1✔
3798
        };
3799
    }
3800

3801
    public static void main(String... args) {
3802
        final String message =
1✔
3803
                "Underscore-java is a java port of Underscore.js.\n\n"
3804
                        + "In addition to porting Underscore's functionality,"
3805
                        + " Underscore-java includes matching unit tests.\n\n"
3806
                        + "For docs, license, tests, and downloads, see: https://javadev.github.io/underscore-java";
3807
        System.out.println(message);
1✔
3808
    }
1✔
3809

3810
    public static interface Function3<F1, F2, F3, T> {
3811
        T apply(F1 arg1, F2 arg2, F3 arg3);
3812
    }
3813

3814
    public abstract static class MemoizeFunction<F, T> implements Function<F, T> {
1✔
3815
        private final Map<F, T> cache = new LinkedHashMap<>();
1✔
3816

3817
        public abstract T calc(final F n);
3818

3819
        public T apply(final F key) {
3820
            cache.putIfAbsent(key, calc(key));
1✔
3821
            return cache.get(key);
1✔
3822
        }
3823
    }
3824

3825
    public static interface PredicateIndexed<T> {
3826
        boolean test(int index, T arg);
3827
    }
3828

3829
    public static interface Template<T> extends Function<T, String> {
3830
        List<String> check(T arg);
3831
    }
3832
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc