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

javadev / underscore-java / #4211

04 Jun 2025 06:13PM CUT coverage: 100.0%. Remained the same
#4211

push

web-flow
Spring boot 3.5.0

4519 of 4519 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-2025 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.Optional;
45
import java.util.Set;
46
import java.util.UUID;
47
import java.util.function.BiConsumer;
48
import java.util.function.BiFunction;
49
import java.util.function.BinaryOperator;
50
import java.util.function.Consumer;
51
import java.util.function.Function;
52
import java.util.function.Predicate;
53
import java.util.function.Supplier;
54
import java.util.function.UnaryOperator;
55

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

90
    static {
91
        TEMPLATE_SETTINGS.put(EVALUATE, "<%([\\s\\S]+?)%>");
1✔
92
        TEMPLATE_SETTINGS.put(INTERPOLATE, "<%=([\\s\\S]+?)%>");
1✔
93
        TEMPLATE_SETTINGS.put(ESCAPE, "<%-([\\s\\S]+?)%>");
1✔
94
        ESCAPES.put('&', "&amp;");
1✔
95
        ESCAPES.put('<', "&lt;");
1✔
96
        ESCAPES.put('>', "&gt;");
1✔
97
        ESCAPES.put('"', "&quot;");
1✔
98
        ESCAPES.put('\'', "&#x27;");
1✔
99
        ESCAPES.put('`', "&#x60;");
1✔
100
    }
1✔
101

102
    public Underscore(final Iterable<T> iterable) {
1✔
103
        this.iterable = iterable;
1✔
104
        this.string = Optional.empty();
1✔
105
    }
1✔
106

107
    public Underscore(final String string) {
1✔
108
        this.iterable = null;
1✔
109
        this.string = Optional.of(string);
1✔
110
    }
1✔
111

112
    private static void setTemplateKey(
113
            final Map<String, String> templateSettings, final String key) {
114
        if (templateSettings.containsKey(key) && templateSettings.get(key).contains(ALL_SYMBOLS)) {
1✔
115
            TEMPLATE_SETTINGS.put(key, templateSettings.get(key));
1✔
116
        }
117
    }
1✔
118

119
    public static void templateSettings(final Map<String, String> templateSettings) {
120
        setTemplateKey(templateSettings, EVALUATE);
1✔
121
        setTemplateKey(templateSettings, INTERPOLATE);
1✔
122
        setTemplateKey(templateSettings, ESCAPE);
1✔
123
    }
1✔
124

