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

javadev / underscore-java / #3557

08 Feb 2023 11:20AM UTC coverage: 99.955% (-0.05%) from 100.0%
#3557

push

web-flow
Update maven.yml

4420 of 4422 relevant lines covered (99.95%)

1.0 hits per line

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

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

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

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

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

97
    public Underscore(final Iterable<T> iterable) {
1✔
98
        this.iterable = iterable;
1✔
99
        this.string = Optional.empty();
1✔
100
    }
1✔
101

102
    public Underscore(final String string) {
1✔
103
        this.iterable = null;
1✔
104
        this.string = Optional.of(string);
1✔
105
    }
1✔
106

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

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

120
    private static final class WherePredicate<E, T> implements Predicate<E> {
121
        private final List<Tuple<String, T>> properties;
122

123
        private WherePredicate(List<Tuple<String, T>> properties) {
1✔
124
            this.properties = properties;
1✔
125
        }
1✔
126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2439
    /*
2440
     * Documented, #defaults
2441
     */
2442
    public static <K, V> Map<K, V> defaults(final Map<K, V> object, final Map<K, V> defaults) {
2443
        final Map<K, V> result = newLinkedHashMap();
1✔
2444
        for (final Map.Entry<K, V> entry : defaults.entrySet()) {
1✔
2445
            result.put(entry.getKey(), entry.getValue());
1✔
2446
        }
1✔
2447
        for (final Map.Entry<K, V> entry : object.entrySet()) {
1✔
2448
            result.put(entry.getKey(), entry.getValue());
1✔
2449
        }
1✔
2450
        return result;
1✔
2451
    }
2452

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

2472
    @SuppressWarnings("unchecked")
2473
    public static <E> E[] clone(final E... iterable) {
2474
        return Arrays.copyOf(iterable, iterable.length);
1✔
2475
    }
2476

2477
    public static <T> void tap(final Iterable<T> iterable, final Consumer<? super T> func) {
2478
        each(iterable, func);
1✔
2479
    }
1✔
2480

2481
    public static <K, V> boolean isMatch(final Map<K, V> object, final Map<K, V> properties) {
2482
        for (final K key : keys(properties)) {
1✔
2483
            if (!object.containsKey(key) || !object.get(key).equals(properties.get(key))) {
1✔
2484
                return false;
1✔
2485
            }
2486
        }
1✔
2487
        return true;
1✔
2488
    }
2489

2490
    /*
2491
     * Documented, #isEqual
2492
     */
2493
    public static boolean isEqual(final Object object, final Object other) {
2494
        return Objects.equals(object, other);
1✔
2495
    }
2496

2497
    public static <K, V> boolean isEmpty(final Map<K, V> object) {
2498
        return object == null || object.isEmpty();
1✔
2499
    }
2500

2501
    /*
2502
     * Documented, #isEmpty
2503
     */
2504
    public static <T> boolean isEmpty(final Iterable<T> iterable) {
2505
        return iterable == null || !iterable.iterator().hasNext();
1✔
2506
    }
2507

2508
    public boolean isEmpty() {
2509
        return iterable == null || !iterable.iterator().hasNext();
1✔
2510
    }
2511

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

2516
    public static <T> boolean isNotEmpty(final Iterable<T> iterable) {
2517
        return iterable != null && iterable.iterator().hasNext();
1✔
2518
    }
2519

2520
    public boolean isNotEmpty() {
2521
        return iterable != null && iterable.iterator().hasNext();
1✔
2522
    }
2523

2524
    /*
2525
     * Documented, #isArray
2526
     */
2527
    public static boolean isArray(final Object object) {
2528
        return object != null && object.getClass().isArray();
1✔
2529
    }
2530

2531
    /*
2532
     * Documented, #isObject
2533
     */
2534
    public static boolean isObject(final Object object) {
2535
        return object instanceof Map;
1✔
2536
    }
2537

2538
    /*
2539
     * Documented, #isFunction
2540
     */
2541
    public static boolean isFunction(final Object object) {
2542
        return object instanceof Function;
1✔
2543
    }
2544

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

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

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

2566
    public static boolean isRegExp(final Object object) {
2567
        return object instanceof java.util.regex.Pattern;
1✔
2568
    }
2569

2570
    public static boolean isError(final Object object) {
2571
        return object instanceof Throwable;
1✔
2572
    }
2573

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

2581
    public static boolean isNull(final Object object) {
2582
        return object == null;
1✔
2583
    }
2584

2585
    /*
2586
     * Documented, #has
2587
     */
2588
    public static <K, V> boolean has(final Map<K, V> object, final K key) {
2589
        return object.containsKey(key);
1✔
2590
    }
2591

2592
    public static <E> E identity(final E value) {
2593
        return value;
1✔
2594
    }
2595

2596
    public static <E> Supplier<E> constant(final E value) {
2597
        return () -> value;
1✔
2598
    }
2599

2600
    public static <K, V> Function<Map<K, V>, V> property(final K key) {
2601
        return object -> object.get(key);
1✔
2602
    }
2603

2604
    public static <K, V> Function<K, V> propertyOf(final Map<K, V> object) {
2605
        return object::get;
1✔
2606
    }
2607

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

2619
    /*
2620
     * Documented, #times
2621
     */
2622
    public static void times(final int count, final Runnable runnable) {
2623
        for (int index = 0; index < count; index += 1) {
1✔
2624
            runnable.run();
1✔
2625
        }
2626
    }
1✔
2627

2628
    /*
2629
     * Documented, #random
2630
     */
2631
    public static int random(final int min, final int max) {
2632
        return min + new java.security.SecureRandom().nextInt(max - min + 1);
1✔
2633
    }
2634

2635
    public static int random(final int max) {
2636
        return new java.security.SecureRandom().nextInt(max + 1);
1✔
2637
    }
2638

2639
    public static long now() {
2640
        return new Date().getTime();
1✔
2641
    }
2642

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

2654
    public static String unescape(final String value) {
2655
        return value.replace("&#x60;", "`")
1✔
2656
                .replace("&#x27;", "'")
1✔
2657
                .replace("&lt;", "<")
1✔
2658
                .replace("&gt;", ">")
1✔
2659
                .replace("&quot;", "\"")
1✔
2660
                .replace("&amp;", "&");
1✔
2661
    }
2662

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

2681
    /*
2682
     * Documented, #uniqueId
2683
     */
2684
    public static String uniqueId(final String prefix) {
2685
        return (prefix == null ? "" : prefix) + UNIQUE_ID.incrementAndGet();
1✔
2686
    }
2687

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

2715
    public static <K, V> Template<Map<K, V>> template(final String template) {
2716
        return new TemplateImpl<>(template);
1✔
2717
    }
2718

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

2741
    public static <T> Iterable<T> iterate(final T seed, final UnaryOperator<T> unaryOperator) {
2742
        return new MyIterable<>(seed, unaryOperator);
1✔
2743
    }
2744

2745
    /*
2746
     * Documented, #chain
2747
     */
2748
    public static <T> Chain<T> chain(final List<T> list) {
2749
        return new Underscore.Chain<>(list);
1✔
2750
    }
2751

2752
    public static Chain<Map<String, Object>> chain(final Map<String, Object> map) {
2753
        return new Underscore.Chain<>(map);
1✔
2754
    }
2755

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

2760
    public static <T> Chain<T> chain(final Iterable<T> iterable, int size) {
2761
        return new Underscore.Chain<>(newArrayList(iterable, size));
1✔
2762
    }
2763

2764
    @SuppressWarnings("unchecked")
2765
    public static <T> Chain<T> chain(final T... array) {
2766
        return new Underscore.Chain<>(Arrays.asList(array));
1✔
2767
    }
2768

2769
    public static Chain<Integer> chain(final int[] array) {
2770
        return new Underscore.Chain<>(newIntegerList(array));
1✔
2771
    }
2772

2773
    public Chain<T> chain() {
2774
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2775
    }
2776

2777
    public static <T> Chain<T> of(final List<T> list) {
2778
        return new Underscore.Chain<>(list);
1✔
2779
    }
2780

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

2785
    public static <T> Chain<T> of(final Iterable<T> iterable, int size) {
2786
        return new Underscore.Chain<>(newArrayList(iterable, size));
1✔
2787
    }
2788

2789
    @SuppressWarnings("unchecked")
2790
    public static <T> Chain<T> of(final T... array) {
2791
        return new Underscore.Chain<>(Arrays.asList(array));
1✔
2792
    }
2793

2794
    public static Chain<Integer> of(final int[] array) {
2795
        return new Underscore.Chain<>(newIntegerList(array));
1✔
2796
    }
2797

2798
    public Chain<T> of() {
2799
        return new Underscore.Chain<>(newArrayList(iterable));
1✔
2800
    }
2801

2802
    public static class Chain<T> {
2803
        private final T item;
2804
        private final List<T> list;
2805
        private final Map<String, Object> map;
2806

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

2813
        public Chain(final List<T> list) {
1✔
2814
            this.item = null;
1✔
2815
            this.list = list;
1✔
2816
            this.map = null;
1✔
2817
        }
1✔
2818

2819
        public Chain(final Map<String, Object> map) {
1✔
2820
            this.item = null;
1✔
2821
            this.list = null;
1✔
2822
            this.map = map;
1✔
2823
        }
1✔
2824

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

2829
        public Chain<T> first(int n) {
2830
            return new Chain<>(Underscore.first(list, n));
1✔
2831
        }
2832

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

2837
        public Chain<T> first(final Predicate<T> pred, int n) {
2838
            return new Chain<>(Underscore.first(list, pred, n));
1✔
2839
        }
2840

2841
        public Chain<T> firstOrNull() {
2842
            return new Chain<>(Underscore.firstOrNull(list));
1✔
2843
        }
2844

2845
        public Chain<T> firstOrNull(final Predicate<T> pred) {
2846
            return new Chain<>(Underscore.firstOrNull(list, pred));
1✔
2847
        }
2848

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

2853
        public Chain<T> initial(int n) {
2854
            return new Chain<>(Underscore.initial(list, n));
1✔
2855
        }
2856

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

2861
        public Chain<T> last(int n) {
2862
            return new Chain<>(Underscore.last(list, n));
1✔
2863
        }
2864

2865
        public Chain<T> lastOrNull() {
2866
            return new Chain<>(Underscore.lastOrNull(list));
1✔
2867
        }
2868

2869
        public Chain<T> lastOrNull(final Predicate<T> pred) {
2870
            return new Chain<>(Underscore.lastOrNull(list, pred));
1✔
2871
        }
2872

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

2877
        public Chain<T> rest(int n) {
2878
            return new Chain<>(Underscore.rest(list, n));
1✔
2879
        }
2880

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

2885
        public Chain<T> compact(final T falsyValue) {
2886
            return new Chain<>(Underscore.compact(list, falsyValue));
1✔
2887
        }
2888

2889
        @SuppressWarnings("unchecked")
2890
        public Chain flatten() {
2891
            return new Chain<>(Underscore.flatten(list));
1✔
2892
        }
2893

2894
        public <F> Chain<F> map(final Function<? super T, F> func) {
2895
            return new Chain<>(Underscore.map(list, func));
1✔
2896
        }
2897

2898
        public <F> Chain<F> mapMulti(final BiConsumer<? super T, ? super Consumer<F>> mapper) {
2899
            return new Chain<>(Underscore.mapMulti(list, mapper));
1✔
2900
        }
2901

2902
        public <F> Chain<F> mapIndexed(final BiFunction<Integer, ? super T, F> func) {
2903
            return new Chain<>(Underscore.mapIndexed(list, func));
1✔
2904
        }
2905

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

2910
        public Chain<T> replaceIndexed(final PredicateIndexed<T> pred, final T value) {
2911
            return new Chain<>(Underscore.replaceIndexed(list, pred, value));
1✔
2912
        }
2913

2914
        public Chain<T> filter(final Predicate<T> pred) {
2915
            return new Chain<>(Underscore.filter(list, pred));
1✔
2916
        }
2917

2918
        public Chain<T> filterIndexed(final PredicateIndexed<T> pred) {
2919
            return new Chain<>(Underscore.filterIndexed(list, pred));
1✔
2920
        }
2921

2922
        public Chain<T> reject(final Predicate<T> pred) {
2923
            return new Chain<>(Underscore.reject(list, pred));
1✔
2924
        }
2925

2926
        public Chain<T> rejectIndexed(final PredicateIndexed<T> pred) {
2927
            return new Chain<>(Underscore.rejectIndexed(list, pred));
1✔
2928
        }
2929

2930
        public Chain<T> filterFalse(final Predicate<T> pred) {
2931
            return new Chain<>(Underscore.reject(list, pred));
1✔
2932
        }
2933

2934
        public <F> Chain<F> reduce(final BiFunction<F, T, F> func, final F zeroElem) {
2935
            return new Chain<>(Underscore.reduce(list, func, zeroElem));
1✔
2936
        }
2937

2938
        public Chain<Optional<T>> reduce(final BinaryOperator<T> func) {
2939
            return new Chain<>(Underscore.reduce(list, func));
1✔
2940
        }
2941

2942
        public <F> Chain<F> reduceRight(final BiFunction<F, T, F> func, final F zeroElem) {
2943
            return new Chain<>(Underscore.reduceRight(list, func, zeroElem));
1✔
2944
        }
2945

2946
        public Chain<Optional<T>> reduceRight(final BinaryOperator<T> func) {
2947
            return new Chain<>(Underscore.reduceRight(list, func));
1✔
2948
        }
2949

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

2954
        public Chain<Optional<T>> findLast(final Predicate<T> pred) {
2955
            return new Chain<>(Underscore.findLast(list, pred));
1✔
2956
        }
2957

2958
        @SuppressWarnings("unchecked")
2959
        public Chain<Comparable> max() {
2960
            return new Chain<>(Underscore.max((Collection) list));
1✔
2961
        }
2962

2963
        public <F extends Comparable<? super F>> Chain<T> max(final Function<T, F> func) {
2964
            return new Chain<>(Underscore.max(list, func));
1✔
2965
        }
2966

2967
        @SuppressWarnings("unchecked")
2968
        public Chain<Comparable> min() {
2969
            return new Chain<>(Underscore.min((Collection) list));
1✔
2970
        }
2971

2972
        public <F extends Comparable<? super F>> Chain<T> min(final Function<T, F> func) {
2973
            return new Chain<>(Underscore.min(list, func));
1✔
2974
        }
2975

2976
        @SuppressWarnings("unchecked")
2977
        public Chain<Comparable> sort() {
2978
            return new Chain<>(Underscore.sort((List<Comparable>) list));
1✔
2979
        }
2980

2981
        @SuppressWarnings("unchecked")
2982
        public <F extends Comparable<? super F>> Chain<F> sortWith(final Comparator<F> comparator) {
2983
            return new Chain<>(Underscore.sortWith((List<F>) list, comparator));
1✔
2984
        }
2985

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

2990
        @SuppressWarnings("unchecked")
2991
        public <K> Chain<Map<K, Comparable>> sortBy(final K key) {
2992
            return new Chain<>(Underscore.sortBy((List<Map<K, Comparable>>) list, key));
1✔
2993
        }
2994

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

2999
        public <F> Chain<Map<F, Optional<T>>> groupBy(
3000
                final Function<T, F> func, final BinaryOperator<T> binaryOperator) {
3001
            return new Chain<>(Underscore.groupBy(list, func, binaryOperator));
1✔
3002
        }
3003

3004
        public Chain<Map<Object, List<T>>> indexBy(final String property) {
3005
            return new Chain<>(Underscore.indexBy(list, property));
1✔
3006
        }
3007

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

3012
        public Chain<Map<T, Integer>> countBy() {
3013
            return new Chain<>(Underscore.countBy(list));
1✔
3014
        }
3015

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

3020
        public Chain<T> sample() {
3021
            return new Chain<>(Underscore.sample(list));
1✔
3022
        }
3023

3024
        public Chain<T> sample(final int howMany) {
3025
            return new Chain<>(Underscore.newArrayList(Underscore.sample(list, howMany)));
1✔
3026
        }
3027

3028
        public Chain<T> tap(final Consumer<T> func) {
3029
            Underscore.each(list, func);
1✔
3030
            return new Chain<>(list);
1✔
3031
        }
3032

3033
        public Chain<T> forEach(final Consumer<T> func) {
3034
            return tap(func);
1✔
3035
        }
3036

3037
        public Chain<T> forEachRight(final Consumer<T> func) {
3038
            Underscore.eachRight(list, func);
1✔
3039
            return new Chain<>(list);
1✔
3040
        }
3041

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

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

3050
        public Chain<Integer> count(final Predicate<T> pred) {
3051
            return new Chain<>(Underscore.count(list, pred));
1✔
3052
        }
3053

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

3058
        public Chain<Boolean> containsWith(final T elem) {
3059
            return new Chain<>(Underscore.containsWith(list, elem));
1✔
3060
        }
3061

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

3066
        public Chain<T> invoke(final String methodName) {
3067
            return new Chain<>(Underscore.invoke(list, methodName));
1✔
3068
        }
3069

3070
        public Chain<Object> pluck(final String propertyName) {
3071
            return new Chain<>(Underscore.pluck(list, propertyName));
1✔
3072
        }
3073

3074
        public <E> Chain<T> where(final List<Tuple<String, E>> properties) {
3075
            return new Chain<>(Underscore.where(list, properties));
1✔
3076
        }
3077

3078
        public <E> Chain<Optional<T>> findWhere(final List<Tuple<String, E>> properties) {
3079
            return new Chain<>(Underscore.findWhere(list, properties));
1✔
3080
        }
3081

3082
        public Chain<T> uniq() {
3083
            return new Chain<>(Underscore.uniq(list));
1✔
3084
        }
3085

3086
        public <F> Chain<T> uniq(final Function<T, F> func) {
3087
            return new Chain<>(Underscore.newArrayList(Underscore.uniq(list, func)));
1✔
3088
        }
3089

3090
        public Chain<T> distinct() {
3091
            return new Chain<>(Underscore.uniq(list));
1✔
3092
        }
3093

3094
        @SuppressWarnings("unchecked")
3095
        public <F> Chain<F> distinctBy(final Function<T, F> func) {
3096
            return new Chain<>(Underscore.newArrayList((Iterable<F>) Underscore.uniq(list, func)));
1✔
3097
        }
3098

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

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

3109
        @SuppressWarnings("unchecked")
3110
        public Chain<T> difference(final List<T>... lists) {
3111
            return new Chain<>(Underscore.difference(list, lists));
1✔
3112
        }
3113

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

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

3122
        public Chain<Integer> range(final int start, final int stop, final int step) {
3123
            return new Chain<>(Underscore.range(start, stop, step));
1✔
3124
        }
3125

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

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

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

3138
        public Chain<List<T>> chunkFill(final int size, final int step, final T fillValue) {
3139
            return new Chain<>(Underscore.chunkFill(value(), size, step, fillValue));
1✔
3140
        }
3141

3142
        public Chain<T> cycle(final int times) {
3143
            return new Chain<>(Underscore.cycle(value(), times));
1✔
3144
        }
3145

3146
        public Chain<T> interpose(final T element) {
3147
            return new Chain<>(Underscore.interpose(value(), element));
1✔
3148
        }
3149

3150
        public Chain<T> interposeByList(final Iterable<T> interIter) {
3151
            return new Chain<>(Underscore.interposeByList(value(), interIter));
1✔
3152
        }
3153

3154
        @SuppressWarnings("unchecked")
3155
        public Chain<T> concat(final List<T>... lists) {
3156
            return new Chain<>(Underscore.concat(list, lists));
1✔
3157
        }
3158

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

3163
        public Chain<T> slice(final int start, final int end) {
3164
            return new Chain<>(Underscore.slice(list, start, end));
1✔
3165
        }
3166

3167
        public Chain<List<T>> splitAt(final int position) {
3168
            return new Chain<>(Underscore.splitAt(list, position));
1✔
3169
        }
3170

3171
        public Chain<T> takeSkipping(final int stepSize) {
3172
            return new Chain<>(Underscore.takeSkipping(list, stepSize));
1✔
3173
        }
3174

3175
        public Chain<T> reverse() {
3176
            return new Chain<>(Underscore.reverse(list));
1✔
3177
        }
3178

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

3183
        public Chain<String> join(final String separator) {
3184
            return new Chain<>(Underscore.join(list, separator));
1✔
3185
        }
3186

3187
        @SuppressWarnings("unchecked")
3188
        public Chain<T> push(final T... values) {
3189
            return new Chain<>(Underscore.push(value(), values));
1✔
3190
        }
3191

3192
        public Chain<Tuple<T, List<T>>> pop() {
3193
            return new Chain<>(Underscore.pop(value()));
1✔
3194
        }
3195

3196
        public Chain<Tuple<T, List<T>>> shift() {
3197
            return new Chain<>(Underscore.shift(value()));
1✔
3198
        }
3199

3200
        @SuppressWarnings("unchecked")
3201
        public Chain<T> unshift(final T... values) {
3202
            return new Chain<>(Underscore.unshift(value(), values));
1✔
3203
        }
3204

3205
        public Chain<T> skip(final int numberToSkip) {
3206
            return new Chain<>(list.subList(numberToSkip, list.size()));
1✔
3207
        }
3208

3209
        public Chain<T> limit(final int size) {
3210
            return new Chain<>(Underscore.first(list, size));
1✔
3211
        }
3212

3213
        @SuppressWarnings("unchecked")
3214
        public <K, V> Chain<Map<K, V>> toMap() {
3215
            return new Chain<>(Underscore.toMap((Iterable<Map.Entry<K, V>>) list));
1✔
3216
        }
3217

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

3222
        public boolean isNotEmpty() {
3223
            return Underscore.isNotEmpty(list);
1✔
3224
        }
3225

3226
        public int size() {
3227
            return Underscore.size(list);
1✔
3228
        }
3229

3230
        public T item() {
3231
            return item;
1✔
3232
        }
3233

3234
        /*
3235
         * Documented, #value
3236
         */
3237
        public List<T> value() {
3238
            return list;
1✔
3239
        }
3240

3241
        public Map<String, Object> map() {
3242
            return map;
1✔
3243
        }
3244

3245
        public List<T> toList() {
3246
            return list;
1✔
3247
        }
3248

3249
        public String toString() {
3250
            return String.valueOf(list);
1✔
3251
        }
3252
    }
3253

3254
    /*
3255
     * Documented, #mixin
3256
     */
3257
    public static void mixin(final String funcName, final UnaryOperator<String> func) {
3258
        FUNCTIONS.put(funcName, func);
1✔
3259
    }
1✔
3260

3261
    public Optional<String> call(final String funcName) {
3262
        if (string.isPresent() && FUNCTIONS.containsKey(funcName)) {
1✔
3263
            return Optional.of(FUNCTIONS.get(funcName).apply(string.get()));
1✔
3264
        }
3265
        return Optional.empty();
1✔
3266
    }
3267

3268
    public static <T extends Comparable<T>> List<T> sort(final Iterable<T> iterable) {
3269
        final List<T> localList = newArrayList(iterable);
1✔
3270
        Collections.sort(localList);
1✔
3271
        return localList;
1✔
3272
    }
3273

3274
    @SuppressWarnings("unchecked")
3275
    public static <T extends Comparable<T>> T[] sort(final T... array) {
3276
        final T[] localArray = array.clone();
1✔
3277
        Arrays.sort(localArray);
1✔
3278
        return localArray;
1✔
3279
    }
3280

3281
    @SuppressWarnings("unchecked")
3282
    public List<Comparable> sort() {
3283
        return sort((Iterable<Comparable>) iterable);
1✔
3284
    }
3285

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

3302
    public static <T> String join(final Iterable<T> iterable) {
3303
        return join(iterable, " ");
1✔
3304
    }
3305

3306
    public static <T> String join(final T[] array, final String separator) {
3307
        return join(Arrays.asList(array), separator);
1✔
3308
    }
3309

3310
    public static <T> String join(final T[] array) {
3311
        return join(array, " ");
1✔
3312
    }
3313

3314
    public String join(final String separator) {
3315
        return join(iterable, separator);
1✔
3316
    }
3317

3318
    public String join() {
3319
        return join(iterable);
1✔
3320
    }
3321

3322
    @SuppressWarnings("unchecked")
3323
    public static <T> List<T> push(final List<T> list, final T... values) {
3324
        final List<T> result = newArrayList(list);
1✔
3325
        Collections.addAll(result, values);
1✔
3326
        return result;
1✔
3327
    }
3328

3329
    @SuppressWarnings("unchecked")
3330
    public List<T> push(final T... values) {
3331
        return push((List<T>) getIterable(), values);
1✔
3332
    }
3333

3334
    public static <T> Tuple<T, List<T>> pop(final List<T> list) {
3335
        return Tuple.create(last(list), initial(list));
1✔
3336
    }
3337

3338
    public Tuple<T, List<T>> pop() {
3339
        return pop((List<T>) getIterable());
1✔
3340
    }
3341

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

3353
    @SuppressWarnings("unchecked")
3354
    public List<T> unshift(final T... values) {
3355
        return unshift((List<T>) getIterable(), values);
1✔
3356
    }
3357

3358
    public static <T> Tuple<T, List<T>> shift(final List<T> list) {
3359
        return Tuple.create(first(list), rest(list));
1✔
3360
    }
3361

3362
    public Tuple<T, List<T>> shift() {
3363
        return shift((List<T>) getIterable());
1✔
3364
    }
3365

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

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

3393
    @SuppressWarnings("unchecked")
3394
    public List<T> concatWith(final Iterable<T>... other) {
3395
        return concat(iterable, other);
1✔
3396
    }
3397

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

3411
    public static <T> T[] slice(final T[] array, final int start) {
3412
        final T[] result;
3413
        if (start >= 0) {
1✔
3414
            result = Arrays.copyOfRange(array, start, array.length);
1✔
3415
        } else {
3416
            result = Arrays.copyOfRange(array, array.length + start, array.length);
1✔
3417
        }
3418
        return result;
1✔
3419
    }
3420

3421
    public List<T> slice(final int start) {
3422
        return slice(iterable, start);
1✔
3423
    }
3424

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

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

3463
    public List<T> slice(final int start, final int end) {
3464
        return slice(iterable, start, end);
1✔
3465
    }
3466

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

3481
    public static <T> List<List<T>> splitAt(final T[] array, final int position) {
3482
        return splitAt(Arrays.asList(array), position);
1✔
3483
    }
3484

3485
    public List<List<T>> splitAt(final int position) {
3486
        return splitAt(iterable, position);
1✔
3487
    }
3488

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

3508
    public static <T> List<T> takeSkipping(final T[] array, final int stepSize) {
3509
        return takeSkipping(Arrays.asList(array), stepSize);
1✔
3510
    }
3511

3512
    public List<T> takeSkipping(final int stepSize) {
3513
        return takeSkipping(iterable, stepSize);
1✔
3514
    }
3515

3516
    /*
3517
     * Documented, #reverse
3518
     */
3519
    public static <T> List<T> reverse(final Iterable<T> iterable) {
3520
        final List<T> result = newArrayList(iterable);
1✔
3521
        Collections.reverse(result);
1✔
3522
        return result;
1✔
3523
    }
3524

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

3537
    public static List<Integer> reverse(final int[] array) {
3538
        final List<Integer> result = newIntegerList(array);
1✔
3539
        Collections.reverse(result);
1✔
3540
        return result;
1✔
3541
    }
3542

3543
    public List<T> reverse() {
3544
        return reverse(iterable);
1✔
3545
    }
3546

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

3551
    public Iterable<T> value() {
3552
        return iterable;
1✔
3553
    }
3554

3555
    public Optional<String> getString() {
3556
        return string;
1✔
3557
    }
3558

3559
    public static <T> java.util.concurrent.ScheduledFuture<T> setTimeout(
3560
            final Supplier<T> function, final int delayMilliseconds) {
3561
        return delay(function, delayMilliseconds);
1✔
3562
    }
3563

3564
    public static void clearTimeout(java.util.concurrent.ScheduledFuture<?> scheduledFuture) {
3565
        if (scheduledFuture != null) {
1✔
3566
            scheduledFuture.cancel(true);
1✔
3567
        }
3568
    }
1✔
3569

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

3581
    public static void clearInterval(java.util.concurrent.ScheduledFuture scheduledFuture) {
3582
        clearTimeout(scheduledFuture);
1✔
3583
    }
1✔
3584

3585
    public static <T> List<T> copyOf(final Iterable<T> iterable) {
3586
        return newArrayList(iterable);
1✔
3587
    }
3588

3589
    public List<T> copyOf() {
3590
        return newArrayList(value());
1✔
3591
    }
3592

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

3598
    public List<T> copyOfRange(final int start, final int end) {
3599
        return slice(value(), start, end);
1✔
3600
    }
3601

3602
    public static <T> T elementAt(final List<T> list, final int index) {
3603
        return list.get(index);
1✔
3604
    }
3605

3606
    public T elementAt(final int index) {
3607
        return elementAt((List<T>) value(), index);
1✔
3608
    }
3609

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

3614
    public T get(final int index) {
3615
        return elementAt((List<T>) value(), index);
1✔
3616
    }
3617

3618
    public static <T> Tuple<T, List<T>> set(final List<T> list, final int index, final T value) {
3619
        final List<T> newList = newArrayList(list);
1✔
3620
        return Tuple.create(newList.set(index, value), newList);
1✔
3621
    }
3622

3623
    public Tuple<T, List<T>> set(final int index, final T value) {
3624
        return set((List<T>) value(), index, value);
1✔
3625
    }
3626

3627
    public static <T> T elementAtOrElse(final List<T> list, final int index, T defaultValue) {
3628
        try {
3629
            return list.get(index);
1✔
3630
        } catch (IndexOutOfBoundsException ex) {
1✔
3631
            return defaultValue;
1✔
3632
        }
3633
    }
3634

3635
    public T elementAtOrElse(final int index, T defaultValue) {
3636
        return elementAtOrElse((List<T>) value(), index, defaultValue);
1✔
3637
    }
3638

3639
    public static <T> T elementAtOrNull(final List<T> list, final int index) {
3640
        try {
3641
            return list.get(index);
1✔
3642
        } catch (IndexOutOfBoundsException ex) {
1✔
3643
            return null;
1✔
3644
        }
3645
    }
3646

3647
    public T elementAtOrNull(final int index) {
3648
        return elementAtOrNull((List<T>) value(), index);
1✔
3649
    }
3650

3651
    public static <T> int lastIndex(final Iterable<T> iterable) {
3652
        return size(iterable) - 1;
1✔
3653
    }
3654

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

3659
    public static int lastIndex(final int[] array) {
3660
        return array.length - 1;
1✔
3661
    }
3662

3663
    public static <T> T checkNotNull(T reference) {
3664
        if (reference == null) {
1✔
3665
            throw new NullPointerException();
1✔
3666
        }
3667
        return reference;
1✔
3668
    }
3669

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

3680
    public static <T> T checkNotNull(T reference, Object errorMessage) {
3681
        if (reference == null) {
1✔
3682
            throw new NullPointerException(String.valueOf(errorMessage));
1✔
3683
        }
3684
        return reference;
1✔
3685
    }
3686

3687
    public static boolean nonNull(Object obj) {
3688
        return obj != null;
1✔
3689
    }
3690

3691
    public static <T> T defaultTo(T value, T defaultValue) {
3692
        if (value == null) {
1✔
3693
            return defaultValue;
1✔
3694
        }
3695
        return value;
1✔
3696
    }
3697

3698
    protected static <T> List<T> newArrayList() {
3699
        return new ArrayList<>();
1✔
3700
    }
3701

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

3715
    protected static <T> List<T> newArrayList(final T object) {
3716
        final List<T> result = new ArrayList<>();
1✔
3717
        result.add(object);
1✔
3718
        return result;
1✔
3719
    }
3720

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

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

3737
    protected static <T> List<T> newArrayListWithExpectedSize(int size) {
3738
        return new ArrayList<>((int) (CAPACITY_SIZE_5 + size + (size / 10)));
1✔
3739
    }
3740

3741
    protected static <T> Set<T> newLinkedHashSet() {
3742
        return new LinkedHashSet<>();
1✔
3743
    }
3744

3745
    protected static <T> Set<T> newLinkedHashSet(Iterable<T> iterable) {
3746
        final Set<T> result = new LinkedHashSet<>();
1✔
3747
        for (final T item : iterable) {
1✔
3748
            result.add(item);
1✔
3749
        }
1✔
3750
        return result;
1✔
3751
    }
3752

3753
    protected static <T> Set<T> newLinkedHashSetWithExpectedSize(int size) {
3754
        return new LinkedHashSet<>((int) Math.max(size * CAPACITY_COEFF_2, CAPACITY_SIZE_16));
1✔
3755
    }
3756

3757
    protected static <K, E> Map<K, E> newLinkedHashMap() {
3758
        return new LinkedHashMap<>();
1✔
3759
    }
3760

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

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

3805
    public static int minimumDays(int rows, int columns, List<List<Integer>> grid) {
3806
        Queue<int[]> queue = new LinkedList<>();
1✔
3807
        int cnt = 0;
1✔
3808
        for (int i = 0; i < rows; i++) {
1✔
3809
            for (int j = 0; j < columns; j++) {
1✔
3810
                if (grid.get(i).get(j) == 1) {
1✔
3811
                    queue.offer(new int[] {i, j});
1✔
3812
                    cnt++;
1✔
3813
                }
3814
            }
3815
        }
3816
        return getInteger(rows, columns, grid, queue, cnt);
1✔
3817
    }
3818

3819
    private static int getInteger(
3820
            int rows, int columns, List<List<Integer>> grid, Queue<int[]> queue, int cnt) {
3821
        int target = rows * columns;
1✔
3822
        int res = 0;
1✔
3823
        int localCnt = cnt;
1✔
3824
        int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
1✔
3825
        while (!queue.isEmpty()) {
1✔
3826
            int size = queue.size();
1✔
3827
            if (localCnt == target) {
1✔
3828
                return res;
1✔
3829
            }
3830
            for (int i = 0; i < size; i++) {
1✔
3831
                int[] cur = queue.poll();
1✔
3832
                for (int[] dir : dirs) {
1✔
3833
                    int ni = cur[0] + dir[0];
1✔
3834
                    int nj = cur[1] + dir[1];
1✔
3835
                    if (ni >= 0
1✔
3836
                            && ni < rows
3837
                            && nj >= 0
3838
                            && nj < columns
3839
                            && grid.get(ni).get(nj) == 0) {
1✔
3840
                        localCnt++;
1✔
3841
                        queue.offer(new int[] {ni, nj});
1✔
3842
                        grid.get(ni).set(nj, 1);
1✔
3843
                    }
3844
                }
3845
            }
3846
            res++;
1✔
3847
        }
1✔
3848
        return -1;
1✔
3849
    }
3850

3851
    public static List<String> topNCompetitors(
3852
            int numCompetitors,
3853
            int topNCompetitors,
3854
            List<String> competitors,
3855
            int numReviews,
3856
            List<String> reviews) {
3857
        if (Underscore.isNull(reviews)
1✔
3858
                || reviews.isEmpty()
1✔
3859
                || Underscore.isNull(competitors)
1✔
3860
                || competitors.isEmpty()
1✔
3861
                || numReviews < 1
3862
                || numCompetitors < 1) {
3863
            return new ArrayList<>();
1✔
3864
        }
3865

3866
        List<String> topNCompetitorsList = new ArrayList<>(topNCompetitors);
1✔
3867

3868
        Set<String> competitorsSet = new HashSet<>(competitors);
1✔
3869
        Map<String, Integer> topCompetitorsMap = new HashMap<>();
1✔
3870
        List<Map.Entry<String, Integer>> list =
1✔
3871
                getEntries(reviews, competitorsSet, topCompetitorsMap);
1✔
3872

3873
        for (Map.Entry<String, Integer> item : list) {
1✔
3874
            if (topNCompetitorsList.size() < topNCompetitors) {
1✔
3875
                topNCompetitorsList.add(item.getKey());
1✔
3876
            } else {
3877
                break;
3878
            }
3879
        }
1✔
3880

3881
        return topNCompetitorsList;
1✔
3882
    }
3883

3884
    private static List<Map.Entry<String, Integer>> getEntries(
3885
            List<String> reviews,
3886
            Set<String> competitorsSet,
3887
            Map<String, Integer> topCompetitorsMap) {
3888
        // clean the reviews first: lowercase, remove special characters and split by spaces.
3889
        for (String review : reviews) {
1✔
3890
            String[] reviewArray = review.toLowerCase().replaceAll("[^a-zA-Z0-9 ]", "").split(" ");
1✔
3891
            Set<String> tempCompetitorSet = new HashSet<>();
1✔
3892

3893
            for (String text : reviewArray) {
1✔
3894
                if (competitorsSet.contains(text) && !tempCompetitorSet.contains(text)) {
1✔
3895
                    tempCompetitorSet.add(text);
1✔
3896
                    if (topCompetitorsMap.containsKey(text)) {
1✔
3897
                        topCompetitorsMap.put(text, topCompetitorsMap.get(text) + 1);
1✔
3898
                    } else {
3899
                        topCompetitorsMap.put(text, 1);
1✔
3900
                    }
3901
                }
3902
            }
3903
        }
1✔
3904

3905
        return getEntries(topCompetitorsMap);
1✔
3906
    }
3907

3908
    private static List<Map.Entry<String, Integer>> getEntries(
3909
            Map<String, Integer> topCompetitorsMap) {
3910
        List<Map.Entry<String, Integer>> list = new ArrayList<>(topCompetitorsMap.entrySet());
1✔
3911
        list.sort(new ValueThenKeyComparator<>());
1✔
3912
        return list;
1✔
3913
    }
3914

3915
    public static class ValueThenKeyComparator<
1✔
3916
                    K extends Comparable<? super K>, V extends Comparable<? super V>>
3917
            implements Comparator<Map.Entry<K, V>>, java.io.Serializable {
3918

3919
        public int compare(Map.Entry<K, V> a, Map.Entry<K, V> b) {
3920
            int cmp1 = b.getValue().compareTo(a.getValue());
1✔
3921
            if (cmp1 == 0) {
1✔
3922
                return a.getKey().compareTo(b.getKey());
1✔
3923
            }
3924
            return cmp1;
1✔
3925
        }
3926
    }
3927

3928
    public static void main(String... args) {
3929
        final String message =
1✔
3930
                "Underscore-java is a java port of Underscore.js.\n\n"
3931
                        + "In addition to porting Underscore's functionality,"
3932
                        + " Underscore-java includes matching unit tests.\n\n"
3933
                        + "For docs, license, tests, and downloads, see: https://javadev.github.io/underscore-java";
3934
        System.out.println(message);
1✔
3935
    }
1✔
3936
}
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