125
    private static final class WherePredicate<E, T> implements Predicate<E> {
126
        private final List<Map.Entry<String, T>> properties;
127

128
        private WherePredicate(List<Map.Entry<String, T>> properties) {
1✔
129
            this.properties = properties;
1✔
130
        }
1✔
131

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

159
    private static final class TemplateImpl<K, V> implements Template<Map<K, V>> {
160
        private final String template;
161

162
        private TemplateImpl(String template) {
1✔
163
            this.template = template;
1✔
164
        }
1✔
165

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

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

251
    private static final class MyIterable<T> implements Iterable<T> {
252
        private final UnaryOperator<T> unaryOperator;
253
        private boolean firstRun = true;
1✔
254
        private T value;
255

256
        MyIterable(final T seed, final UnaryOperator<T> unaryOperator) {
1✔
257
            this.value = seed;
1✔
258
            this.unaryOperator = unaryOperator;
1✔
259
        }
1✔
260

261
        public Iterator<T> iterator() {
262
            return new Iterator<>() {
1✔
263
                @Override
264
                public boolean hasNext() {
265
                    return true;
1✔
266
                }
267

268
                @Override
269
                public T next() {
270
                    if (firstRun) {
1✔
271
                        firstRun = false;
1✔
272
                    } else {
273
                        value = unaryOperator.apply(value);
1✔
274
                    }
275
                    return value;
1✔
276
                }
277

278
                @Override
279
                public void remove() {
280
                    // ignored
281
                }
1✔
282
            };
283
        }
284
    }
285

286
    public static <K, V> Function<Map<K, V>, V> iteratee(final K key) {
287
        return item -> item.get(key);
1✔
288
    }
289

290
    /*
291
     * Documented, #each
292
     */
293
    public static <T> void each(final Iterable<T> iterable, final Consumer<? super T> func) {
294
        for (T element : iterable) {
1✔
295
            func.accept(element);
1✔
296
        }
1✔
297
    }
1✔
298

299
    public static <T> void eachIndexed(
300
            final Iterable<T> iterable, final BiConsumer<Integer, ? super T> func) {
301
        int index = 0;
1✔
302
        for (T element : iterable) {
1✔
303
            func.accept(index, element);
1✔
304
            index += 1;
1✔
305
        }
1✔
306
    }
1✔
307

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

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

316
    public void eachRight(final Consumer<? super T> func) {
317
        eachRight(iterable, func);
1✔
318
    }
1✔
319

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

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

329
    public void forEach(final Consumer<? super T> func) {
330
        each(iterable, func);
1✔
331
    }
1✔
332

333
    public void forEachIndexed(final BiConsumer<Integer, ? super T> func) {
334
        eachIndexed(iterable, func);
1✔
335
    }
1✔
336

337
    public static <T> void forEachRight(
338
            final Iterable<T> iterable, final Consumer<? super T> func) {
339
        eachRight(iterable, func);
1✔
340
    }
1✔
341

342
    public void forEachRight(final Consumer<? super T> func) {
343
        eachRight(iterable, func);
1✔
344
    }
1✔
345

346
    /*
347
     * Documented, #map
348
     */
349
    public static <T, E> List<T> map(final List<E> list, final Function<? super E, T> func) {
350
        final List<T> transformed = newArrayListWithExpectedSize(list.size());
1✔
351
        for (E element : list) {
1✔
352
            transformed.add(func.apply(element));
1✔
353
        }
1✔
354
        return transformed;
1✔
355
    }
356

357
    public static <T, E> List<T> mapMulti(
358
            final List<E> list, final BiConsumer<? super E, ? super Consumer<T>> mapper) {
359
        final List<T> transformed = newArrayListWithExpectedSize(list.size());
1✔
360
        for (E element : list) {
1✔
361
            Consumer<T> value = transformed::add;
1✔
362
            mapper.accept(element, value);
1✔
363
        }
1✔
364
        return transformed;
1✔
365
    }
366

367
    public <F> List<F> map(final Function<? super T, F> func) {
368
        return map(newArrayList(iterable), func);
1✔
369
    }
370

371
    public static <T> List<T> map(final int[] array, final Function<? super Integer, T> func) {
372
        final List<T> transformed = newArrayListWithExpectedSize(array.length);
1✔
373
        for (int element : array) {
1✔
374
            transformed.add(func.apply(element));
1✔
375
        }
376
        return transformed;
1✔
377
    }
378

379
    public static <T, E> Set<T> map(final Set<E> set, final Function<? super E, T> func) {
380
        final Set<T> transformed = newLinkedHashSetWithExpectedSize(set.size());
1✔
381
        for (E element : set) {
1✔
382
            transformed.add(func.apply(element));
1✔
383
        }
1✔
384
        return transformed;
1✔
385
    }
386

387
    public static <T, E> List<T> mapIndexed(
388
            final List<E> list, final BiFunction<Integer, ? super E, T> func) {
389
        final List<T> transformed = newArrayListWithExpectedSize(list.size());
1✔
390
        int index = 0;
1✔
391
        for (E element : list) {
1✔
392
            transformed.add(func.apply(index, element));
1✔
393
            index += 1;
1✔
394
        }
1✔
395
        return transformed;
1✔
396
    }
397

398
    public static <T> List<T> replace(
399
            final Iterable<T> iter, final Predicate<T> pred, final T value) {
400
        List<T> list = newArrayList(iter);
1✔
401
        if (pred == null) {
1✔
402
            return list;
1✔
403
        }
404
        ListIterator<T> itera = list.listIterator();
1✔
405
        while (itera.hasNext()) {
1✔
406
            if (pred.test(itera.next())) {
1✔
407
                itera.set(value);
1✔
408
            }
409
        }
410
        return list;
1✔
411
    }
412

413
    public List<T> replace(final Predicate<T> pred, final T value) {
414
        return replace(value(), pred, value);
1✔
415
    }
416

417
    public static <T> List<T> replaceIndexed(
418
            final Iterable<T> iter, final PredicateIndexed<T> pred, final T value) {
419
        List<T> list = newArrayList(iter);
1✔
420
        if (pred == null) {
1✔
421
            return list;
1✔
422
        }
423
        ListIterator<T> itera = list.listIterator();
1✔
424
        int index = 0;
1✔
425
        while (itera.hasNext()) {
1✔
426
            if (pred.test(index, itera.next())) {
1✔
427
                itera.set(value);
1✔
428
            }
429
            index++;
1✔
430
        }
431
        return list;
1✔
432
    }
433

434
    public List<T> replaceIndexed(final PredicateIndexed<T> pred, final T value) {
435
        return replaceIndexed(value(), pred, value);
1✔
436
    }
437

438
    public <F> List<F> mapIndexed(final BiFunction<Integer, ? super T, F> func) {
439
        return mapIndexed(newArrayList(iterable), func);
1✔
440
    }
441

442
    public static <T, E> List<T> collect(final List<E> list, final Function<? super E, T> func) {
443
        return map(list, func);
1✔
444
    }
445

446
    public static <T, E> Set<T> collect(final Set<E> set, final Function<? super E, T> func) {
447
        return map(set, func);
1✔
448
    }
449

450
    /*
451
     * Documented, #reduce
452
     */
453
    public static <T, E> E reduce(
454
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
455
        E accum = zeroElem;
1✔
456
        for (T element : iterable) {
1✔
457
            accum = func.apply(accum, element);
1✔
458
        }
1✔
459
        return accum;
1✔
460
    }
461

462
    public static <T> Optional<T> reduce(final Iterable<T> iterable, final BinaryOperator<T> func) {
463
        boolean foundAny = false;
1✔
464
        T accum = null;
1✔
465
        for (T element : iterable) {
1✔
466
            if (foundAny) {
1✔
467
                accum = func.apply(accum, element);
1✔
468
            } else {
469
                foundAny = true;
1✔
470
                accum = element;
1✔
471
            }
472
        }
1✔
473
        return foundAny ? Optional.of(accum) : Optional.empty();
1✔
474
    }
475

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

485
    public static <T, E> E reduce(
486
            final T[] array, final BiFunction<E, T, E> func, final E zeroElem) {
487
        E accum = zeroElem;
1✔
488
        for (T element : array) {
1✔
489
            accum = func.apply(accum, element);
1✔
490
        }
491
        return accum;
1✔
492
    }
493

494
    public static <T, E> E foldl(
495
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
496
        return reduce(iterable, func, zeroElem);
1✔
497
    }
498

499
    public static <T, E> E inject(
500
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
501
        return reduce(iterable, func, zeroElem);
1✔
502
    }
503

504
    /*
505
     * Documented, #reduceRight
506
     */
507
    public static <T, E> E reduceRight(
508
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
509
        return reduce(reverse(iterable), func, zeroElem);
1✔
510
    }
511

512
    public static <T> Optional<T> reduceRight(
513
            final Iterable<T> iterable, final BinaryOperator<T> func) {
514
        return reduce(reverse(iterable), func);
1✔
515
    }
516

517
    public static <E> E reduceRight(
518
            final int[] array, final BiFunction<E, ? super Integer, E> func, final E zeroElem) {
519
        E accum = zeroElem;
1✔
520
        for (Integer element : reverse(array)) {
1✔
521
            accum = func.apply(accum, element);
1✔
522
        }
1✔
523
        return accum;
1✔
524
    }
525

526
    public static <T, E> E reduceRight(
527
            final T[] array, final BiFunction<E, T, E> func, final E zeroElem) {
528
        return reduce(reverse(array), func, zeroElem);
1✔
529
    }
530

531
    public static <T, E> E foldr(
532
            final Iterable<T> iterable, final BiFunction<E, T, E> func, final E zeroElem) {
533
        return reduceRight(iterable, func, zeroElem);
1✔
534
    }
535

536
    /*
537
     * Documented, #find
538
     */
539
    public static <E> Optional<E> find(final Iterable<E> iterable, final Predicate<E> pred) {
540
        for (E element : iterable) {
1✔
541
            if (pred.test(element)) {
1✔
542
                return isNull(element) ? null : Optional.of(element);
1✔
543
            }
544
        }
1✔
545
        return Optional.empty();
1✔
546
    }
547

548
    public static <E> Optional<E> detect(final Iterable<E> iterable, final Predicate<E> pred) {
549
        return find(iterable, pred);
1✔
550
    }
551

552
    public static <E> Optional<E> findLast(final Iterable<E> iterable, final Predicate<E> pred) {
553
        return find(reverse(iterable), pred);
1✔
554
    }
555

556
    /*
557
     * Documented, #filter
558
     */
559
    public static <E> List<E> filter(final Iterable<E> iterable, final Predicate<E> pred) {
560
        final List<E> filtered = new ArrayList<>();
1✔
561
        for (E element : iterable) {
1✔
562
            if (pred.test(element)) {
1✔
563
                filtered.add(element);
1✔
564
            }
565
        }
1✔
566
        return filtered;
1✔
567
    }
568

569
    public static <E> List<E> filter(final List<E> list, final Predicate<E> pred) {
570
        final List<E> filtered = new ArrayList<>();
1✔
571
        for (E element : list) {
1✔
572
            if (pred.test(element)) {
1✔
573
                filtered.add(element);
1✔
574
            }
575
        }
1✔
576
        return filtered;
1✔
577
    }
578

579
    public List<T> filter(final Predicate<T> pred) {
580
        final List<T> filtered = new ArrayList<>();
1✔
581
        for (final T element : value()) {
1✔
582
            if (pred.test(element)) {
1✔
583
                filtered.add(element);
1✔
584
            }
585
        }
1✔
586
        return filtered;
1✔
587
    }
588

589
    public static <E> List<E> filterIndexed(final List<E> list, final PredicateIndexed<E> pred) {
590
        final List<E> filtered = new ArrayList<>();
1✔
591
        int index = 0;
1✔
592
        for (E element : list) {
1✔
593
            if (pred.test(index, element)) {
1✔
594
                filtered.add(element);
1✔
595
            }
596
            index += 1;
1✔
597
        }
1✔
598
        return filtered;
1✔
599
    }
600

601
    public static <E> Set<E> filter(final Set<E> set, final Predicate<E> pred) {
602
        final Set<E> filtered = new LinkedHashSet<>();
1✔
603
        for (E element : set) {
1✔
604
            if (pred.test(element)) {
1✔
605
                filtered.add(element);
1✔
606
            }
607
        }
1✔
608
        return filtered;
1✔
609
    }
610

611
    public static <E> List<E> select(final List<E> list, final Predicate<E> pred) {
612
        return filter(list, pred);
1✔
613
    }
614

615
    public static <E> Set<E> select(final Set<E> set, final Predicate<E> pred) {
616
        return filter(set, pred);
1✔
617
    }
618

619
    /*
620
     * Documented, #reject
621
     */
622
    public static <E> List<E> reject(final List<E> list, final Predicate<E> pred) {
623
        return filter(list, input -> !pred.test(input));
1✔
624
    }
625

626
    public List<T> reject(final Predicate<T> pred) {
627
        return filter(input -> !pred.test(input));
1✔
628
    }
629

630
    public static <E> List<E> rejectIndexed(final List<E> list, final PredicateIndexed<E> pred) {
631
        return filterIndexed(list, (index, input) -> !pred.test(index, input));
1✔
632
    }
633

634
    public static <E> Set<E> reject(final Set<E> set, final Predicate<E> pred) {
635
        return filter(set, input -> !pred.test(input));
1✔
636
    }
637

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

642
    public List<T> filterFalse(final Predicate<T> pred) {
643
        return reject(pred);
1✔
644
    }
645

646
    public static <E> Set<E> filterFalse(final Set<E> set, final Predicate<E> pred) {
647
        return reject(set, pred);
1✔
648
    }
649

650
    public static <E> boolean every(final Iterable<E> iterable, final Predicate<E> pred) {
651
        for (E item : iterable) {
1✔
652
            if (!pred.test(item)) {
1✔
653
                return false;
1✔
654
            }
655
        }
1✔
656
        return true;
1✔
657
    }
658

659
    public boolean every(final Predicate<T> pred) {
660
        return every(iterable, pred);
1✔
661
    }
662

663
    /*
664
     * Documented, #all
665
     */
666
    public static <E> boolean all(final Iterable<E> iterable, final Predicate<E> pred) {
667
        return every(iterable, pred);
1✔
668
    }
669

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

674
    public static <E> boolean some(final Iterable<E> iterable, final Predicate<E> pred) {
675
        Optional<E> optional = find(iterable, pred);
1✔
676
        return optional == null || optional.isPresent();
1✔
677
    }
678

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

683
    /*
684
     * Documented, #any
685
     */
686
    public static <E> boolean any(final Iterable<E> iterable, final Predicate<E> pred) {
687
        return some(iterable, pred);
1✔
688
    }
689

690
    public boolean any(final Predicate<T> pred) {
691
        return some(iterable, pred);
1✔
692
    }
693

694
    public static <E> int count(final Iterable<E> iterable, final Predicate<E> pred) {
695
        int result = 0;
1✔
696
        for (E item : iterable) {
1✔
697
            if (pred.test(item)) {
1✔
698
                result += 1;
1✔
699
            }
700
        }
1✔
701
        return result;
1✔
702
    }
703

704
    public int count(final Predicate<T> pred) {
705
        return count(iterable, pred);
1✔
706
    }
707

708
    public static <E> boolean contains(final Iterable<E> iterable, final E elem) {
709
        return some(iterable, e -> Objects.equals(elem, e));
1✔
710
    }
711

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

716
    public static <E> boolean containsWith(final Iterable<E> iterable, final E elem) {
717
        return some(
1✔
718
                iterable,
719
                e -> elem == null ? e == null : String.valueOf(e).contains(String.valueOf(elem)));
1✔
720
    }
721

722
    public boolean containsWith(final T elem) {
723
        return containsWith(iterable, elem);
1✔
724
    }
725

726
    public static <E> boolean contains(
727
            final Iterable<E> iterable, final E elem, final int fromIndex) {
728
        final List<E> list = newArrayList(iterable);
1✔
729
        return contains(list.subList(fromIndex, list.size()), elem);
1✔
730
    }
731

732
    public boolean containsAtLeast(final T value, final int count) {
733
        return Underscore.containsAtLeast(this.iterable, value, count);
1✔
734
    }
735

736
    public boolean containsAtMost(final T value, final int count) {
737
        return Underscore.containsAtMost(this.iterable, value, count);
1✔
738
    }
739

740
    public static <E> boolean containsAtLeast(
741
            final Iterable<E> iterable, final E value, final int count) {
742
        int foundItems = 0;
1✔
743
        for (E element : iterable) {
1✔
744
            if (Objects.equals(element, value)) {
1✔
745
                foundItems += 1;
1✔
746
            }
747
            if (foundItems >= count) {
1✔
748
                break;
1✔
749
            }
750
        }
1✔
751
        return foundItems >= count;
1✔
752
    }
753

754
    public static <E> boolean containsAtMost(
755
            final Iterable<E> iterable, final E value, final int count) {
756
        int foundItems = size(iterable);
1✔
757
        for (E element : iterable) {
1✔
758
            if (!(Objects.equals(element, value))) {
1✔
759
                foundItems -= 1;
1✔
760
            }
761
            if (foundItems <= count) {
1✔
762
                break;
1✔
763
            }
764
        }
1✔
765
        return foundItems <= count;
1✔
766
    }
767

768
    /*
769
     * Documented, #include
770
     */
771
    public static <E> boolean include(final Iterable<E> iterable, final E elem) {
772
        return contains(iterable, elem);
1✔
773
    }
774

775
    /*
776
     * Documented, #invoke
777
     */
778
    @SuppressWarnings("unchecked")
779
    public static <E> List<E> invoke(
780
            final Iterable<E> iterable, final String methodName, final List<Object> args) {
781
        final List<E> result = new ArrayList<>();
1✔
782
        final List<Class<?>> argTypes = map(args, Object::getClass);
1✔
783
        try {
784
            final Method method =
1✔
785
                    iterable.iterator()
1✔
786
                            .next()
1✔
787
                            .getClass()
1✔
788
                            .getMethod(methodName, argTypes.toArray(new Class[0]));
1✔
789
            for (E arg : iterable) {
1✔
790
                doInvoke(args, result, method, arg);
1✔
791
            }
1✔
792
        } catch (NoSuchMethodException e) {
1✔
793
            throw new IllegalArgumentException(e);
1✔
794
        }
1✔
795
        return result;
1✔
796
    }
797

798
    @SuppressWarnings("unchecked")
799
    private static <E> void doInvoke(List<Object> args, List<E> result, Method method, E arg) {
800
        try {
801
            result.add((E) method.invoke(arg, args.toArray(new Object[0])));
1✔
802
        } catch (Exception e) {
1✔
803
            throw new IllegalArgumentException(e);
1✔
804
        }
1✔
805
    }
1✔
806

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

811
    public static <E> List<E> invoke(final Iterable<E> iterable, final String methodName) {
812
        return invoke(iterable, methodName, Collections.emptyList());
1✔
813
    }
814

815
    public List<T> invoke(final String methodName) {
816
        return invoke(iterable, methodName);
1✔
817
    }
818

819
    /*
820
     * Documented, #pluck
821
     */
822
    public static <E> List<Object> pluck(final List<E> list, final String propertyName) {
823
        if (list.isEmpty()) {
1✔
824
            return Collections.emptyList();
1✔
825
        }
826
        return map(
1✔
827
                list,
828
                elem -> {
829
                    try {
830
                        return elem.getClass().getField(propertyName).get(elem);
1✔
831
                    } catch (Exception e) {
1✔
832
                        try {
833
                            return elem.getClass().getMethod(propertyName).invoke(elem);
1✔
834
                        } catch (Exception ex) {
1✔
835
                            throw new IllegalArgumentException(ex);
1✔
836
                        }
837
                    }
838
                });
839
    }
840

841
    public List<Object> pluck(final String propertyName) {
842
        return pluck(newArrayList(iterable), propertyName);
1✔
843
    }
844

845
    public static <E> Set<Object> pluck(final Set<E> set, final String propertyName) {
846
        if (set.isEmpty()) {
1✔
847
            return Collections.emptySet();
1✔
848
        }
849
        return map(
1✔
850
                set,
851
                elem -> {
852
                    try {
853
                        return elem.getClass().getField(propertyName).get(elem);
1✔
854
                    } catch (Exception e) {
1✔
855
                        try {
856
                            return elem.getClass().getMethod(propertyName).invoke(elem);
1✔
857
                        } catch (Exception ex) {
1✔
858
                            throw new IllegalArgumentException(ex);
1✔
859
                        }
860
                    }
861
                });
862
    }
863

864
    /*
865
     * Documented, #where
866
     */
867
    public static <T, E> List<E> where(
868
            final List<E> list, final List<Map.Entry<String, T>> properties) {
869
        return filter(list, new WherePredicate<>(properties));
1✔
870
    }
871

872
    public <E> List<T> where(final List<Map.Entry<String, E>> properties) {
873
        return where(newArrayList(iterable), properties);
1✔
874
    }
875

876
    public static <T, E> Set<E> where(
877
            final Set<E> set, final List<Map.Entry<String, T>> properties) {
878
        return filter(set, new WherePredicate<>(properties));
1✔
879
    }
880

881
    /*
882
     * Documented, #findWhere
883
     */
884
    public static <T, E> Optional<E> findWhere(
885
            final Iterable<E> iterable, final List<Map.Entry<String, T>> properties) {
886
        return find(iterable, new WherePredicate<>(properties));
1✔
887
    }
888

889
    public <E> Optional<T> findWhere(final List<Map.Entry<String, E>> properties) {
890
        return findWhere(iterable, properties);
1✔
891
    }
892

893
    /*
894
     * Documented, #max
895
     */
896
    public static <E extends Comparable<? super E>> E max(final Collection<E> collection) {
897
        return Collections.max(collection);
1✔
898
    }
899

900
    @SuppressWarnings("unchecked")
901
    public T max() {
902
        return (T) max((Collection) iterable);
1✔
903
    }
904

905
    @SuppressWarnings("unchecked")
906
    public static <E, F extends Comparable> E max(
907
            final Collection<E> collection, final Function<E, F> func) {
908
        return Collections.max(collection, (o1, o2) -> func.apply(o1).compareTo(func.apply(o2)));
1✔
909
    }
910

911
    @SuppressWarnings("unchecked")
912
    public <F extends Comparable<? super F>> T max(final Function<T, F> func) {
913
        return (T) max((Collection) iterable, func);
1✔
914
    }
915

916
    /*
917
     * Documented, #min
918
     */
919
    public static <E extends Comparable<? super E>> E min(final Collection<E> collection) {
920
        return Collections.min(collection);
1✔
921
    }
922

923
    @SuppressWarnings("unchecked")
924
    public T min() {
925
        return (T) min((Collection) iterable);
1✔
926
    }
927

928
    @SuppressWarnings("unchecked")
929
    public static <E, F extends Comparable> E min(
930
            final Collection<E> collection, final Function<E, F> func) {
931
        return Collections.min(collection, (o1, o2) -> func.apply(o1).compareTo(func.apply(o2)));
1✔
932
    }
933

934
    @SuppressWarnings("unchecked")
935
    public <F extends Comparable<? super F>> T min(final Function<T, F> func) {
936
        return (T) min((Collection) iterable, func);
1✔
937
    }
938

939
    /*
940
     * Documented, #shuffle
941
     */
942
    public static <E> List<E> shuffle(final Iterable<E> iterable) {
943
        final List<E> shuffled = newArrayList(iterable);
1✔
944
        Collections.shuffle(shuffled);
1✔
945
        return shuffled;
1✔
946
    }
947

948
    public List<T> shuffle() {
949
        return shuffle(iterable);
1✔
950
    }
951

952
    /*
953
     * Documented, #sample
954
     */
955
    public static <E> E sample(final Iterable<E> iterable) {
956
        return newArrayList(iterable).get(new java.security.SecureRandom().nextInt(size(iterable)));
1✔
957
    }
958

959
    public T sample() {
960
        return sample(iterable);
1✔
961
    }
962

963
    public static <E> Set<E> sample(final List<E> list, final int howMany) {
964
        final int size = Math.min(howMany, list.size());
1✔
965
        final Set<E> samples = newLinkedHashSetWithExpectedSize(size);
1✔
966
        while (samples.size() < size) {
1✔
967
            E sample = sample(list);
1✔
968
            samples.add(sample);
1✔
969
        }
1✔
970
        return samples;
1✔
971
    }
972

973
    public static <T extends Comparable<? super T>> List<T> sortWith(
974
            final Iterable<T> iterable, final Comparator<T> comparator) {
975
        final List<T> sortedList = newArrayList(iterable);
1✔
976
        sortedList.sort(comparator);
1✔
977
        return sortedList;
1✔
978
    }
979

980
    @SuppressWarnings("unchecked")
981
    public <E extends Comparable<? super E>> List<E> sortWith(final Comparator<E> comparator) {
982
        return sortWith((Iterable<E>) iterable, comparator);
1✔
983
    }
984

985
    /*
986
     * Documented, #sortBy
987
     */
988
    public static <E, T extends Comparable<? super T>> List<E> sortBy(
989
            final Iterable<E> iterable, final Function<E, T> func) {
990
        final List<E> sortedList = newArrayList(iterable);
1✔
991
        sortedList.sort(Comparator.comparing(func));
1✔
992
        return sortedList;
1✔
993
    }
994

995
    @SuppressWarnings("unchecked")
996
    public <E, V extends Comparable<? super V>> List<E> sortBy(final Function<E, V> func) {
997
        return sortBy((Iterable<E>) iterable, func);
1✔
998
    }
999

1000
    public static <K, V extends Comparable<? super V>> List<Map<K, V>> sortBy(
1001
            final Iterable<Map<K, V>> iterable, final K key) {
1002
        final List<Map<K, V>> sortedList = newArrayList(iterable);
1✔
1003
        sortedList.sort(Comparator.comparing(o -> o.get(key)));
1✔
1004
        return sortedList;
1✔
1005
    }
1006

1007
    /*
1008
     * Documented, #groupBy
1009
     */
1010
    public static <K, E> Map<K, List<E>> groupBy(
1011
            final Iterable<E> iterable, final Function<E, K> func) {
1012
        final Map<K, List<E>> retVal = new LinkedHashMap<>();
1✔
1013
        for (E e : iterable) {
1✔
1014
            final K key = func.apply(e);
1✔
1015
            List<E> val;
1016
            if (retVal.containsKey(key)) {
1✔
1017
                val = retVal.get(key);
1✔
1018
            } else {
1019
                val = new ArrayList<>();
1✔
1020
            }
1021
            val.add(e);
1✔
1022
            retVal.put(key, val);
1✔
1023
        }
1✔
1024
        return retVal;
1✔
1025
    }
1026

1027
    @SuppressWarnings("unchecked")
1028
    public <K, E> Map<K, List<E>> groupBy(final Function<E, K> func) {
1029
        return groupBy((Iterable<E>) iterable, func);
1✔
1030
    }
1031

1032
    public static <K, E> Map<K, Optional<E>> groupBy(
1033
            final Iterable<E> iterable,
1034
            final Function<E, K> func,
1035
            final BinaryOperator<E> binaryOperator) {
1036
        final Map<K, Optional<E>> retVal = new LinkedHashMap<>();
1✔
1037
        for (Map.Entry<K, List<E>> entry : groupBy(iterable, func).entrySet()) {
1✔
1038
            retVal.put(entry.getKey(), reduce(entry.getValue(), binaryOperator));
1✔
1039
        }
1✔
1040
        return retVal;
1✔
1041
    }
1042

1043
    @SuppressWarnings("unchecked")
1044
    public <K, E> Map<K, Optional<E>> groupBy(
1045
            final Function<E, K> func, final BinaryOperator<E> binaryOperator) {
1046
        return groupBy((Iterable<E>) iterable, func, binaryOperator);
1✔
1047
    }
1048

1049
    public static <K, E> Map<K, E> associateBy(
1050
            final Iterable<E> iterable, final Function<E, K> func) {
1051
        final Map<K, E> retVal = new LinkedHashMap<>();
1✔
1052
        for (E e : iterable) {
1✔
1053
            final K key = func.apply(e);
1✔
1054
            retVal.putIfAbsent(key, e);
1✔
1055
        }
1✔
1056
        return retVal;
1✔
1057
    }
1058

1059
    @SuppressWarnings("unchecked")
1060
    public <K, E> Map<K, E> associateBy(final Function<E, K> func) {
1061
        return associateBy((Iterable<E>) iterable, func);
1✔
1062
    }
1063

1064
    @SuppressWarnings("unchecked")
1065
    public static <K, E> Map<K, List<E>> indexBy(
1066
            final Iterable<E> iterable, final String property) {
1067
        return groupBy(
1✔
1068
                iterable,
1069
                elem -> {
1070
                    try {
1071
                        return (K) elem.getClass().getField(property).get(elem);
1✔
1072
                    } catch (Exception e) {
1✔
1073
                        return null;
1✔
1074
                    }
1075
                });
1076
    }
1077

1078
    @SuppressWarnings("unchecked")
1079
    public <K, E> Map<K, List<E>> indexBy(final String property) {
1080
        return indexBy((Iterable<E>) iterable, property);
1✔
1081
    }
1082

1083
    /*
1084
     * Documented, #countBy
1085
     */
1086
    public static <K, E> Map<K, Integer> countBy(final Iterable<E> iterable, Function<E, K> func) {
1087
        final Map<K, Integer> retVal = new LinkedHashMap<>();
1✔
1088
        for (E e : iterable) {
1✔
1089
            final K key = func.apply(e);
1✔
1090
            if (retVal.containsKey(key)) {
1✔
1091
                retVal.put(key, 1 + retVal.get(key));
1✔
1092
            } else {
1093
                retVal.put(key, 1);
1✔
1094
            }
1095
        }
1✔
1096
        return retVal;
1✔
1097
    }
1098

1099
    public static <K> Map<K, Integer> countBy(final Iterable<K> iterable) {
1100
        final Map<K, Integer> retVal = new LinkedHashMap<>();
1✔
1101
        for (K key : iterable) {
1✔
1102
            if (retVal.containsKey(key)) {
1✔
1103
                retVal.put(key, 1 + retVal.get(key));
1✔
1104
            } else {
1105
                retVal.put(key, 1);
1✔
1106
            }
1107
        }
1✔
1108
        return retVal;
1✔
1109
    }
1110

1111
    @SuppressWarnings("unchecked")
1112
    public <K, E> Map<K, Integer> countBy(Function<E, K> func) {
1113
        return countBy((Iterable<E>) iterable, func);
1✔
1114
    }
1115

1116
    @SuppressWarnings("unchecked")
1117
    public <K> Map<K, Integer> countBy() {
1118
        return countBy((Iterable<K>) iterable);
1✔
1119
    }
1120

1121
    /*
1122
     * Documented, #toArray
1123
     */
1124
    @SuppressWarnings("unchecked")
1125
    public static <E> E[] toArray(final Iterable<E> iterable) {
1126
        return (E[]) newArrayList(iterable).toArray();
1✔
1127
    }
1128

1129
    @SuppressWarnings("unchecked")
1130
    public <E> E[] toArray() {
1131
        return toArray((Iterable<E>) iterable);
1✔
1132
    }
1133

1134
    /*
1135
     * Documented, #toMap
1136
     */
1137
    public static <K, V> Map<K, V> toMap(final Iterable<Map.Entry<K, V>> iterable) {
1138
        final Map<K, V> result = new LinkedHashMap<>();
1✔
1139
        for (Map.Entry<K, V> entry : iterable) {
1✔
1140
            result.put(entry.getKey(), entry.getValue());
1✔
1141
        }
1✔
1142
        return result;
1✔
1143
    }
1144

1145
    @SuppressWarnings("unchecked")
1146
    public <K, V> Map<K, V> toMap() {
1147
        return toMap((Iterable<Map.Entry<K, V>>) iterable);
1✔
1148
    }
1149

1150
    public static <K, V> Map<K, V> toMap(final List<Map.Entry<K, V>> tuples) {
1151
        final Map<K, V> result = new LinkedHashMap<>();
1✔
1152
        for (final Map.Entry<K, V> entry : tuples) {
1✔
1153
            result.put(entry.getKey(), entry.getValue());
1✔
1154
        }
1✔
1155
        return result;
1✔
1156
    }
1157

1158
    public Map<T, Integer> toCardinalityMap() {
1159
        return toCardinalityMap(iterable);
1✔
1160
    }
1161

1162
    public static <K> Map<K, Integer> toCardinalityMap(final Iterable<K> iterable) {
1163
        Iterator<K> iterator = iterable.iterator();
1✔
1164
        Map<K, Integer> result = new LinkedHashMap<>();
1✔
1165

1166
        while (iterator.hasNext()) {
1✔
1167
            K item = iterator.next();
1✔
1168

1169
            if (result.containsKey(item)) {
1✔
1170
                result.put(item, result.get(item) + 1);
1✔
1171
            } else {
1172
                result.put(item, 1);
1✔
1173
            }
1174
        }
1✔
1175
        return result;
1✔
1176
    }
1177

1178
    /*
1179
     * Documented, #size
1180
     */
1181
    public static int size(final Iterable<?> iterable) {
1182
        if (iterable instanceof Collection) {
1✔
1183
            return ((Collection) iterable).size();
1✔
1184
        }
1185
        int size;
1186
        final Iterator<?> iterator = iterable.iterator();
1✔
1187
        for (size = 0; iterator.hasNext(); size += 1) {
1✔
1188
            iterator.next();
1✔
1189
        }
1190
        return size;
1✔
1191
    }
1192

1193
    public int size() {
1194
        return size(iterable);
1✔
1195
    }
1196

1197
    @SuppressWarnings("unchecked")
1198
    public static <E> int size(final E... array) {
1199
        return array.length;
1✔
1200
    }
1201

1202
    public static <E> List<List<E>> partition(final Iterable<E> iterable, final Predicate<E> pred) {
1203
        final List<E> retVal1 = new ArrayList<>();
1✔
1204
        final List<E> retVal2 = new ArrayList<>();
1✔
1205
        for (final E e : iterable) {
1✔
1206
            if (pred.test(e)) {
1✔
1207
                retVal1.add(e);
1✔
1208
            } else {
1209
                retVal2.add(e);
1✔
1210
            }
1211
        }
1✔
1212
        return Arrays.asList(retVal1, retVal2);
1✔
1213
    }
1214

1215
    @SuppressWarnings("unchecked")
1216
    public static <E> List<E>[] partition(final E[] iterable, final Predicate<E> pred) {
1217
        return partition(Arrays.asList(iterable), pred).toArray(new List[0]);
1✔
1218
    }
1219

1220
    public T singleOrNull() {
1221
        return singleOrNull(iterable);
1✔
1222
    }
1223

1224
    public T singleOrNull(Predicate<T> pred) {
1225
        return singleOrNull(iterable, pred);
1✔
1226
    }
1227

1228
    public static <E> E singleOrNull(final Iterable<E> iterable) {
1229
        Iterator<E> iterator = iterable.iterator();
1✔
1230
        if (!iterator.hasNext()) {
1✔
1231
            return null;
1✔
1232
        }
1233
        E result = iterator.next();
1✔
1234

1235
        if (iterator.hasNext()) {
1✔
1236
            result = null;
1✔
1237
        }
1238
        return result;
1✔
1239
    }
1240

1241
    public static <E> E singleOrNull(final Iterable<E> iterable, Predicate<E> pred) {
1242
        return singleOrNull(filter(iterable, pred));
1✔
1243
    }
1244

1245
    /*
1246
     * Documented, #first
1247
     */
1248
    public static <E> E first(final Iterable<E> iterable) {
1249
        return iterable.iterator().next();
1✔
1250
    }
1251

1252
    @SuppressWarnings("unchecked")
1253
    public static <E> E first(final E... array) {
1254
        return array[0];
1✔
1255
    }
1256

1257
    public static <E> List<E> first(final List<E> list, final int n) {
1258
        return list.subList(0, Math.min(Math.max(n, 0), list.size()));
1✔
1259
    }
1260

1261
    public T first() {
1262
        return first(iterable);
1✔
1263
    }
1264

1265
    public List<T> first(final int n) {
1266
        return first(newArrayList(iterable), n);
1✔
1267
    }
1268

1269
    public static <E> E first(final Iterable<E> iterable, final Predicate<E> pred) {
1270
        return filter(newArrayList(iterable), pred).iterator().next();
1✔
1271
    }
1272

1273
    public static <E> List<E> first(
1274
            final Iterable<E> iterable, final Predicate<E> pred, final int n) {
1275
        List<E> list = filter(newArrayList(iterable), pred);
1✔
1276
        return list.subList(0, Math.min(Math.max(n, 0), list.size()));
1✔
1277
    }
1278

1279
    public T first(final Predicate<T> pred) {
1280
        return first(newArrayList(iterable), pred);
1✔
1281
    }
1282

1283
    public List<T> first(final Predicate<T> pred, final int n) {
1284
        return first(newArrayList(iterable), pred, n);
1✔
1285
    }
1286

1287
    public static <E> E firstOrNull(final Iterable<E> iterable) {
1288
        final Iterator<E> iterator = iterable.iterator();
1✔
1289
        return iterator.hasNext() ? iterator.next() : null;
1✔
1290
    }
1291

1292
    public T firstOrNull() {
1293
        return firstOrNull(iterable);
1✔
1294
    }
1295

1296
    public static <E> E firstOrNull(final Iterable<E> iterable, final Predicate<E> pred) {
1297
        final Iterator<E> iterator = filter(newArrayList(iterable), pred).iterator();
1✔
1298
        return iterator.hasNext() ? iterator.next() : null;
1✔
1299
    }
1300

1301
    public T firstOrNull(final Predicate<T> pred) {
1302
        return firstOrNull(iterable, pred);
1✔
1303
    }
1304

1305
    public static <E> E head(final Iterable<E> iterable) {
1306
        return first(iterable);
1✔
1307
    }
1308

1309
    @SuppressWarnings("unchecked")
1310
    public static <E> E head(final E... array) {
1311
        return first(array);
1✔
1312
    }
1313

1314
    public static <E> List<E> head(final List<E> list, final int n) {
1315
        return first(list, n);
1✔
1316
    }
1317

1318
    public T head() {
1319
        return first();
1✔
1320
    }
1321

1322
    public List<T> head(final int n) {
1323
        return first(n);
1✔
1324
    }
1325

1326
    /*
1327
     * Documented, #initial
1328
     */
1329
    public static <E> List<E> initial(final List<E> list) {
1330
        return initial(list, 1);
1✔
1331
    }
1332

1333
    public static <E> List<E> initial(final List<E> list, final int n) {
1334
        return list.subList(0, Math.max(0, list.size() - n));
1✔
1335
    }
1336

1337
    @SuppressWarnings("unchecked")
1338
    public static <E> E[] initial(final E... array) {
1339
        return initial(array, 1);
1✔
1340
    }
1341

1342
    public static <E> E[] initial(final E[] array, final int n) {
1343
        return Arrays.copyOf(array, array.length - n);
1✔
1344
    }
1345

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

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

1354
    @SuppressWarnings("unchecked")
1355
    public static <E> E last(final E... array) {
1356
        return array[array.length - 1];
1✔
1357
    }
1358

1359
    /*
1360
     * Documented, #last
1361
     */
1362
    public static <E> E last(final List<E> list) {
1363
        return list.get(list.size() - 1);
1✔
1364
    }
1365

1366
    public static <E> List<E> last(final List<E> list, final int n) {
1367
        return list.subList(Math.max(0, list.size() - n), list.size());
1✔
1368
    }
1369

1370
    public T last() {
1371
        return last((List<T>) iterable);
1✔
1372
    }
1373

1374
    public List<T> last(final int n) {
1375
        return last((List<T>) iterable, n);
1✔
1376
    }
1377

1378
    public static <E> E last(final List<E> list, final Predicate<E> pred) {
1379
        final List<E> filteredList = filter(list, pred);
1✔
1380
        return filteredList.get(filteredList.size() - 1);
1✔
1381
    }
1382

1383
    public T last(final Predicate<T> pred) {
1384
        return last((List<T>) iterable, pred);
1✔
1385
    }
1386

1387
    public static <E> E lastOrNull(final List<E> list) {
1388
        return list.isEmpty() ? null : list.get(list.size() - 1);
1✔
1389
    }
1390

1391
    public T lastOrNull() {
1392
        return lastOrNull((List<T>) iterable);
1✔
1393
    }
1394

1395
    public static <E> E lastOrNull(final List<E> list, final Predicate<E> pred) {
1396
        final List<E> filteredList = filter(list, pred);
1✔
1397
        return filteredList.isEmpty() ? null : filteredList.get(filteredList.size() - 1);
1✔
1398
    }
1399

1400
    public T lastOrNull(final Predicate<T> pred) {
1401
        return lastOrNull((List<T>) iterable, pred);
1✔
1402
    }
1403

1404
    /*
1405
     * Documented, #rest
1406
     */
1407
    public static <E> List<E> rest(final List<E> list) {
1408
        return rest(list, 1);
1✔
1409
    }
1410

1411
    public static <E> List<E> rest(final List<E> list, int n) {
1412
        return list.subList(Math.min(n, list.size()), list.size());
1✔
1413
    }
1414

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

1420
    @SuppressWarnings("unchecked")
1421
    public static <E> E[] rest(final E[] array, final int n) {
1422
        return (E[]) rest(Arrays.asList(array), n).toArray();
1✔
1423
    }
1424

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

1429
    public List<T> rest(int n) {
1430
        return rest((List<T>) iterable, n);
1✔
1431
    }
1432

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

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

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

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

1450
    public List<T> tail() {
1451
        return rest();
1✔
1452
    }
1453

1454
    public List<T> tail(final int n) {
1455
        return rest(n);
1✔
1456
    }
1457

1458
    public static <E> List<E> drop(final List<E> list) {
1459
        return rest(list);
1✔
1460
    }
1461

1462
    public static <E> List<E> drop(final List<E> list, final int n) {
1463
        return rest(list, n);
1✔
1464
    }
1465

1466
    @SuppressWarnings("unchecked")
1467
    public static <E> E[] drop(final E... array) {
1468
        return rest(array);
1✔
1469
    }
1470

1471
    public static <E> E[] drop(final E[] array, final int n) {
1472
        return rest(array, n);
1✔
1473
    }
1474

1475
    /*
1476
     * Documented, #compact
1477
     */
1478
    public static <E> List<E> compact(final List<E> list) {
1479
        return filter(
1✔
1480
                list,
1481
                arg ->
1482
                        !String.valueOf(arg).equals("null")
1✔
1483
                                && !String.valueOf(arg).equals("0")
1✔
1484
                                && !String.valueOf(arg).equals("false")
1✔
1485
                                && !String.valueOf(arg).isEmpty());
1✔
1486
    }
1487

1488
    @SuppressWarnings("unchecked")
1489
    public static <E> E[] compact(final E... array) {
1490
        return (E[]) compact(Arrays.asList(array)).toArray();
1✔
1491
    }
1492

1493
    public static <E> List<E> compactList(final List<E> list, final E falsyValue) {
1494
        return filter(list, arg -> !(Objects.equals(arg, falsyValue)));
1✔
1495
    }
1496

1497
    @SuppressWarnings("unchecked")
1498
    public static <E> E[] compact(final E[] array, final E falsyValue) {
1499
        return (E[]) compactList(Arrays.asList(array), falsyValue).toArray();
1✔
1500
    }
1501

1502
    public List<T> compact() {
1503
        return compact((List<T>) iterable);
1✔
1504
    }
1505

1506
    public List<T> compact(final T falsyValue) {
1507
        return compactList((List<T>) iterable, falsyValue);
1✔
1508
    }
1509

1510
    /*
1511
     * Documented, #flatten
1512
     */
1513
    public static <E> List<E> flatten(final List<?> list) {
1514
        List<E> flattened = new ArrayList<>();
1✔
1515
        flatten(list, flattened, -1);
1✔
1516
        return flattened;
1✔
1517
    }
1518

1519
    public static <E> List<E> flatten(final List<?> list, final boolean shallow) {
1520
        List<E> flattened = new ArrayList<>();
1✔
1521
        flatten(list, flattened, shallow ? 1 : -1);
1✔
1522
        return flattened;
1✔
1523
    }
1524

1525
    @SuppressWarnings("unchecked")
1526
    private static <E> void flatten(
1527
            final List<?> fromTreeList, final List<E> toFlatList, final int shallowLevel) {
1528
        for (Object item : fromTreeList) {
1✔
1529
            if (item instanceof List<?> && shallowLevel != 0) {
1✔
1530
                flatten((List<?>) item, toFlatList, shallowLevel - 1);
1✔
1531
            } else {
1532
                toFlatList.add((E) item);
1✔
1533
            }
1534
        }
1✔
1535
    }
1✔
1536

1537
    public List<T> flatten() {
1538
        return flatten((List<T>) iterable);
1✔
1539
    }
1540

1541
    public List<T> flatten(final boolean shallow) {
1542
        return flatten((List<T>) iterable, shallow);
1✔
1543
    }
1544

1545
    /*
1546
     * Documented, #without
1547
     */
1548
    @SuppressWarnings("unchecked")
1549
    public static <E> List<E> without(final List<E> list, E... values) {
1550
        final List<E> valuesList = Arrays.asList(values);
1✔
1551
        return filter(list, elem -> !contains(valuesList, elem));
1✔
1552
    }
1553

1554
    @SuppressWarnings("unchecked")
1555
    public static <E> E[] without(final E[] array, final E... values) {
1556
        return (E[]) without(Arrays.asList(array), values).toArray();
1✔
1557
    }
1558

1559
    /*
1560
     * Documented, #uniq
1561
     */
1562
    public static <E> List<E> uniq(final List<E> list) {
1563
        return newArrayList(newLinkedHashSet(list));
1✔
1564
    }
1565

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

1571
    public static <K, E> Collection<E> uniq(final Iterable<E> iterable, final Function<E, K> func) {
1572
        final Map<K, E> retVal = new LinkedHashMap<>();
1✔
1573
        for (final E e : iterable) {
1✔
1574
            final K key = func.apply(e);
1✔
1575
            retVal.put(key, e);
1✔
1576
        }
1✔
1577
        return retVal.values();
1✔
1578
    }
1579

1580
    @SuppressWarnings("unchecked")
1581
    public static <K, E> E[] uniq(final E[] array, final Function<E, K> func) {
1582
        return (E[]) uniq(Arrays.asList(array), func).toArray();
1✔
1583
    }
1584

1585
    public static <E> List<E> distinct(final List<E> list) {
1586
        return uniq(list);
1✔
1587
    }
1588

1589
    @SuppressWarnings("unchecked")
1590
    public static <E> E[] distinct(final E... array) {
1591
        return uniq(array);
1✔
1592
    }
1593

1594
    public static <K, E> Collection<E> distinctBy(
1595
            final Iterable<E> iterable, final Function<E, K> func) {
1596
        return uniq(iterable, func);
1✔
1597
    }
1598

1599
    public static <K, E> E[] distinctBy(final E[] array, final Function<E, K> func) {
1600
        return uniq(array, func);
1✔
1601
    }
1602

1603
    /*
1604
     * Documented, #union
1605
     */
1606
    @SuppressWarnings("unchecked")
1607
    public static <E> List<E> union(final List<E> list, final List<E>... lists) {
1608
        final Set<E> union = new LinkedHashSet<>(list);
1✔
1609
        for (List<E> localList : lists) {
1✔
1610
            union.addAll(localList);
1✔
1611
        }
1612
        return newArrayList(union);
1✔
1613
    }
1614

1615
    @SuppressWarnings("unchecked")
1616
    public List<T> unionWith(final List<T>... lists) {
1617
        return union(newArrayList(iterable), lists);
1✔
1618
    }
1619

1620
    @SuppressWarnings("unchecked")
1621
    public static <E> E[] union(final E[]... arrays) {
1622
        final Set<E> union = new LinkedHashSet<>();
1✔
1623
        for (E[] array : arrays) {
1✔
1624
            union.addAll(Arrays.asList(array));
1✔
1625
        }
1626
        return (E[]) newArrayList(union).toArray();
1✔
1627
    }
1628

1629
    /*
1630
     * Documented, #intersection
1631
     */
1632
    public static <E> List<E> intersection(final List<E> list1, final List<E> list2) {
1633
        final List<E> result = new ArrayList<>();
1✔
1634
        for (final E item : list1) {
1✔
1635
            if (list2.contains(item)) {
1✔
1636
                result.add(item);
1✔
1637
            }
1638
        }
1✔
1639
        return result;
1✔
1640
    }
1641

1642
    @SuppressWarnings("unchecked")
1643
    public static <E> List<E> intersection(final List<E> list, final List<E>... lists) {
1644
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1645
        stack.push(list);
1✔
1646
        for (List<E> es : lists) {
1✔
1647
            stack.push(intersection(stack.peek(), es));
1✔
1648
        }
1649
        return stack.peek();
1✔
1650
    }
1651

1652
    @SuppressWarnings("unchecked")
1653
    public List<T> intersectionWith(final List<T>... lists) {
1654
        return intersection(newArrayList(iterable), lists);
1✔
1655
    }
1656

1657
    @SuppressWarnings("unchecked")
1658
    public static <E> E[] intersection(final E[]... arrays) {
1659
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1660
        stack.push(Arrays.asList(arrays[0]));
1✔
1661
        for (int index = 1; index < arrays.length; index += 1) {
1✔
1662
            stack.push(intersection(stack.peek(), Arrays.asList(arrays[index])));
1✔
1663
        }
1664
        return (E[]) stack.peek().toArray();
1✔
1665
    }
1666

1667
    /*
1668
     * Documented, #difference
1669
     */
1670
    public static <E> List<E> difference(final List<E> list1, final List<E> list2) {
1671
        final List<E> result = new ArrayList<>();
1✔
1672
        for (final E item : list1) {
1✔
1673
            if (!list2.contains(item)) {
1✔
1674
                result.add(item);
1✔
1675
            }
1676
        }
1✔
1677
        return result;
1✔
1678
    }
1679

1680
    @SuppressWarnings("unchecked")
1681
    public static <E> List<E> difference(final List<E> list, final List<E>... lists) {
1682
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1683
        stack.push(list);
1✔
1684
        for (List<E> es : lists) {
1✔
1685
            stack.push(difference(stack.peek(), es));
1✔
1686
        }
1687
        return stack.peek();
1✔
1688
    }
1689

1690
    @SuppressWarnings("unchecked")
1691
    public List<T> differenceWith(final List<T>... lists) {
1692
        return difference(newArrayList(iterable), lists);
1✔
1693
    }
1694

1695
    @SuppressWarnings("unchecked")
1696
    public static <E> E[] difference(final E[]... arrays) {
1697
        final Deque<List<E>> stack = new ArrayDeque<>();
1✔
1698
        stack.push(Arrays.asList(arrays[0]));
1✔
1699
        for (int index = 1; index < arrays.length; index += 1) {
1✔
1700
            stack.push(difference(stack.peek(), Arrays.asList(arrays[index])));
1✔
1701
        }
1702
        return (E[]) stack.peek().toArray();
1✔
1703
    }
1704

1705
    /*
1706
     * Documented, #zip
1707
     */
1708
    @SuppressWarnings("unchecked")
1709
    public static <T> List<List<T>> zip(final List<T>... lists) {
1710
        final List<List<T>> zipped = new ArrayList<>();
1✔
1711
        each(
1✔
1712
                Arrays.asList(lists),
1✔
1713
                list -> {
1714
                    int index = 0;
1✔
1715
                    for (T elem : list) {
1✔
1716
                        final List<T> nTuple;
1717
                        nTuple = index >= zipped.size() ? new ArrayList<>() : zipped.get(index);
1✔
1718
                        if (index >= zipped.size()) {
1✔
1719
                            zipped.add(nTuple);
1✔
1720
                        }
1721
                        index += 1;
1✔
1722
                        nTuple.add(elem);
1✔
1723
                    }
1✔
1724
                });
1✔
1725
        return zipped;
1✔
1726
    }
1727

1728
    @SuppressWarnings("unchecked")
1729
    public static <T> List<List<T>> unzip(final List<T>... lists) {
1730
        final List<List<T>> unzipped = new ArrayList<>();
1✔
1731
        for (int index = 0; index < lists[0].size(); index += 1) {
1✔
1732
            final List<T> nTuple = new ArrayList<>();
1✔
1733
            for (List<T> list : lists) {
1✔
1734
                nTuple.add(list.get(index));
1✔
1735
            }
1736
            unzipped.add(nTuple);
1✔
1737
        }
1738
        return unzipped;
1✔
1739
    }
1740

1741
    /*
1742
     * Documented, #object
1743
     */
1744
    public static <K, V> List<Map.Entry<K, V>> object(final List<K> keys, final List<V> values) {
1745
        return map(
1✔
1746
                keys,
1747
                new Function<>() {
1✔
1748
                    private int index;
1749

1750
                    @Override
1751
                    public Map.Entry<K, V> apply(K key) {
1752
                        return Map.entry(key, values.get(index++));
1✔
1753
                    }
1754
                });
1755
    }
1756

1757
    public static <E> int findIndex(final List<E> list, final Predicate<E> pred) {
1758
        for (int index = 0; index < list.size(); index++) {
1✔
1759
            if (pred.test(list.get(index))) {
1✔
1760
                return index;
1✔
1761
            }
1762
        }
1763
        return -1;
1✔
1764
    }
1765

1766
    public static <E> int findIndex(final E[] array, final Predicate<E> pred) {
1767
        return findIndex(Arrays.asList(array), pred);
1✔
1768
    }
1769

1770
    public static <E> int findLastIndex(final List<E> list, final Predicate<E> pred) {
1771
        for (int index = list.size() - 1; index >= 0; index--) {
1✔
1772
            if (pred.test(list.get(index))) {
1✔
1773
                return index;
1✔
1774
            }
1775
        }
1776
        return -1;
1✔
1777
    }
1778

1779
    public static <E> int findLastIndex(final E[] array, final Predicate<E> pred) {
1780
        return findLastIndex(Arrays.asList(array), pred);
1✔
1781
    }
1782

1783
    public static <E extends Comparable<E>> int binarySearch(
1784
            final Iterable<E> iterable, final E key) {
1785
        if (key == null) {
1✔
1786
            return first(iterable) == null ? 0 : -1;
1✔
1787
        }
1788
        int begin = 0;
1✔
1789
        int end = size(iterable) - 1;
1✔
1790
        int numberOfNullValues = 0;
1✔
1791
        List<E> list = new ArrayList<>();
1✔
1792
        for (E item : iterable) {
1✔
1793
            if (item == null) {
1✔
1794
                numberOfNullValues++;
1✔
1795
                end--;
1✔
1796
            } else {
1797
                list.add(item);
1✔
1798
            }
1799
        }
1✔
1800
        while (begin <= end) {
1✔
1801
            int middle = begin + (end - begin) / 2;
1✔
1802
            if (key.compareTo(list.get(middle)) < 0) {
1✔
1803
                end = middle - 1;
1✔
1804
            } else if (key.compareTo(list.get(middle)) > 0) {
1✔
1805
                begin = middle + 1;
1✔
1806
            } else {
1807
                return middle + numberOfNullValues;
1✔
1808
            }
1809
        }
1✔
1810
        return -(begin + numberOfNullValues + 1);
1✔
1811
    }
1812

1813
    public static <E extends Comparable<E>> int binarySearch(final E[] array, final E key) {
1814
        return binarySearch(Arrays.asList(array), key);
1✔
1815
    }
1816

1817
    /*
1818
     * Documented, #sortedIndex
1819
     */
1820
    public static <E extends Comparable<E>> int sortedIndex(final List<E> list, final E value) {
1821
        int index = 0;
1✔
1822
        for (E elem : list) {
1✔
1823
            if (elem.compareTo(value) >= 0) {
1✔
1824
                return index;
1✔
1825
            }
1826
            index += 1;
1✔
1827
        }
1✔
1828
        return -1;
1✔
1829
    }
1830

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

1835
    @SuppressWarnings("unchecked")
1836
    public static <E extends Comparable<E>> int sortedIndex(
1837
            final List<E> list, final E value, final String propertyName) {
1838
        try {
1839
            final Field property = value.getClass().getField(propertyName);
1✔
1840
            final Object valueProperty = property.get(value);
1✔
1841
            int index = 0;
1✔
1842
            for (E elem : list) {
1✔
1843
                if (((Comparable) property.get(elem)).compareTo(valueProperty) >= 0) {
1✔
1844
                    return index;
1✔
1845
                }
1846
                index += 1;
1✔
1847
            }
1✔
1848
            return -1;
1✔
1849
        } catch (Exception e) {
1✔
1850
            throw new IllegalArgumentException(e);
1✔
1851
        }
1852
    }
1853

1854
    public static <E extends Comparable<E>> int sortedIndex(
1855
            final E[] array, final E value, final String propertyName) {
1856
        return sortedIndex(Arrays.asList(array), value, propertyName);
1✔
1857
    }
1858

1859
    /*
1860
     * Documented, #indexOf
1861
     */
1862
    public static <E> int indexOf(final List<E> list, final E value) {
1863
        return list.indexOf(value);
1✔
1864
    }
1865

1866
    public static <E> int indexOf(final E[] array, final E value) {
1867
        return indexOf(Arrays.asList(array), value);
1✔
1868
    }
1869

1870
    /*
1871
     * Documented, #lastIndexOf
1872
     */
1873
    public static <E> int lastIndexOf(final List<E> list, final E value) {
1874
        return list.lastIndexOf(value);
1✔
1875
    }
1876

1877
    public static <E> int lastIndexOf(final E[] array, final E value) {
1878
        return lastIndexOf(Arrays.asList(array), value);
1✔
1879
    }
1880

1881
    /*
1882
     * Documented, #range
1883
     */
1884
    public static List<Integer> range(int stop) {
1885
        return range(0, stop, 1);
1✔
1886
    }
1887

1888
    public static List<Integer> range(int start, int stop) {
1889
        return range(start, stop, start < stop ? 1 : -1);
1✔
1890
    }
1891

1892
    public static List<Integer> range(int start, int stop, int step) {
1893
        List<Integer> list = new ArrayList<>();
1✔
1894
        if (step == 0) {
1✔
1895
            return list;
1✔
1896
        }
1897
        if (start < stop) {
1✔
1898
            for (int value = start; value < stop; value += step) {
1✔
1899
                list.add(value);
1✔
1900
            }
1901
        } else {
1902
            for (int value = start; value > stop; value += step) {
1✔
1903
                list.add(value);
1✔
1904
            }
1905
        }
1906
        return list;
1✔
1907
    }
1908

1909
    public static List<Character> range(char stop) {
1910
        return range('a', stop, 1);
1✔
1911
    }
1912

1913
    public static List<Character> range(char start, char stop) {
1914
        return range(start, stop, start < stop ? 1 : -1);
1✔
1915
    }
1916

1917
    public static List<Character> range(char start, char stop, int step) {
1918
        List<Character> list = new ArrayList<>();
1✔
1919
        if (step == 0) {
1✔
1920
            return list;
1✔
1921
        }
1922
        if (start < stop) {
1✔
1923
            for (char value = start; value < stop; value += (char) step) {
1✔
1924
                list.add(value);
1✔
1925
            }
1926
        } else {
1927
            for (char value = start; value > stop; value += (char) step) {
1✔
1928
                list.add(value);
1✔
1929
            }
1930
        }
1931
        return list;
1✔
1932
    }
1933

1934
    public static <T> List<List<T>> chunk(final Iterable<T> iterable, final int size) {
1935
        if (size <= 0) {
1✔
1936
            return new ArrayList<>();
1✔
1937
        }
1938
        return chunk(iterable, size, size);
1✔
1939
    }
1940

1941
    public static <T> List<List<T>> chunk(
1942
            final Iterable<T> iterable, final int size, final int step) {
1943
        if (step <= 0 || size < 0) {
1✔
1944
            return new ArrayList<>();
1✔
1945
        }
1946
        int index = 0;
1✔
1947
        int length = size(iterable);
1✔
1948
        final List<List<T>> result = new ArrayList<>(size == 0 ? size : (length / size) + 1);
1✔
1949
        while (index < length) {
1✔
1950
            result.add(newArrayList(iterable).subList(index, Math.min(length, index + size)));
1✔
1951
            index += step;
1✔
1952
        }
1953
        return result;
1✔
1954
    }
1955

1956
    public static <T> List<List<T>> chunkFill(
1957
            final Iterable<T> iterable, final int size, final T fillValue) {
1958
        if (size <= 0) {
1✔
1959
            return new ArrayList<>();
1✔
1960
        }
1961
        return chunkFill(iterable, size, size, fillValue);
1✔
1962
    }
1963

1964
    public static <T> List<List<T>> chunkFill(
1965
            final Iterable<T> iterable, final int size, final int step, final T fillValue) {
1966
        if (step <= 0 || size < 0) {
1✔
1967
            return new ArrayList<>();
1✔
1968
        }
1969
        final List<List<T>> result = chunk(iterable, size, step);
1✔
1970
        int difference = size - result.get(result.size() - 1).size();
1✔
1971
        for (int i = difference; 0 < i; i--) {
1✔
1972
            result.get(result.size() - 1).add(fillValue);
1✔
1973
        }
1974
        return result;
1✔
1975
    }
1976

1977
    public List<List<T>> chunk(final int size) {
1978
        return chunk(getIterable(), size, size);
1✔
1979
    }
1980

1981
    public List<List<T>> chunk(final int size, final int step) {
1982
        return chunk(getIterable(), size, step);
1✔
1983
    }
1984

1985
    public List<List<T>> chunkFill(final int size, final T fillvalue) {
1986
        return chunkFill(getIterable(), size, size, fillvalue);
1✔
1987
    }
1988

1989
    public List<List<T>> chunkFill(final int size, final int step, T fillvalue) {
1990
        return chunkFill(getIterable(), size, step, fillvalue);
1✔
1991
    }
1992

1993
    public static <T> List<T> cycle(final Iterable<T> iterable, final int times) {
1994
        int size = Math.abs(size(iterable) * times);
1✔
1995
        if (size == 0) {
1✔
1996
            return new ArrayList<>();
1✔
1997
        }
1998
        List<T> list = newArrayListWithExpectedSize(size);
1✔
1999
        int round = 0;
1✔
2000
        if (times > 0) {
1✔
2001
            while (round < times) {
1✔
2002
                for (T element : iterable) {
1✔
2003
                    list.add(element);
1✔
2004
                }
1✔
2005
                round++;
1✔
2006
            }
2007
        } else {
2008
            list = cycle(Underscore.reverse(iterable), -times);
1✔
2009
        }
2010
        return list;
1✔
2011
    }
2012

2013
    public List<T> cycle(final int times) {
2014
        return cycle(value(), times);
1✔
2015
    }
2016

2017
    public static <T> List<T> repeat(final T element, final int times) {
2018
        if (times <= 0) {
1✔
2019
            return new ArrayList<>();
1✔
2020
        }
2021
        List<T> result = newArrayListWithExpectedSize(times);
1✔
2022
        for (int i = 0; i < times; i++) {
1✔
2023
            result.add(element);
1✔
2024
        }
2025
        return result;
1✔
2026
    }
2027

2028
    public static <T> List<T> interpose(final Iterable<T> iterable, final T interElement) {
2029
        if (interElement == null) {
1✔
2030
            return newArrayList(iterable);
1✔
2031
        }
2032
        int size = size(iterable);
1✔
2033
        int index = 0;
1✔
2034
        List<T> array = newArrayListWithExpectedSize(size * 2);
1✔
2035
        for (T elem : iterable) {
1✔
2036
            array.add(elem);
1✔
2037
            if (index + 1 < size) {
1✔
2038
                array.add(interElement);
1✔
2039
                index++;
1✔
2040
            }
2041
        }
1✔
2042
        return array;
1✔
2043
    }
2044

2045
    public static <T> List<T> interposeByList(
2046
            final Iterable<T> iterable, final Iterable<T> interIter) {
2047
        if (interIter == null) {
1✔
2048
            return newArrayList(iterable);
1✔
2049
        }
2050
        List<T> interList = newArrayList(interIter);
1✔
2051
        if (isEmpty(interIter)) {
1✔
2052
            return newArrayList(iterable);
1✔
2053
        }
2054
        int size = size(iterable);
1✔
2055
        List<T> array = newArrayListWithExpectedSize(size + interList.size());
1✔
2056
        int index = 0;
1✔
2057
        for (T element : iterable) {
1✔
2058
            array.add(element);
1✔
2059
            if (index < interList.size() && index + 1 < size) {
1✔
2060
                array.add(interList.get(index));
1✔
2061
                index++;
1✔
2062
            }
2063
        }
1✔
2064
        return array;
1✔
2065
    }
2066

2067
    public List<T> interpose(final T element) {
2068
        return interpose(value(), element);
1✔
2069
    }
2070

2071
    public List<T> interposeByList(final Iterable<T> interIter) {
2072
        return interposeByList(value(), interIter);
1✔
2073
    }
2074

2075
    /*
2076
     * Documented, #bind
2077
     */
2078
    public static <T, F> Function<F, T> bind(final Function<F, T> function) {
2079
        return function;
1✔
2080
    }
2081

2082
    /*
2083
     * Documented, #memoize
2084
     */
2085
    public static <T, F> Function<F, T> memoize(final Function<F, T> function) {
2086
        return new MemoizeFunction<>() {
1✔
2087
            @Override
2088
            public T calc(F arg) {
2089
                return function.apply(arg);
1✔
2090
            }
2091
        };
2092
    }
2093

2094
    /*
2095
     * Documented, #delay
2096
     */
2097
    public static <T> java.util.concurrent.ScheduledFuture<T> delay(
2098
            final Supplier<T> function, final int delayMilliseconds) {
2099
        final java.util.concurrent.ScheduledExecutorService scheduler =
2100
                java.util.concurrent.Executors.newSingleThreadScheduledExecutor();
1✔
2101
        try {
2102
            return scheduler.schedule(
1✔
2103
                    function::get, delayMilliseconds, java.util.concurrent.TimeUnit.MILLISECONDS);
1✔
2104
        } finally {
2105
            scheduler.shutdown();
1✔
2106
        }
2107
    }
2108

2109
    public static <T> java.util.concurrent.ScheduledFuture<T> defer(final Supplier<T> function) {
2110
        return delay(function, 0);
1✔
2111
    }
2112

2113
    public static java.util.concurrent.ScheduledFuture<Void> defer(final Runnable runnable) {
2114
        return delay(
1✔
2115
                () -> {
2116
                    runnable.run();
1✔
2117
                    return null;
1✔
2118
                },
2119
                0);
2120
    }
2121

2122
    public static <T> Supplier<T> throttle(final Supplier<T> function, final int waitMilliseconds) {
2123
        class ThrottleLater implements Supplier<T> {
2124
            private final Supplier<T> localFunction;
2125
            private java.util.concurrent.ScheduledFuture<T> timeout;
2126
            private long previous;
2127

2128
            ThrottleLater(final Supplier<T> function) {
1✔
2129
                this.localFunction = function;
1✔
2130
            }
1✔
2131

2132
            @Override
2133
            public T get() {
2134
                previous = now();
1✔
2135
                timeout = null;
1✔
2136
                return localFunction.get();
1✔
2137
            }
2138

2139
            java.util.concurrent.ScheduledFuture<T> getTimeout() {
2140
                return timeout;
1✔
2141
            }
2142

2143
            void setTimeout(java.util.concurrent.ScheduledFuture<T> timeout) {
2144
                this.timeout = timeout;
1✔
2145
            }
1✔
2146

2147
            long getPrevious() {
2148
                return previous;
1✔
2149
            }
2150

2151
            void setPrevious(long previous) {
2152
                this.previous = previous;
1✔
2153
            }
1✔
2154
        }
2155

2156
        class ThrottleFunction implements Supplier<T> {
2157
            private final Supplier<T> localFunction;
2158
            private final ThrottleLater throttleLater;
2159

2160
            ThrottleFunction(final Supplier<T> function) {
1✔
2161
                this.localFunction = function;
1✔
2162
                this.throttleLater = new ThrottleLater(function);
1✔
2163
            }
1✔
2164

2165
            @Override
2166
            public T get() {
2167
                final long now = now();
1✔
2168
                if (throttleLater.getPrevious() == 0L) {
1✔
2169
                    throttleLater.setPrevious(now);
1✔
2170
                }
2171
                final long remaining = waitMilliseconds - (now - throttleLater.getPrevious());
1✔
2172
                T result = null;
1✔
2173
                if (remaining <= 0) {
1✔
2174
                    throttleLater.setPrevious(now);
1✔
2175
                    result = localFunction.get();
1✔
2176
                } else if (throttleLater.getTimeout() == null) {
1✔
2177
                    throttleLater.setTimeout(delay(throttleLater, waitMilliseconds));
1✔
2178
                }
2179
                return result;
1✔
2180
            }
2181
        }
2182
        return new ThrottleFunction(function);
1✔
2183
    }
2184

2185
    /*
2186
     * Documented, #debounce
2187
     */
2188
    public static <T> Supplier<T> debounce(
2189
            final Supplier<T> function, final int delayMilliseconds) {
2190
        return new Supplier<>() {
1✔
2191
            private java.util.concurrent.ScheduledFuture<T> timeout;
2192

2193
            @Override
2194
            public T get() {
2195
                clearTimeout(timeout);
1✔
2196
                timeout = delay(function, delayMilliseconds);
1✔
2197
                return null;
1✔
2198
            }
2199
        };
2200
    }
2201

2202
    /*
2203
     * Documented, #wrap
2204
     */
2205
    public static <T> Function<Void, T> wrap(
2206
            final UnaryOperator<T> function, final Function<UnaryOperator<T>, T> wrapper) {
2207
        return arg -> wrapper.apply(function);
1✔
2208
    }
2209

2210
    public static <E> Predicate<E> negate(final Predicate<E> pred) {
2211
        return item -> !pred.test(item);
1✔
2212
    }
2213

2214
    /*
2215
     * Documented, #compose
2216
     */
2217
    @SuppressWarnings("unchecked")
2218
    public static <T> Function<T, T> compose(final Function<T, T>... func) {
2219
        return arg -> {
1✔
2220
            T result = arg;
1✔
2221
            for (int index = func.length - 1; index >= 0; index -= 1) {
1✔
2222
                result = func[index].apply(result);
1✔
2223
            }
2224
            return result;
1✔
2225
        };
2226
    }
2227

2228
    /*
2229
     * Documented, #after
2230
     */
2231
    public static <E> Supplier<E> after(final int count, final Supplier<E> function) {
2232
        class AfterFunction implements Supplier<E> {
2233
            private final int count;
2234
            private final Supplier<E> localFunction;
2235
            private int index;
2236
            private E result;
2237

2238
            AfterFunction(final int count, final Supplier<E> function) {
1✔
2239
                this.count = count;
1✔
2240
                this.localFunction = function;
1✔
2241
            }
1✔
2242

2243
            public E get() {
2244
                if (++index >= count) {
1✔
2245
                    result = localFunction.get();
1✔
2246
                }
2247
                return result;
1✔
2248
            }
2249
        }
2250
        return new AfterFunction(count, function);
1✔
2251
    }
2252

2253
    /*
2254
     * Documented, #before
2255
     */
2256
    public static <E> Supplier<E> before(final int count, final Supplier<E> function) {
2257
        class BeforeFunction implements Supplier<E> {
2258
            private final int count;
2259
            private final Supplier<E> localFunction;
2260
            private int index;
2261
            private E result;
2262

2263
            BeforeFunction(final int count, final Supplier<E> function) {
1✔
2264
                this.count = count;
1✔
2265
                this.localFunction = function;
1✔
2266
            }
1✔
2267

2268
            public E get() {
2269
                if (++index <= count) {
1✔
2270
                    result = localFunction.get();
1✔
2271
                }
2272
                return result;
1✔
2273
            }
2274
        }
2275
        return new BeforeFunction(count, function);
1✔
2276
    }
2277

2278
    /*
2279
     * Documented, #once
2280
     */
2281
    public static <T> Supplier<T> once(final Supplier<T> function) {
2282
        return new Supplier<>() {
1✔
2283
            private volatile boolean executed;
2284
            private T result;
2285

2286
            @Override
2287
            public T get() {
2288
                if (!executed) {
1✔
2289
                    executed = true;
1✔
2290
                    result = function.get();
1✔
2291
                }
2292
                return result;
1✔
2293
            }
2294
        };
2295
    }
2296

2297
    /*
2298
     * Documented, #keys
2299
     */
2300
    public static <K, V> Set<K> keys(final Map<K, V> object) {
2301
        return object.keySet();
1✔
2302
    }
2303

2304
    /*
2305
     * Documented, #values
2306
     */
2307
    public static <K, V> Collection<V> values(final Map<K, V> object) {
2308
        return object.values();
1✔
2309
    }
2310

2311
    public static <K, V> List<Map.Entry<K, V>> mapObject(
2312
            final Map<K, V> object, final Function<? super V, V> func) {
2313
        return map(
1✔
2314
                newArrayList(object.entrySet()),
1✔
2315
                entry -> Map.entry(entry.getKey(), func.apply(entry.getValue())));
1✔
2316
    }
2317

2318
    /*
2319
     * Documented, #pairs
2320
     */
2321
    public static <K, V> List<Map.Entry<K, V>> pairs(final Map<K, V> object) {
2322
        return map(
1✔
2323
                newArrayList(object.entrySet()),
1✔
2324
                entry -> Map.entry(entry.getKey(), entry.getValue()));
1✔
2325
    }
2326

2327
    /*
2328
     * Documented, #invert
2329
     */
2330
    public static <K, V> List<Map.Entry<V, K>> invert(final Map<K, V> object) {
2331
        return map(
1✔
2332
                newArrayList(object.entrySet()),
1✔
2333
                entry -> Map.entry(entry.getValue(), entry.getKey()));
1✔
2334
    }
2335

2336
    /*
2337
     * Documented, #functions
2338
     */
2339
    public static List<String> functions(final Object object) {
2340
        final List<String> result = new ArrayList<>();
1✔
2341
        for (final Method method : object.getClass().getDeclaredMethods()) {
1✔
2342
            result.add(method.getName());
1✔
2343
        }
2344
        return sort(uniq(result));
1✔
2345
    }
2346

2347
    public static List<String> methods(final Object object) {
2348
        return functions(object);
1✔
2349
    }
2350

2351
    /*
2352
     * Documented, #extend
2353
     */
2354
    @SuppressWarnings("unchecked")
2355
    public static <K, V> Map<K, V> extend(final Map<K, V> destination, final Map<K, V>... sources) {
2356
        final Map<K, V> result = new LinkedHashMap<>(destination);
1✔
2357
        for (final Map<K, V> source : sources) {
1✔
2358
            result.putAll(source);
1✔
2359
        }
2360
        return result;
1✔
2361
    }
2362

2363
    public static <E> E findKey(final List<E> list, final Predicate<E> pred) {
2364
        for (E e : list) {
1✔
2365
            if (pred.test(e)) {
1✔
2366
                return e;
1✔
2367
            }
2368
        }
1✔
2369
        return null;
1✔
2370
    }
2371

2372
    public static <E> E findKey(final E[] array, final Predicate<E> pred) {
2373
        return findKey(Arrays.asList(array), pred);
1✔
2374
    }
2375

2376
    public static <E> E findLastKey(final List<E> list, final Predicate<E> pred) {
2377
        for (int index = list.size() - 1; index >= 0; index--) {
1✔
2378
            if (pred.test(list.get(index))) {
1✔
2379
                return list.get(index);
1✔
2380
            }
2381
        }
2382
        return null;
1✔
2383
    }
2384

2385
    public static <E> E findLastKey(final E[] array, final Predicate<E> pred) {
2386
        return findLastKey(Arrays.asList(array), pred);
1✔
2387
    }
2388

2389
    /*
2390
     * Documented, #pick
2391
     */
2392
    @SuppressWarnings("unchecked")
2393
    public static <K, V> List<Map.Entry<K, V>> pick(final Map<K, V> object, final K... keys) {
2394
        return without(
1✔
2395
                map(
1✔
2396
                        newArrayList(object.entrySet()),
1✔
2397
                        entry -> {
2398
                            if (Arrays.asList(keys).contains(entry.getKey())) {
1✔
2399
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2400
                            } else {
2401
                                return null;
1✔
2402
                            }
2403
                        }),
2404
                (Map.Entry<K, V>) null);
2405
    }
2406

2407
    @SuppressWarnings("unchecked")
2408
    public static <K, V> List<Map.Entry<K, V>> pick(
2409
            final Map<K, V> object, final Predicate<V> pred) {
2410
        return without(
1✔
2411
                map(
1✔
2412
                        newArrayList(object.entrySet()),
1✔
2413
                        entry -> {
2414
                            if (pred.test(object.get(entry.getKey()))) {
1✔
2415
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2416
                            } else {
2417
                                return null;
1✔
2418
                            }
2419
                        }),
2420
                (Map.Entry<K, V>) null);
2421
    }
2422

2423
    /*
2424
     * Documented, #omit
2425
     */
2426
    @SuppressWarnings("unchecked")
2427
    public static <K, V> List<Map.Entry<K, V>> omit(final Map<K, V> object, final K... keys) {
2428
        return without(
1✔
2429
                map(
1✔
2430
                        newArrayList(object.entrySet()),
1✔
2431
                        entry -> {
2432
                            if (Arrays.asList(keys).contains(entry.getKey())) {
1✔
2433
                                return null;
1✔
2434
                            } else {
2435
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2436
                            }
2437
                        }),
2438
                (Map.Entry<K, V>) null);
2439
    }
2440

2441
    @SuppressWarnings("unchecked")
2442
    public static <K, V> List<Map.Entry<K, V>> omit(
2443
            final Map<K, V> object, final Predicate<V> pred) {
2444
        return without(
1✔
2445
                map(
1✔
2446
                        newArrayList(object.entrySet()),
1✔
2447
                        entry -> {
2448
                            if (pred.test(entry.getValue())) {
1✔
2449
                                return null;
1✔
2450
                            } else {
2451
                                return Map.entry(entry.getKey(), entry.getValue());
1✔
2452
                            }
2453
                        }),
2454
                (Map.Entry<K, V>) null);
2455
    }
2456

2457
    /*
2458
     * Documented, #defaults
2459
     */
2460
    public static <K, V> Map<K, V> defaults(final Map<K, V> object, final Map<K, V> defaults) {
2461
        final Map<K, V> result = new LinkedHashMap<>();
1✔
2462
        result.putAll(defaults);
1✔
2463
        result.putAll(object);
1✔
2464
        return result;
1✔
2465
    }
2466

2467
    /*
2468
     * Documented, #clone
2469
     */
2470
    public static Object clone(final Object obj) {
2471
        try {
2472
            if (obj instanceof Cloneable) {
1✔
2473
                for (final Method method : obj.getClass().getMethods()) {
1✔
2474
                    if (method.getName().equals("clone")
1✔
2475
                            && method.getParameterTypes().length == 0) {
1✔
2476
                        return method.invoke(obj);
1✔
2477
                    }
2478
                }
2479
            }
2480
        } catch (Exception e) {
1✔
2481
            throw new IllegalArgumentException(e);
1✔
2482
        }
1✔
2483
        throw new IllegalArgumentException("Cannot clone object");
1✔
2484
    }
2485

2486
    @SuppressWarnings("unchecked")
2487
    public static <E> E[] clone(final E... iterable) {
2488
        return Arrays.copyOf(iterable, iterable.length);
1✔
2489
    }
2490

2491
    public static <T> void tap(final Iterable<T> iterable, final Consumer<? super T> func) {
2492
        each(iterable, func);
1✔
2493
    }
1✔
2494

2495
    public static <K, V> boolean isMatch(final Map<K, V> object, final Map<K, V> properties) {
2496
        for (final K key : keys(properties)) {
1✔
2497
            if (!object.containsKey(key) || !object.get(key).equals(properties.get(key))) {
1✔
2498
                return false;
1✔
2499
            }
2500
        }
1✔
2501
        return true;
1✔
2502
    }
2503

2504
    /*
2505
     * Documented, #isEqual
2506
     */
2507
    public static boolean isEqual(final Object object, final Object other) {
2508
        return Objects.equals(object, other);
1✔
2509
    }
2510

2511
    public static <K, V> boolean isEmpty(final Map<K, V> object) {
2512
        return object == null || object.isEmpty();
1✔
2513
    }
2514

2515
    /*
2516
     * Documented, #isEmpty
2517
     */
2518
    public static <T> boolean isEmpty(final Iterable<T> iterable) {
2519
        return iterable == null || !iterable.iterator().hasNext();
1✔
2520
    }
2521

2522
    public boolean isEmpty() {
2523
        return iterable == null || !iterable.iterator().hasNext();
1✔
2524
    }
2525

2526
    public static <K, V> boolean isNotEmpty(final Map<K, V> object) {
2527
        return object != null && !object.isEmpty();
1✔
2528
    }
2529

2530
    public static <T> boolean isNotEmpty(final Iterable<T> iterable) {
2531
        return iterable != null && iterable.iterator().hasNext();
1✔
2532
    }
2533

2534
    public boolean isNotEmpty() {
2535
        return iterable != null && iterable.iterator().hasNext();
1✔
2536
    }
2537

2538
    /*
2539
     * Documented, #isArray
2540
     */
2541
    public static boolean isArray(final Object object) {
2542
        return object != null && object.getClass().isArray();
1✔
2543
    }
2544

2545
    /*
2546
     * Documented, #isObject
2547
     */
2548
    public static boolean isObject(final Object object) {
2549
        return object instanceof Map;
1✔
2550
    }
2551

2552
    /*
2553
     * Documented, #isFunction
2554
     */
2555
    public static boolean isFunction(final Object object) {
2556
        return object instanceof Function;
1✔
2557
    }
2558

2559
    /*
2560
     * Documented, #isString
2561
     */
2562
    public static boolean isString(final Object object) {
2563
        return object instanceof String;
1✔
2564
    }
2565

2566
    /*
2567
     * Documented, #isNumber
2568
     */
2569
    public static boolean isNumber(final Object object) {
2570
        return object instanceof Number;
1✔
2571
    }
2572

2573
    /*
2574
     * Documented, #isDate
2575
     */
2576
    public static boolean isDate(final Object object) {
2577
        return object instanceof Date;
1✔
2578
    }
2579

2580
    public static boolean isRegExp(final Object object) {
2581
        return object instanceof java.util.regex.Pattern;
1✔
2582
    }
2583

2584
    public static boolean isError(final Object object) {
2585
        return object instanceof Throwable;
1✔
2586
    }
2587

2588
    /*
2589
     * Documented, #isBoolean
2590
     */
2591
    public static boolean isBoolean(final Object object) {
2592
        return object instanceof Boolean;
1✔
2593
    }
2594

2595
    public static boolean isNull(final Object object) {
2596
        return object == null;
1✔
2597
    }
2598

2599
    /*
2600
     * Documented, #has
2601
     */
2602
    public static <K, V> boolean has(final Map<K, V> object, final K key) {
2603
        return object.containsKey(key);
1✔
2604
    }
2605

2606
    public static <E> E identity(final E value) {
2607
        return value;
1✔
2608
    }
2609

2610
    public static <E> Supplier<E> constant(final E value) {
2611
        return () -> value;
1✔
2612
    }
2613

2614
    public static <K, V> Function<Map<K, V>, V> property(final K key) {
2615
        return object -> object.get(key);
1✔
2616
    }
2617

2618
    public static <K, V> Function<K, V> propertyOf(final Map<K, V> object) {
2619
        return object::get;
1✔
2620
    }
2621

2622
    public static <K, V> Predicate<Map<K, V>> matcher(final Map<K, V> object) {
2623
        return item -> {
1✔
2624
            for (final K key : keys(object)) {
1✔
2625
                if (!item.containsKey(key) || !item.get(key).equals(object.get(key))) {
1✔
2626
                    return false;
1✔
2627
                }
2628
            }
1✔
2629
            return true;
1✔
2630
        };
2631
    }
2632

2633
    /*
2634
     * Documented, #times
2635
     */
2636
    public static void times(final int count, final Runnable runnable) {
2637
        for (int index = 0; index < count; index += 1) {
1✔
2638
            runnable.run();
1✔
2639
        }
2640
    }
1✔
2641

2642
    /*
2643
     * Documented, #random
2644
     */
2645
    public static int random(final int min, final int max) {
2646
        return min + new java.security.SecureRandom().nextInt(max - min + 1);
1✔
2647
    }
2648

2649
    public static int random(final int max) {
2650
        return new java.security.SecureRandom().nextInt(max + 1);
1✔
2651
    }
2652

2653
    public static long now() {
2654
        return new Date().getTime();
1✔
2655
    }
2656

2657
    /*
2658
     * Documented, #escape
2659
     */
2660
    public static String escape(final String value) {
2661
        final StringBuilder builder = new StringBuilder();
1✔
2662
        for (final char ch : value.toCharArray()) {
1✔
2663
            builder.append(ESCAPES.containsKey(ch) ? ESCAPES.get(ch) : ch);
1✔
2664
        }
2665
        return builder.toString();
1✔
2666
    }
2667

2668
    public static String unescape(final String value) {
2669
        return value.replace("&#x60;", "`")
1✔
2670
                .replace("&#x27;", "'")
1✔
2671
                .replace("&lt;", "<")
1✔
2672
                .replace("&gt;", ">")
1✔
2673
                .replace("&quot;", "\"")
1✔
2674
                .replace("&amp;", "&");
1✔
2675
    }
2676

2677
    /*
2678
     * Documented, #result
2679
     */
2680
    public static <E> Object result(final Iterable<E> iterable, final Predicate<E> pred) {
2681
        for (E element : iterable) {
1✔
2682
            if (pred.test(element)) {
1✔
2683
                if (element instanceof Map.Entry) {
1✔
2684
                    if (((Map.Entry) element).getValue() instanceof Supplier) {
1✔
2685
                        return ((Supplier) ((Map.Entry) element).getValue()).get();
1✔
2686
                    }
2687
                    return ((Map.Entry) element).getValue();
1✔
2688
                }
2689
                return element;
1✔
2690
            }
2691
        }
1✔
2692
        return null;
1✔
2693
    }
2694

2695
    /*
2696
     * Documented, #uniqueId
2697
     */
2698
    public static String uniqueId(final String prefix) {
2699
        return (prefix == null ? "" : prefix) + UNIQUE_ID.incrementAndGet();
1✔
2700
    }
2701

2702
    /*
2703
     * Documented, #uniquePassword
2704
     */
2705
    public static String uniquePassword() {
2706
        final String[] passwords =
1✔
2707
                new String[] {
2708
                    "ALKJVBPIQYTUIWEBVPQALZVKQRWORTUYOYISHFLKAJMZNXBVMNFGAHKJSDFALAPOQIERIUYTGSFGKMZNXBVJAHGFAKX",
2709
                    "1234567890",
2710
                    "qpowiealksdjzmxnvbfghsdjtreiuowiruksfhksajmzxncbvlaksjdhgqwetytopskjhfgvbcnmzxalksjdfhgbvzm",
2711
                    ".@,-+/()#$%^&*!"
2712
                };
2713
        final StringBuilder result = new StringBuilder();
1✔
2714
        final long passwordLength =
2715
                Math.abs(UUID.randomUUID().getLeastSignificantBits() % MIN_PASSWORD_LENGTH_8)
1✔
2716
                        + MIN_PASSWORD_LENGTH_8;
2717
        for (int index = 0; index < passwordLength; index += 1) {
1✔
2718
            final int passIndex = (int) (passwords.length * (long) index / passwordLength);
1✔
2719
            final int charIndex =
2720
                    (int)
2721
                            Math.abs(
1✔
2722
                                    UUID.randomUUID().getLeastSignificantBits()
1✔
2723
                                            % passwords[passIndex].length());
1✔
2724
            result.append(passwords[passIndex].charAt(charIndex));
1✔
2725
        }
2726
        return result.toString();
1✔
2727
    }
2728

2729
    public static <K, V> Template<Map<K, V>> template(final String template) {
2730
        return new TemplateImpl<>(template);
1✔
2731
    }
2732

2733
    public static String format(final String template, final Object... params) {
2734
        final java.util.regex.Matcher matcher = FORMAT_PATTERN.matcher(template);
1✔
2735
        final StringBuilder buffer = new StringBuilder();
1✔
2736
        int index = 0;
1✔
2737
        while (matcher.find()) {
1✔
2738
            if (matcher.group(1).isEmpty()) {
1✔
2739
                matcher.appendReplacement(buffer, "<%" + index++ + "%>");
1✔
2740
            } else {
2741
                matcher.appendReplacement(buffer, "<%" + matcher.group(1) + "%>");
1✔
2742
            }
2743
        }
2744
        matcher.appendTail(buffer);
1✔
2745
        final String newTemplate = buffer.toString();
1✔
2746
        final Map<Integer, String> args = new LinkedHashMap<>();
1✔
2747
        index = 0;
1✔
2748
        for (Object param : params) {
1✔
2749
            args.put(index, param.toString());
1✔
2750
            index += 1;
1✔
2751
        }
2752
        return new TemplateImpl<Integer, String>(newTemplate).apply(args);
1✔
2753
    }
2754

2755
    public static <T> Iterable<T> iterate(final T seed, final UnaryOperator<T> unaryOperator) {
2756
        return new MyIterable<>(seed, unaryOperator);
1✔
2757
    }
2758

2759
    /*
2760
     * Documented, #chain
2761
     */
2762
    public static <T> Chain<T> chain(final List<T> list) {
2763
        return new Underscore.Chain<>(list);
1✔
2764
    }
2765

2766
    public static Chain<Map<String, Object>> chain(final Map<String, Object> map) {
2767
        return new Underscore.Chain<>(map);
1✔
2768
    }
2769

2770
    public static <T> Chain<T> chain(final Iterable<T> iterable) {
2771
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2772
    }
2773

2774
    public static <T> Chain<T> chain(final Iterable<T> iterable, int size) {
2775
        return new Underscore.Chain<>(newArrayList(iterable, size));
1✔
2776
    }
2777

2778
    @SuppressWarnings("unchecked")
2779
    public static <T> Chain<T> chain(final T... array) {
2780
        return new Underscore.Chain<>(Arrays.asList(array));
1✔
2781
    }
2782

2783
    public static Chain<Integer> chain(final int[] array) {
2784
        return new Underscore.Chain<>(newIntegerList(array));
1✔
2785
    }
2786

2787
    public Chain<T> chain() {
2788
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2789
    }
2790

2791
    public static <T> Chain<T> of(final List<T> list) {
2792
        return new Underscore.Chain<>(list);
1✔
2793
    }
2794

2795
    public static <T> Chain<T> of(final Iterable<T> iterable) {
2796
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2797
    }
2798

2799
    public static <T> Chain<T> of(final Iterable<T> iterable, int size) {
2800
        return new Underscore.Chain<>(newArrayList(iterable, size));
1✔
2801
    }
2802

2803
    @SuppressWarnings("unchecked")
2804
    public static <T> Chain<T> of(final T... array) {
2805
        return new Underscore.Chain<>(Arrays.asList(array));
1✔
2806
    }
2807

2808
    public static Chain<Integer> of(final int[] array) {
2809
        return new Underscore.Chain<>(newIntegerList(array));
1✔
2810
    }
2811

2812
    public Chain<T> of() {
2813
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2814
    }
2815

2816
    public static class Chain<T> {
2817
        private final T item;
2818
        private final List<T> list;
2819
        private final Map<String, Object> map;
2820

2821
        public Chain(final T item) {
1✔
2822
            this.item = item;
1✔
2823
            this.list = null;
1✔
2824
            this.map = null;
1✔
2825
        }
1✔
2826

2827
        public Chain(final List<T> list) {
1✔
2828
            this.item = null;
1✔
2829
            this.list = list;
1✔
2830
            this.map = null;
1✔
2831
        }
1✔
2832

2833
        public Chain(final Map<String, Object> map) {
1✔
2834
            this.item = null;
1✔
2835
            this.list = null;
1✔
2836
            this.map = map;
1✔
2837
        }
1✔
2838

2839
        public Chain<T> first() {
2840
            return new Chain<>(Underscore.first(list));
1✔
2841
        }
2842

2843
        public Chain<T> first(int n) {
2844
            return new Chain<>(Underscore.first(list, n));
1✔
2845
        }
2846

2847
        public Chain<T> first(final Predicate<T> pred) {
2848
            return new Chain<>(Underscore.first(list, pred));
1✔
2849
        }
2850

2851
        public Chain<T> first(final Predicate<T> pred, int n) {
2852
            return new Chain<>(Underscore.first(list, pred, n));
1✔
2853
        }
2854

2855
        public Chain<T> firstOrNull() {
2856
            return new Chain<>(Underscore.firstOrNull(list));
1✔
2857
        }
2858

2859
        public Chain<T> firstOrNull(final Predicate<T> pred) {
2860
            return new Chain<>(Underscore.firstOrNull(list, pred));
1✔
2861
        }
2862

2863
        public Chain<T> initial() {
2864
            return new Chain<>(Underscore.initial(list));
1✔
2865
        }
2866

2867
        public Chain<T> initial(int n) {
2868
            return new Chain<>(Underscore.initial(list, n));
1✔
2869
        }
2870

2871
        public Chain<T> last() {
2872
            return new Chain<>(Underscore.last(list));
1✔
2873
        }
2874

2875
        public Chain<T> last(int n) {
2876
            return new Chain<>(Underscore.last(list, n));
1✔
2877
        }
2878

2879
        public Chain<T> lastOrNull() {
2880
            return new Chain<>(Underscore.lastOrNull(list));
1✔
2881
        }
2882

2883
        public Chain<T> lastOrNull(final Predicate<T> pred) {
2884
            return new Chain<>(Underscore.lastOrNull(list, pred));
1✔
2885
        }
2886

2887
        public Chain<T> rest() {
2888
            return new Chain<>(Underscore.rest(list));
1✔
2889
        }
2890

2891
        public Chain<T> rest(int n) {
2892
            return new Chain<>(Underscore.rest(list, n));
1✔
2893
        }
2894

2895
        public Chain<T> compact() {
2896
            return new Chain<>(Underscore.compact(list));
1✔
2897
        }
2898

2899
        public Chain<T> compact(final T falsyValue) {
2900
            return new Chain<>(Underscore.compactList(list, falsyValue));
1✔
2901
        }
2902

2903
        @SuppressWarnings("unchecked")
2904
        public Chain flatten() {
2905
            return new Chain<>(Underscore.flatten(list));
1✔
2906
        }
2907

2908
        public <F> Chain<F> map(final Function<? super T, F> func) {
2909
            return new Chain<>(Underscore.map(list, func));
1✔
2910
        }
2911

2912
        public <F> Chain<F> mapMulti(final BiConsumer<? super T, ? super Consumer<F>> mapper) {
2913
            return new Chain<>(Underscore.mapMulti(list, mapper));
1✔
2914
        }
2915

2916
        public <F> Chain<F> mapIndexed(final BiFunction<Integer, ? super T, F> func) {
2917
            return new Chain<>(Underscore.mapIndexed(list, func));
1✔
2918
        }
2919

2920
        public Chain<T> replace(final Predicate<T> pred, final T value) {
2921
            return new Chain<>(Underscore.replace(list, pred, value));
1✔
2922
        }
2923

2924
        public Chain<T> replaceIndexed(final PredicateIndexed<T> pred, final T value) {
2925
            return new Chain<>(Underscore.replaceIndexed(list, pred, value));
1✔
2926
        }
2927

2928
        public Chain<T> filter(final Predicate<T> pred) {
2929
            return new Chain<>(Underscore.filter(list, pred));
1✔
2930
        }
2931

2932
        public Chain<T> filterIndexed(final PredicateIndexed<T> pred) {
2933
            return new Chain<>(Underscore.filterIndexed(list, pred));
1✔
2934
        }
2935

2936
        public Chain<T> reject(final Predicate<T> pred) {
2937
            return new Chain<>(Underscore.reject(list, pred));
1✔
2938
        }
2939

2940
        public Chain<T> rejectIndexed(final PredicateIndexed<T> pred) {
2941
            return new Chain<>(Underscore.rejectIndexed(list, pred));
1✔
2942
        }
2943

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

2948
        public <F> Chain<F> reduce(final BiFunction<F, T, F> func, final F zeroElem) {
2949
            return new Chain<>(Underscore.reduce(list, func, zeroElem));
1✔
2950
        }
2951

2952
        public Chain<Optional<T>> reduce(final BinaryOperator<T> func) {
2953
            return new Chain<>(Underscore.reduce(list, func));
1✔
2954
        }
2955

2956
        public <F> Chain<F> reduceRight(final BiFunction<F, T, F> func, final F zeroElem) {
2957
            return new Chain<>(Underscore.reduceRight(list, func, zeroElem));
1✔
2958
        }
2959

2960
        public Chain<Optional<T>> reduceRight(final BinaryOperator<T> func) {
2961
            return new Chain<>(Underscore.reduceRight(list, func));
1✔
2962
        }
2963

2964
        public Chain<Optional<T>> find(final Predicate<T> pred) {
2965
            return new Chain<>(Underscore.find(list, pred));
1✔
2966
        }
2967

2968
        public Chain<Optional<T>> findLast(final Predicate<T> pred) {
2969
            return new Chain<>(Underscore.findLast(list, pred));
1✔
2970
        }
2971

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

2977
        public <F extends Comparable<? super F>> Chain<T> max(final Function<T, F> func) {
2978
            return new Chain<>(Underscore.max(list, func));
1✔
2979
        }
2980

2981
        @SuppressWarnings("unchecked")
2982
        public Chain<Comparable> min() {
2983
            return new Chain<>(Underscore.min((Collection) list));
1✔
2984
        }
2985

2986
        public <F extends Comparable<? super F>> Chain<T> min(final Function<T, F> func) {
2987
            return new Chain<>(Underscore.min(list, func));
1✔
2988
        }
2989

2990
        @SuppressWarnings("unchecked")
2991
        public Chain<Comparable> sort() {
2992
            return new Chain<>(Underscore.sort((List<Comparable>) list));
1✔
2993
        }
2994

2995
        @SuppressWarnings("unchecked")
2996
        public <F extends Comparable<? super F>> Chain<F> sortWith(final Comparator<F> comparator) {
2997
            return new Chain<>(Underscore.sortWith((List<F>) list, comparator));
1✔
2998
        }
2999

3000
        public <F extends Comparable<? super F>> Chain<T> sortBy(final Function<T, F> func) {
3001
            return new Chain<>(Underscore.sortBy(list, func));
1✔
3002
        }
3003

3004
        @SuppressWarnings("unchecked")
3005
        public <K> Chain<Map<K, Comparable>> sortBy(final K key) {
3006
            return new Chain<>(Underscore.sortBy((List<Map<K, Comparable>>) list, key));
1✔
3007
        }
3008

3009
        public <F> Chain<Map<F, List<T>>> groupBy(final Function<T, F> func) {
3010
            return new Chain<>(Underscore.groupBy(list, func));
1✔
3011
        }
3012

3013
        public <F> Chain<Map<F, T>> associateBy(final Function<T, F> func) {
3014
            return new Chain<>(Underscore.associateBy(list, func));
1✔
3015
        }
3016

3017
        public <F> Chain<Map<F, Optional<T>>> groupBy(
3018
                final Function<T, F> func, final BinaryOperator<T> binaryOperator) {
3019
            return new Chain<>(Underscore.groupBy(list, func, binaryOperator));
1✔
3020
        }
3021

3022
        public Chain<Map<Object, List<T>>> indexBy(final String property) {
3023
            return new Chain<>(Underscore.indexBy(list, property));
1✔
3024
        }
3025

3026
        public <F> Chain<Map<F, Integer>> countBy(final Function<T, F> func) {
3027
            return new Chain<>(Underscore.countBy(list, func));
1✔
3028
        }
3029

3030
        public Chain<Map<T, Integer>> countBy() {
3031
            return new Chain<>(Underscore.countBy(list));
1✔
3032
        }
3033

3034
        public Chain<T> shuffle() {
3035
            return new Chain<>(Underscore.shuffle(list));
1✔
3036
        }
3037

3038
        public Chain<T> sample() {
3039
            return new Chain<>(Underscore.sample(list));
1✔
3040
        }
3041

3042
        public Chain<T> sample(final int howMany) {
3043
            return new Chain<>(Underscore.newArrayList(Underscore.sample(list, howMany)));
1✔
3044
        }
3045

3046
        public Chain<T> tap(final Consumer<T> func) {
3047
            Underscore.each(list, func);
1✔
3048
            return new Chain<>(list);
1✔
3049
        }
3050

3051
        public Chain<T> forEach(final Consumer<T> func) {
3052
            return tap(func);
1✔
3053
        }
3054

3055
        public Chain<T> forEachRight(final Consumer<T> func) {
3056
            Underscore.eachRight(list, func);
1✔
3057
            return new Chain<>(list);
1✔
3058
        }
3059

3060
        public Chain<Boolean> every(final Predicate<T> pred) {
3061
            return new Chain<>(Underscore.every(list, pred));
1✔
3062
        }
3063

3064
        public Chain<Boolean> some(final Predicate<T> pred) {
3065
            return new Chain<>(Underscore.some(list, pred));
1✔
3066
        }
3067

3068
        public Chain<Integer> count(final Predicate<T> pred) {
3069
            return new Chain<>(Underscore.count(list, pred));
1✔
3070
        }
3071

3072
        public Chain<Boolean> contains(final T elem) {
3073
            return new Chain<>(Underscore.contains(list, elem));
1✔
3074
        }
3075

3076
        public Chain<Boolean> containsWith(final T elem) {
3077
            return new Chain<>(Underscore.containsWith(list, elem));
1✔
3078
        }
3079

3080
        public Chain<T> invoke(final String methodName, final List<Object> args) {
3081
            return new Chain<>(Underscore.invoke(list, methodName, args));
1✔
3082
        }
3083

3084
        public Chain<T> invoke(final String methodName) {
3085
            return new Chain<>(Underscore.invoke(list, methodName));
1✔
3086
        }
3087

3088
        public Chain<Object> pluck(final String propertyName) {
3089
            return new Chain<>(Underscore.pluck(list, propertyName));
1✔
3090
        }
3091

3092
        public <E> Chain<T> where(final List<Map.Entry<String, E>> properties) {
3093
            return new Chain<>(Underscore.where(list, properties));
1✔
3094
        }
3095

3096
        public <E> Chain<Optional<T>> findWhere(final List<Map.Entry<String, E>> properties) {
3097
            return new Chain<>(Underscore.findWhere(list, properties));
1✔
3098
        }
3099

3100
        public Chain<T> uniq() {
3101
            return new Chain<>(Underscore.uniq(list));
1✔
3102
        }
3103

3104
        public <F> Chain<T> uniq(final Function<T, F> func) {
3105
            return new Chain<>(Underscore.newArrayList(Underscore.uniq(list, func)));
1✔
3106
        }
3107

3108
        public Chain<T> distinct() {
3109
            return new Chain<>(Underscore.uniq(list));
1✔
3110
        }
3111

3112
        @SuppressWarnings("unchecked")
3113
        public <F> Chain<F> distinctBy(final Function<T, F> func) {
3114
            return new Chain<>(Underscore.newArrayList((Iterable<F>) Underscore.uniq(list, func)));
1✔
3115
        }
3116

3117
        @SuppressWarnings("unchecked")
3118
        public Chain<T> union(final List<T>... lists) {
3119
            return new Chain<>(Underscore.union(list, lists));
1✔
3120
        }
3121

3122
        @SuppressWarnings("unchecked")
3123
        public Chain<T> intersection(final List<T>... lists) {
3124
            return new Chain<>(Underscore.intersection(list, lists));
1✔
3125
        }
3126

3127
        @SuppressWarnings("unchecked")
3128
        public Chain<T> difference(final List<T>... lists) {
3129
            return new Chain<>(Underscore.difference(list, lists));
1✔
3130
        }
3131

3132
        public Chain<Integer> range(final int stop) {
3133
            return new Chain<>(Underscore.range(stop));
1✔
3134
        }
3135

3136
        public Chain<Integer> range(final int start, final int stop) {
3137
            return new Chain<>(Underscore.range(start, stop));
1✔
3138
        }
3139

3140
        public Chain<Integer> range(final int start, final int stop, final int step) {
3141
            return new Chain<>(Underscore.range(start, stop, step));
1✔
3142
        }
3143

3144
        public Chain<List<T>> chunk(final int size) {
3145
            return new Chain<>(Underscore.chunk(value(), size, size));
1✔
3146
        }
3147

3148
        public Chain<List<T>> chunk(final int size, final int step) {
3149
            return new Chain<>(Underscore.chunk(value(), size, step));
1✔
3150
        }
3151

3152
        public Chain<List<T>> chunkFill(final int size, final T fillValue) {
3153
            return new Chain<>(Underscore.chunkFill(value(), size, size, fillValue));
1✔
3154
        }
3155

3156
        public Chain<List<T>> chunkFill(final int size, final int step, final T fillValue) {
3157
            return new Chain<>(Underscore.chunkFill(value(), size, step, fillValue));
1✔
3158
        }
3159

3160
        public Chain<T> cycle(final int times) {
3161
            return new Chain<>(Underscore.cycle(value(), times));
1✔
3162
        }
3163

3164
        public Chain<T> interpose(final T element) {
3165
            return new Chain<>(Underscore.interpose(value(), element));
1✔
3166
        }
3167

3168
        public Chain<T> interposeByList(final Iterable<T> interIter) {
3169
            return new Chain<>(Underscore.interposeByList(value(), interIter));
1✔
3170
        }
3171

3172
        @SuppressWarnings("unchecked")
3173
        public Chain<T> concat(final List<T>... lists) {
3174
            return new Chain<>(Underscore.concat(list, lists));
1✔
3175
        }
3176

3177
        public Chain<T> slice(final int start) {
3178
            return new Chain<>(Underscore.slice(list, start));
1✔
3179
        }
3180

3181
        public Chain<T> slice(final int start, final int end) {
3182
            return new Chain<>(Underscore.slice(list, start, end));
1✔
3183
        }
3184

3185
        public Chain<List<T>> splitAt(final int position) {
3186
            return new Chain<>(Underscore.splitAt(list, position));
1✔
3187
        }
3188

3189
        public Chain<T> takeSkipping(final int stepSize) {
3190
            return new Chain<>(Underscore.takeSkipping(list, stepSize));
1✔
3191
        }
3192

3193
        public Chain<T> reverse() {
3194
            return new Chain<>(Underscore.reverse(list));
1✔
3195
        }
3196

3197
        public Chain<String> join() {
3198
            return new Chain<>(Underscore.join(list));
1✔
3199
        }
3200

3201
        public Chain<String> join(final String separator) {
3202
            return new Chain<>(Underscore.join(list, separator));
1✔
3203
        }
3204

3205
        @SuppressWarnings("unchecked")
3206
        public Chain<T> push(final T... values) {
3207
            return new Chain<>(Underscore.push(value(), values));
1✔
3208
        }
3209

3210
        public Chain<Map.Entry<T, List<T>>> pop() {
3211
            return new Chain<>(Underscore.pop(value()));
1✔
3212
        }
3213

3214
        public Chain<Map.Entry<T, List<T>>> shift() {
3215
            return new Chain<>(Underscore.shift(value()));
1✔
3216
        }
3217

3218
        @SuppressWarnings("unchecked")
3219
        public Chain<T> unshift(final T... values) {
3220
            return new Chain<>(Underscore.unshift(value(), values));
1✔
3221
        }
3222

3223
        public Chain<T> skip(final int numberToSkip) {
3224
            return new Chain<>(list.subList(numberToSkip, list.size()));
1✔
3225
        }
3226

3227
        public Chain<T> limit(final int size) {
3228
            return new Chain<>(Underscore.first(list, size));
1✔
3229
        }
3230

3231
        @SuppressWarnings("unchecked")
3232
        public <K, V> Chain<Map<K, V>> toMap() {
3233
            return new Chain<>(Underscore.toMap((Iterable<Map.Entry<K, V>>) list));
1✔
3234
        }
3235

3236
        public boolean isEmpty() {
3237
            return Underscore.isEmpty(list);
1✔
3238
        }
3239

3240
        public boolean isNotEmpty() {
3241
            return Underscore.isNotEmpty(list);
1✔
3242
        }
3243

3244
        public int size() {
3245
            return Underscore.size(list);
1✔
3246
        }
3247

3248
        public T item() {
3249
            return item;
1✔
3250
        }
3251

3252
        /*
3253
         * Documented, #value
3254
         */
3255
        public List<T> value() {
3256
            return list;
1✔
3257
        }
3258

3259
        public Map<String, Object> map() {
3260
            return map;
1✔
3261
        }
3262

3263
        public List<T> toList() {
3264
            return list;
1✔
3265
        }
3266

3267
        public String toString() {
3268
            return String.valueOf(list);
1✔
3269
        }
3270
    }
3271

3272
    /*
3273
     * Documented, #mixin
3274
     */
3275
    public static void mixin(final String funcName, final UnaryOperator<String> func) {
3276
        FUNCTIONS.put(funcName, func);
1✔
3277
    }
1✔
3278

3279
    public Optional<String> call(final String funcName) {
3280
        if (string.isPresent() && FUNCTIONS.containsKey(funcName)) {
1✔
3281
            return Optional.of(FUNCTIONS.get(funcName).apply(string.get()));
1✔
3282
        }
3283
        return Optional.empty();
1✔
3284
    }
3285

3286
    public static <T extends Comparable<T>> List<T> sort(final Iterable<T> iterable) {
3287
        final List<T> localList = newArrayList(iterable);
1✔
3288
        Collections.sort(localList);
1✔
3289
        return localList;
1✔
3290
    }
3291

3292
    @SuppressWarnings("unchecked")
3293
    public static <T extends Comparable<T>> T[] sort(final T... array) {
3294
        final T[] localArray = array.clone();
1✔
3295
        Arrays.sort(localArray);
1✔
3296
        return localArray;
1✔
3297
    }
3298

3299
    @SuppressWarnings("unchecked")
3300
    public List<Comparable> sort() {
3301
        return sort((Iterable<Comparable>) iterable);
1✔
3302
    }
3303

3304
    /*
3305
     * Documented, #join
3306
     */
3307
    public static <T> String join(final Iterable<T> iterable, final String separator) {
3308
        final StringBuilder sb = new StringBuilder();
1✔
3309
        int index = 0;
1✔
3310
        for (final T item : iterable) {
1✔
3311
            if (index > 0) {
1✔
3312
                sb.append(separator);
1✔
3313
            }
3314
            sb.append(item.toString());
1✔
3315
            index += 1;
1✔
3316
        }
1✔
3317
        return sb.toString();
1✔
3318
    }
3319

3320
    public static <T> String joinToString(
3321
            final Iterable<T> iterable,
3322
            final String separator,
3323
            final String prefix,
3324
            final String postfix,
3325
            final int limit,
3326
            final String truncated,
3327
            final Function<T, String> transform) {
3328
        final StringBuilder sb = new StringBuilder();
1✔
3329
        int index = 0;
1✔
3330
        if (prefix != null) {
1✔
3331
            sb.append(prefix);
1✔
3332
        }
3333
        for (final T item : iterable) {
1✔
3334
            if (index > 0) {
1✔
3335
                sb.append(separator);
1✔
3336
            }
3337
            index += 1;
1✔
3338
            if (limit < 0 || index <= limit) {
1✔
3339
                sb.append(transform == null ? item.toString() : transform.apply(item));
1✔
3340
            } else {
3341
                break;
3342
            }
3343
        }
1✔
3344
        joinToStringPostfix(postfix, limit, truncated, index, sb);
1✔
3345
        return sb.toString();
1✔
3346
    }
3347

3348
    private static void joinToStringPostfix(
3349
            String postfix, int limit, String truncated, int index, StringBuilder sb) {
3350
        if (limit >= 0 && index > limit) {
1✔
3351
            sb.append(truncated == null ? "..." : truncated);
1✔
3352
        }
3353
        if (postfix != null) {
1✔
3354
            sb.append(postfix);
1✔
3355
        }
3356
    }
1✔
3357

3358
    public static <T> String join(final Iterable<T> iterable) {
3359
        return join(iterable, " ");
1✔
3360
    }
3361

3362
    public static <T> String join(final T[] array, final String separator) {
3363
        return join(Arrays.asList(array), separator);
1✔
3364
    }
3365

3366
    public static <T> String join(final T[] array) {
3367
        return join(array, " ");
1✔
3368
    }
3369

3370
    public String join(final String separator) {
3371
        return join(iterable, separator);
1✔
3372
    }
3373

3374
    public String join() {
3375
        return join(iterable);
1✔
3376
    }
3377

3378
    @SuppressWarnings("unchecked")
3379
    public static <T> List<T> push(final List<T> list, final T... values) {
3380
        final List<T> result = newArrayList(list);
1✔
3381
        Collections.addAll(result, values);
1✔
3382
        return result;
1✔
3383
    }
3384

3385
    @SuppressWarnings("unchecked")
3386
    public List<T> push(final T... values) {
3387
        return push((List<T>) getIterable(), values);
1✔
3388
    }
3389

3390
    public static <T> Map.Entry<T, List<T>> pop(final List<T> list) {
3391
        return Map.entry(last(list), initial(list));
1✔
3392
    }
3393

3394
    public Map.Entry<T, List<T>> pop() {
3395
        return pop((List<T>) getIterable());
1✔
3396
    }
3397

3398
    @SuppressWarnings("unchecked")
3399
    public static <T> List<T> unshift(final List<T> list, final T... values) {
3400
        final List<T> result = newArrayList(list);
1✔
3401
        int index = 0;
1✔
3402
        for (T value : values) {
1✔
3403
            result.add(index, value);
1✔
3404
            index += 1;
1✔
3405
        }
3406
        return result;
1✔
3407
    }
3408

3409
    @SuppressWarnings("unchecked")
3410
    public List<T> unshift(final T... values) {
3411
        return unshift((List<T>) getIterable(), values);
1✔
3412
    }
3413

3414
    public static <T> Map.Entry<T, List<T>> shift(final List<T> list) {
3415
        return Map.entry(first(list), rest(list));
1✔
3416
    }
3417

3418
    public Map.Entry<T, List<T>> shift() {
3419
        return shift((List<T>) getIterable());
1✔
3420
    }
3421

3422
    @SuppressWarnings("unchecked")
3423
    public static <T> T[] concat(final T[] first, final T[]... other) {
3424
        int length = 0;
1✔
3425
        for (T[] otherItem : other) {
1✔
3426
            length += otherItem.length;
1✔
3427
        }
3428
        final T[] result = Arrays.copyOf(first, first.length + length);
1✔
3429
        int index = 0;
1✔
3430
        for (T[] otherItem : other) {
1✔
3431
            System.arraycopy(otherItem, 0, result, first.length + index, otherItem.length);
1✔
3432
            index += otherItem.length;
1✔
3433
        }
3434
        return result;
1✔
3435
    }
3436

3437
    /*
3438
     * Documented, #concat
3439
     */
3440
    @SuppressWarnings("unchecked")
3441
    public static <T> List<T> concat(final Iterable<T> first, final Iterable<T>... other) {
3442
        List<T> list = newArrayList(first);
1✔
3443
        for (Iterable<T> iter : other) {
1✔
3444
            list.addAll(newArrayList(iter));
1✔
3445
        }
3446
        return list;
1✔
3447
    }
3448

3449
    @SuppressWarnings("unchecked")
3450
    public List<T> concatWith(final Iterable<T>... other) {
3451
        return concat(iterable, other);
1✔
3452
    }
3453

3454
    /*
3455
     * Documented, #slice
3456
     */
3457
    public static <T> List<T> slice(final Iterable<T> iterable, final int start) {
3458
        final List<T> result;
3459
        if (start >= 0) {
1✔
3460
            result = newArrayList(iterable).subList(start, size(iterable));
1✔
3461
        } else {
3462
            result = newArrayList(iterable).subList(size(iterable) + start, size(iterable));
1✔
3463
        }
3464
        return result;
1✔
3465
    }
3466

3467
    public static <T> T[] slice(final T[] array, final int start) {
3468
        final T[] result;
3469
        if (start >= 0) {
1✔
3470
            result = Arrays.copyOfRange(array, start, array.length);
1✔
3471
        } else {
3472
            result = Arrays.copyOfRange(array, array.length + start, array.length);
1✔
3473
        }
3474
        return result;
1✔
3475
    }
3476

3477
    public List<T> slice(final int start) {
3478
        return slice(iterable, start);
1✔
3479
    }
3480

3481
    public static <T> List<T> slice(final Iterable<T> iterable, final int start, final int end) {
3482
        final List<T> result;
3483
        if (start >= 0) {
1✔
3484
            if (end > 0) {
1✔
3485
                result = newArrayList(iterable).subList(start, end);
1✔
3486
            } else {
3487
                result = newArrayList(iterable).subList(start, size(iterable) + end);
1✔
3488
            }
3489
        } else {
3490
            if (end > 0) {
1✔
3491
                result = newArrayList(iterable).subList(size(iterable) + start, end);
1✔
3492
            } else {
3493
                result =
1✔
3494
                        newArrayList(iterable)
1✔
3495
                                .subList(size(iterable) + start, size(iterable) + end);
1✔
3496
            }
3497
        }
3498
        return result;
1✔
3499
    }
3500

3501
    public static <T> T[] slice(final T[] array, final int start, final int end) {
3502
        final T[] result;
3503
        if (start >= 0) {
1✔
3504
            if (end > 0) {
1✔
3505
                result = Arrays.copyOfRange(array, start, end);
1✔
3506
            } else {
3507
                result = Arrays.copyOfRange(array, start, array.length + end);
1✔
3508
            }
3509
        } else {
3510
            if (end > 0) {
1✔
3511
                result = Arrays.copyOfRange(array, array.length + start, end);
1✔
3512
            } else {
3513
                result = Arrays.copyOfRange(array, array.length + start, array.length + end);
1✔
3514
            }
3515
        }
3516
        return result;
1✔
3517
    }
3518

3519
    public List<T> slice(final int start, final int end) {
3520
        return slice(iterable, start, end);
1✔
3521
    }
3522

3523
    public static <T> List<List<T>> splitAt(final Iterable<T> iterable, final int position) {
3524
        List<List<T>> result = new ArrayList<>();
1✔
3525
        int size = size(iterable);
1✔
3526
        final int index;
3527
        if (position < 0) {
1✔
3528
            index = 0;
1✔
3529
        } else {
3530
            index = Math.min(position, size);
1✔
3531
        }
3532
        result.add(newArrayList(iterable).subList(0, index));
1✔
3533
        result.add(newArrayList(iterable).subList(index, size));
1✔
3534
        return result;
1✔
3535
    }
3536

3537
    public static <T> List<List<T>> splitAt(final T[] array, final int position) {
3538
        return splitAt(Arrays.asList(array), position);
1✔
3539
    }
3540

3541
    public List<List<T>> splitAt(final int position) {
3542
        return splitAt(iterable, position);
1✔
3543
    }
3544

3545
    public static <T> List<T> takeSkipping(final Iterable<T> iterable, final int stepSize) {
3546
        List<T> result = new ArrayList<>();
1✔
3547
        if (stepSize <= 0) {
1✔
3548
            return result;
1✔
3549
        }
3550
        int size = size(iterable);
1✔
3551
        if (stepSize > size) {
1✔
3552
            result.add(first(iterable));
1✔
3553
            return result;
1✔
3554
        }
3555
        int i = 0;
1✔
3556
        for (T element : iterable) {
1✔
3557
            if (i++ % stepSize == 0) {
1✔
3558
                result.add(element);
1✔
3559
            }
3560
        }
1✔
3561
        return result;
1✔
3562
    }
3563

3564
    public static <T> List<T> takeSkipping(final T[] array, final int stepSize) {
3565
        return takeSkipping(Arrays.asList(array), stepSize);
1✔
3566
    }
3567

3568
    public List<T> takeSkipping(final int stepSize) {
3569
        return takeSkipping(iterable, stepSize);
1✔
3570
    }
3571

3572
    /*
3573
     * Documented, #reverse
3574
     */
3575
    public static <T> List<T> reverse(final Iterable<T> iterable) {
3576
        final List<T> result = newArrayList(iterable);
1✔
3577
        Collections.reverse(result);
1✔
3578
        return result;
1✔
3579
    }
3580

3581
    @SuppressWarnings("unchecked")
3582
    public static <T> T[] reverse(final T... array) {
3583
        T temp;
3584
        final T[] newArray = array.clone();
1✔
3585
        for (int index = 0; index < array.length / 2; index += 1) {
1✔
3586
            temp = newArray[index];
1✔
3587
            newArray[index] = newArray[array.length - 1 - index];
1✔
3588
            newArray[array.length - 1 - index] = temp;
1✔
3589
        }
3590
        return newArray;
1✔
3591
    }
3592

3593
    public static List<Integer> reverse(final int[] array) {
3594
        final List<Integer> result = newIntegerList(array);
1✔
3595
        Collections.reverse(result);
1✔
3596
        return result;
1✔
3597
    }
3598

3599
    public List<T> reverse() {
3600
        return reverse(iterable);
1✔
3601
    }
3602

3603
    public Iterable<T> getIterable() {
3604
        return iterable;
1✔
3605
    }
3606

3607
    public Iterable<T> value() {
3608
        return iterable;
1✔
3609
    }
3610

3611
    public Optional<String> getString() {
3612
        return string;
1✔
3613
    }
3614

3615
    public static <T> java.util.concurrent.ScheduledFuture<T> setTimeout(
3616
            final Supplier<T> function, final int delayMilliseconds) {
3617
        return delay(function, delayMilliseconds);
1✔
3618
    }
3619

3620
    public static void clearTimeout(java.util.concurrent.ScheduledFuture<?> scheduledFuture) {
3621
        if (scheduledFuture != null) {
1✔
3622
            scheduledFuture.cancel(true);
1✔
3623
        }
3624
    }
1✔
3625

3626
    public static <T> java.util.concurrent.ScheduledFuture setInterval(
3627
            final Supplier<T> function, final int delayMilliseconds) {
3628
        final java.util.concurrent.ScheduledExecutorService scheduler =
3629
                java.util.concurrent.Executors.newSingleThreadScheduledExecutor();
1✔
3630
        Runtime.getRuntime().addShutdownHook(new Thread(scheduler::shutdown));
1✔
3631
        return scheduler.scheduleAtFixedRate(
1✔
3632
                function::get,
1✔
3633
                delayMilliseconds,
3634
                delayMilliseconds,
3635
                java.util.concurrent.TimeUnit.MILLISECONDS);
3636
    }
3637

3638
    public static void clearInterval(java.util.concurrent.ScheduledFuture scheduledFuture) {
3639
        clearTimeout(scheduledFuture);
1✔
3640
    }
1✔
3641

3642
    public static <T> List<T> copyOf(final Iterable<T> iterable) {
3643
        return newArrayList(iterable);
1✔
3644
    }
3645

3646
    public List<T> copyOf() {
3647
        return newArrayList(value());
1✔
3648
    }
3649

3650
    public static <T> List<T> copyOfRange(
3651
            final Iterable<T> iterable, final int start, final int end) {
3652
        return slice(iterable, start, end);
1✔
3653
    }
3654

3655
    public List<T> copyOfRange(final int start, final int end) {
3656
        return slice(value(), start, end);
1✔
3657
    }
3658

3659
    public static <T> T elementAt(final List<T> list, final int index) {
3660
        return list.get(index);
1✔
3661
    }
3662

3663
    public T elementAt(final int index) {
3664
        return elementAt((List<T>) value(), index);
1✔
3665
    }
3666

3667
    public static <T> T get(final List<T> list, final int index) {
3668
        return elementAt(list, index);
1✔
3669
    }
3670

3671
    public T get(final int index) {
3672
        return elementAt((List<T>) value(), index);
1✔
3673
    }
3674

3675
    public static <T> Map.Entry<T, List<T>> set(
3676
            final List<T> list, final int index, final T value) {
3677
        final List<T> newList = newArrayList(list);
1✔
3678
        return Map.entry(newList.set(index, value), newList);
1✔
3679
    }
3680

3681
    public Map.Entry<T, List<T>> set(final int index, final T value) {
3682
        return set((List<T>) value(), index, value);
1✔
3683
    }
3684

3685
    public static <T> T elementAtOrElse(final List<T> list, final int index, T defaultValue) {
3686
        try {
3687
            return list.get(index);
1✔
3688
        } catch (IndexOutOfBoundsException ex) {
1✔
3689
            return defaultValue;
1✔
3690
        }
3691
    }
3692

3693
    public T elementAtOrElse(final int index, T defaultValue) {
3694
        return elementAtOrElse((List<T>) value(), index, defaultValue);
1✔
3695
    }
3696

3697
    public static <T> T elementAtOrNull(final List<T> list, final int index) {
3698
        try {
3699
            return list.get(index);
1✔
3700
        } catch (IndexOutOfBoundsException ex) {
1✔
3701
            return null;
1✔
3702
        }
3703
    }
3704

3705
    public T elementAtOrNull(final int index) {
3706
        return elementAtOrNull((List<T>) value(), index);
1✔
3707
    }
3708

3709
    public static <T> int lastIndex(final Iterable<T> iterable) {
3710
        return size(iterable) - 1;
1✔
3711
    }
3712

3713
    public static <T> int lastIndex(final T[] array) {
3714
        return array.length - 1;
1✔
3715
    }
3716

3717
    public static int lastIndex(final int[] array) {
3718
        return array.length - 1;
1✔
3719
    }
3720

3721
    public static <T> T checkNotNull(T reference) {
3722
        if (reference == null) {
1✔
3723
            throw new NullPointerException();
1✔
3724
        }
3725
        return reference;
1✔
3726
    }
3727

3728
    public static <T> List<T> checkNotNullElements(List<T> references) {
3729
        if (references == null) {
1✔
3730
            throw new NullPointerException();
1✔
3731
        }
3732
        for (T reference : references) {
1✔
3733
            checkNotNull(reference);
1✔
3734
        }
1✔
3735
        return references;
1✔
3736
    }
3737

3738
    public static <T> T checkNotNull(T reference, Object errorMessage) {
3739
        if (reference == null) {
1✔
3740
            throw new NullPointerException(String.valueOf(errorMessage));
1✔
3741
        }
3742
        return reference;
1✔
3743
    }
3744

3745
    public static boolean nonNull(Object obj) {
3746
        return obj != null;
1✔
3747
    }
3748

3749
    public static <T> T defaultTo(T value, T defaultValue) {
3750
        if (value == null) {
1✔
3751
            return defaultValue;
1✔
3752
        }
3753
        return value;
1✔
3754
    }
3755

3756
    protected static <T> List<T> newArrayList(final Iterable<T> iterable) {
3757
        final List<T> result;
3758
        if (iterable instanceof Collection) {
1✔
3759
            result = new ArrayList<>((Collection<T>) iterable);
1✔
3760
        } else {
3761
            result = new ArrayList<>();
1✔
3762
            for (final T item : iterable) {
1✔
3763
                result.add(item);
1✔
3764
            }
1✔
3765
        }
3766
        return result;
1✔
3767
    }
3768

3769
    protected static <T> List<T> newArrayList(final T object) {
3770
        final List<T> result = new ArrayList<>();
1✔
3771
        result.add(object);
1✔
3772
        return result;
1✔
3773
    }
3774

3775
    protected static <T> List<T> newArrayList(final Iterable<T> iterable, final int size) {
3776
        final List<T> result = new ArrayList<>();
1✔
3777
        for (int index = 0; iterable.iterator().hasNext() && index < size; index += 1) {
1✔
3778
            result.add(iterable.iterator().next());
1✔
3779
        }
3780
        return result;
1✔
3781
    }
3782

3783
    protected static List<Integer> newIntegerList(int... array) {
3784
        final List<Integer> result = new ArrayList<>(array.length);
1✔
3785
        for (final int item : array) {
1✔
3786
            result.add(item);
1✔
3787
        }
3788
        return result;
1✔
3789
    }
3790

3791
    protected static <T> List<T> newArrayListWithExpectedSize(int size) {
3792
        return new ArrayList<>((int) (CAPACITY_SIZE_5 + size + (size / 10)));
1✔
3793
    }
3794

3795
    protected static <T> Set<T> newLinkedHashSet(Iterable<T> iterable) {
3796
        final Set<T> result = new LinkedHashSet<>();
1✔
3797
        for (final T item : iterable) {
1✔
3798
            result.add(item);
1✔
3799
        }
1✔
3800
        return result;
1✔
3801
    }
3802

3803
    protected static <T> Set<T> newLinkedHashSetWithExpectedSize(int size) {
3804
        return new LinkedHashSet<>((int) Math.max(size * CAPACITY_COEFF_2, CAPACITY_SIZE_16));
1✔
3805
    }
3806

3807
    @SuppressWarnings("unchecked")
3808
    public static <T> Predicate<T> and(
3809
            final Predicate<? super T> pred1,
3810
            final Predicate<? super T> pred2,
3811
            final Predicate<? super T>... rest) {
3812
        checkNotNull(pred1);
1✔
3813
        checkNotNull(pred2);
1✔
3814
        checkNotNullElements(Arrays.asList(rest));
1✔
3815
        return value -> {
1✔
3816
            boolean result = pred1.test(value) && pred2.test(value);
1✔
3817
            if (!result) {
1✔
3818
                return false;
1✔
3819
            }
3820
            for (Predicate<? super T> predicate : rest) {
1✔
3821
                if (!predicate.test(value)) {
1✔
3822
                    return false;
1✔
3823
                }
3824
            }
3825
            return true;
1✔
3826
        };
3827
    }
3828

3829
    @SuppressWarnings("unchecked")
3830
    public static <T> Predicate<T> or(
3831
            final Predicate<? super T> pred1,
3832
            final Predicate<? super T> pred2,
3833
            final Predicate<? super T>... rest) {
3834
        checkNotNull(pred1);
1✔
3835
        checkNotNull(pred2);
1✔
3836
        checkNotNullElements(Arrays.asList(rest));
1✔
3837
        return value -> {
1✔
3838
            boolean result = pred1.test(value) || pred2.test(value);
1✔
3839
            if (result) {
1✔
3840
                return true;
1✔
3841
            }
3842
            for (Predicate<? super T> predicate : rest) {
1✔
3843
                if (predicate.test(value)) {
1✔
3844
                    return true;
1✔
3845
                }
3846
            }
3847
            return false;
1✔
3848
        };
3849
    }
3850

3851
    public static void main(String... args) {
3852
        final String message =
1✔
3853
                "Underscore-java is a java port of Underscore.js.\n\n"
3854
                        + "In addition to porting Underscore's functionality,"
3855
                        + " Underscore-java includes matching unit tests.\n\n"
3856
                        + "For docs, license, tests, and downloads, see: https://javadev.github.io/underscore-java";
3857
        System.out.println(message);
1✔
3858
    }
1✔
3859

3860
    public interface Function3<F1, F2, F3, T> {
3861
        T apply(F1 arg1, F2 arg2, F3 arg3);
3862
    }
3863

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

3867
        public abstract T calc(final F n);
3868

3869
        public T apply(final F key) {
3870
            cache.putIfAbsent(key, calc(key));
1✔
3871
            return cache.get(key);
1✔
3872
        }
3873
    }
3874

3875
    public interface PredicateIndexed<T> {
3876
        boolean test(int index, T arg);
3877
    }
3878

3879
    public interface Template<T> extends Function<T, String> {
3880
        List<String> check(T arg);
3881
    }
3882
}
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