001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
018    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
019    
020    import java.io.File;
021    import java.io.FileReader;
022    import java.io.IOException;
023    
024    import java.lang.reflect.Array;
025    
026    import java.util.ArrayList;
027    import java.util.Arrays;
028    import java.util.Collection;
029    import java.util.Collections;
030    import java.util.Comparator;
031    import java.util.Enumeration;
032    import java.util.HashSet;
033    import java.util.Iterator;
034    import java.util.LinkedHashSet;
035    import java.util.LinkedList;
036    import java.util.List;
037    import java.util.ListIterator;
038    import java.util.Map;
039    import java.util.Set;
040    
041    /**
042     * @author Brian Wing Shun Chan
043     * @author Shuyang Zhou
044     */
045    public class ListUtil {
046    
047            public static <E> List<E> copy(List<? extends E> master) {
048                    if (master == null) {
049                            return null;
050                    }
051    
052                    return new ArrayList<>(master);
053            }
054    
055            public static <E> void copy(
056                    List<? extends E> master, List<? super E> copy) {
057    
058                    if ((master == null) || (copy == null)) {
059                            return;
060                    }
061    
062                    copy.clear();
063    
064                    copy.addAll(master);
065            }
066    
067            public static <E> int count(
068                    List<? extends E> list, PredicateFilter<E> predicateFilter) {
069    
070                    if (isEmpty(list)) {
071                            return 0;
072                    }
073    
074                    int count = 0;
075    
076                    for (E element : list) {
077                            if (predicateFilter.filter(element)) {
078                                    count++;
079                            }
080                    }
081    
082                    return count;
083            }
084    
085            public static <E> void distinct(
086                    List<? extends E> list, Comparator<E> comparator) {
087    
088                    if (isEmpty(list)) {
089                            return;
090                    }
091    
092                    Set<E> set = new HashSet<>();
093    
094                    Iterator<? extends E> itr = list.iterator();
095    
096                    while (itr.hasNext()) {
097                            E obj = itr.next();
098    
099                            if (!set.add(obj)) {
100                                    itr.remove();
101                            }
102                    }
103    
104                    if (comparator != null) {
105                            Collections.sort(list, comparator);
106                    }
107            }
108    
109            public static void distinct(List<?> list) {
110                    distinct(list, null);
111            }
112    
113            public static <E> boolean exists(
114                    List<? extends E> list, PredicateFilter<E> predicateFilter) {
115    
116                    if (isEmpty(list)) {
117                            return false;
118                    }
119    
120                    for (E element : list) {
121                            if (predicateFilter.filter(element)) {
122                                    return true;
123                            }
124                    }
125    
126                    return false;
127            }
128    
129            public static <T> List<T> filter(
130                    List<? extends T> inputList, List<T> outputList,
131                    PredicateFilter<T> predicateFilter) {
132    
133                    for (T item : inputList) {
134                            if (predicateFilter.filter(item)) {
135                                    outputList.add(item);
136                            }
137                    }
138    
139                    return outputList;
140            }
141    
142            public static <T> List<T> filter(
143                    List<? extends T> inputList, PredicateFilter<T> predicateFilter) {
144    
145                    return filter(
146                            inputList, new ArrayList<T>(inputList.size()), predicateFilter);
147            }
148    
149            public static <E> List<E> fromArray(E[] array) {
150                    if (ArrayUtil.isEmpty(array)) {
151                            return new ArrayList<>();
152                    }
153    
154                    return new ArrayList<>(Arrays.asList(array));
155            }
156    
157            @SuppressWarnings("rawtypes")
158            public static <E> List<E> fromCollection(Collection<? extends E> c) {
159                    if ((c != null) && (c instanceof List)) {
160                            return (List)c;
161                    }
162    
163                    if ((c == null) || c.isEmpty()) {
164                            return new ArrayList<>();
165                    }
166    
167                    List<E> list = new ArrayList<>(c.size());
168    
169                    list.addAll(c);
170    
171                    return list;
172            }
173    
174            public static <E> List<E> fromEnumeration(Enumeration<? extends E> enu) {
175                    List<E> list = new ArrayList<>();
176    
177                    while (enu.hasMoreElements()) {
178                            E obj = enu.nextElement();
179    
180                            list.add(obj);
181                    }
182    
183                    return list;
184            }
185    
186            public static List<String> fromFile(File file) throws IOException {
187                    if (!file.exists()) {
188                            return new ArrayList<>();
189                    }
190    
191                    List<String> list = new ArrayList<>();
192    
193                    try (UnsyncBufferedReader unsyncBufferedReader =
194                                    new UnsyncBufferedReader(new FileReader(file))) {
195    
196                            String s = StringPool.BLANK;
197    
198                            while ((s = unsyncBufferedReader.readLine()) != null) {
199                                    list.add(s);
200                            }
201                    }
202    
203                    return list;
204            }
205    
206            public static List<String> fromFile(String fileName) throws IOException {
207                    return fromFile(new File(fileName));
208            }
209    
210            public static <E> List<E> fromMapKeys(Map<? extends E, ?> map) {
211                    if (MapUtil.isEmpty(map)) {
212                            return new ArrayList<>();
213                    }
214    
215                    List<E> list = new ArrayList<>(map.size());
216    
217                    for (Map.Entry<? extends E, ?> entry : map.entrySet()) {
218                            list.add(entry.getKey());
219                    }
220    
221                    return list;
222            }
223    
224            public static <E> List<E> fromMapValues(Map<?, ? extends E> map) {
225                    if (MapUtil.isEmpty(map)) {
226                            return new ArrayList<>();
227                    }
228    
229                    List<E> list = new ArrayList<>(map.size());
230    
231                    for (Map.Entry<?, ? extends E> entry : map.entrySet()) {
232                            list.add(entry.getValue());
233                    }
234    
235                    return list;
236            }
237    
238            public static List<String> fromString(String s) {
239                    return fromArray(StringUtil.splitLines(s));
240            }
241    
242            public static List<String> fromString(String s, String delimiter) {
243                    return fromArray(StringUtil.split(s, delimiter));
244            }
245    
246            public static boolean isEmpty(List<?> list) {
247                    if ((list == null) || list.isEmpty()) {
248                            return true;
249                    }
250    
251                    return false;
252            }
253    
254            public static boolean isNotEmpty(List<?> list) {
255                    return !isEmpty(list);
256            }
257    
258            public static boolean isNotNull(List<?> list) {
259                    return !isNull(list);
260            }
261    
262            public static boolean isNull(List<?> list) {
263                    if ((list == null) || list.isEmpty()) {
264                            return true;
265                    }
266    
267                    for (int i = 0; i < list.size(); i++) {
268                            Object bean = list.get(i);
269    
270                            if (Validator.isNotNull(bean)) {
271                                    return false;
272                            }
273                    }
274    
275                    return true;
276            }
277    
278            public static boolean isUnmodifiableList(List<?> list) {
279                    return _unmodifiableListClass.isInstance(list);
280            }
281    
282            /**
283             * @deprecated As of 6.2.0
284             */
285            @Deprecated
286            public static <E> boolean remove(List<? extends E> list, E element) {
287                    Iterator<? extends E> itr = list.iterator();
288    
289                    while (itr.hasNext()) {
290                            E curElement = itr.next();
291    
292                            if ((curElement == element) || curElement.equals(element)) {
293                                    itr.remove();
294    
295                                    return true;
296                            }
297                    }
298    
299                    return false;
300            }
301    
302            public static <E> List<E> remove(List<E> list, List<? extends E> remove) {
303                    if (isEmpty(list) || isEmpty(remove)) {
304                            return list;
305                    }
306    
307                    list = copy(list);
308    
309                    for (E element : remove) {
310                            list.remove(element);
311                    }
312    
313                    return list;
314            }
315    
316            public static <E> Iterator<E> reverseIterator(List<E> list) {
317                    final ListIterator<E> listIterator = list.listIterator(list.size());
318    
319                    return new Iterator<E>() {
320    
321                            @Override
322                            public boolean hasNext() {
323                                    return listIterator.hasPrevious();
324                            }
325    
326                            @Override
327                            public E next() {
328                                    return listIterator.previous();
329                            }
330    
331                            @Override
332                            public void remove() {
333                                    listIterator.remove();
334                            }
335    
336                    };
337            }
338    
339            public static <E> List<E> sort(List<E> list) {
340                    return sort(list, null);
341            }
342    
343            public static <E> List<E> sort(
344                    List<E> list, Comparator<? super E> comparator) {
345    
346                    if (isUnmodifiableList(list)) {
347                            list = copy(list);
348                    }
349    
350                    Collections.sort(list, comparator);
351    
352                    return list;
353            }
354    
355            public static <E> List<E> subList(List<E> list, int start, int end) {
356                    if (start < 0) {
357                            start = 0;
358                    }
359    
360                    if ((end < 0) || (end > list.size())) {
361                            end = list.size();
362                    }
363    
364                    if (start < end) {
365                            return list.subList(start, end);
366                    }
367    
368                    return Collections.emptyList();
369            }
370    
371            public static <T, A> A[] toArray(
372                    List<? extends T> list, Accessor<T, A> accessor) {
373    
374                    if (isEmpty(list)) {
375                            return (A[])Array.newInstance(accessor.getAttributeClass(), 0);
376                    }
377    
378                    A[] array = (A[])Array.newInstance(
379                            accessor.getAttributeClass(), list.size());
380    
381                    for (int i = 0; i < list.size(); i++) {
382                            T bean = list.get(i);
383    
384                            A attribute = accessor.get(bean);
385    
386                            array[i] = attribute;
387                    }
388    
389                    return array;
390            }
391    
392            public static List<Boolean> toList(boolean[] array) {
393                    if (ArrayUtil.isEmpty(array)) {
394                            return new ArrayList<>();
395                    }
396    
397                    List<Boolean> list = new ArrayList<>(array.length);
398    
399                    for (boolean value : array) {
400                            list.add(value);
401                    }
402    
403                    return list;
404            }
405    
406            public static List<Character> toList(char[] array) {
407                    if (ArrayUtil.isEmpty(array)) {
408                            return new ArrayList<>();
409                    }
410    
411                    List<Character> list = new ArrayList<>(array.length);
412    
413                    for (char value : array) {
414                            list.add(value);
415                    }
416    
417                    return list;
418            }
419    
420            public static List<Double> toList(double[] array) {
421                    if (ArrayUtil.isEmpty(array)) {
422                            return new ArrayList<>();
423                    }
424    
425                    List<Double> list = new ArrayList<>(array.length);
426    
427                    for (double value : array) {
428                            list.add(value);
429                    }
430    
431                    return list;
432            }
433    
434            public static <E> List<E> toList(E[] array) {
435                    if (ArrayUtil.isEmpty(array)) {
436                            return new ArrayList<>();
437                    }
438    
439                    return new ArrayList<>(Arrays.asList(array));
440            }
441    
442            public static List<Float> toList(float[] array) {
443                    if (ArrayUtil.isEmpty(array)) {
444                            return new ArrayList<>();
445                    }
446    
447                    List<Float> list = new ArrayList<>(array.length);
448    
449                    for (float value : array) {
450                            list.add(value);
451                    }
452    
453                    return list;
454            }
455    
456            public static List<Integer> toList(int[] array) {
457                    if (ArrayUtil.isEmpty(array)) {
458                            return new ArrayList<>();
459                    }
460    
461                    List<Integer> list = new ArrayList<>(array.length);
462    
463                    for (int value : array) {
464                            list.add(value);
465                    }
466    
467                    return list;
468            }
469    
470            public static <T, A> List<A> toList(List<T> list, Accessor<T, A> accessor) {
471                    List<A> aList = new ArrayList<>(list.size());
472    
473                    for (T t : list) {
474                            aList.add(accessor.get(t));
475                    }
476    
477                    return aList;
478            }
479    
480            public static <T, R> List<R> toList(List<T> list, Function<T, R> function) {
481                    final List<R> result = new ArrayList<>(list.size());
482    
483                    for (T t : list) {
484                            result.add(function.apply(t));
485                    }
486    
487                    return result;
488            }
489    
490            public static <T, V extends T> List<T> toList(List<V> vlist) {
491                    return new ArrayList<T>(vlist);
492            }
493    
494            public static List<Long> toList(long[] array) {
495                    if (ArrayUtil.isEmpty(array)) {
496                            return new ArrayList<>();
497                    }
498    
499                    List<Long> list = new ArrayList<>(array.length);
500    
501                    for (long value : array) {
502                            list.add(value);
503                    }
504    
505                    return list;
506            }
507    
508            public static List<Short> toList(short[] array) {
509                    if (ArrayUtil.isEmpty(array)) {
510                            return new ArrayList<>();
511                    }
512    
513                    List<Short> list = new ArrayList<>(array.length);
514    
515                    for (short value : array) {
516                            list.add(value);
517                    }
518    
519                    return list;
520            }
521    
522            public static <T> long[] toLongArray(
523                    List<? extends T> list, Accessor<T, Long> accessor) {
524    
525                    if (isEmpty(list)) {
526                            return (long[])Array.newInstance(long.class, 0);
527                    }
528    
529                    long[] array = (long[])Array.newInstance(long.class, list.size());
530    
531                    for (int i = 0; i < list.size(); i++) {
532                            T bean = list.get(i);
533    
534                            Long attribute = accessor.get(bean);
535    
536                            array[i] = attribute;
537                    }
538    
539                    return array;
540            }
541    
542            /**
543             * @see ArrayUtil#toString(Object[], Accessor)
544             */
545            public static <T, A> String toString(
546                    List<? extends T> list, Accessor<T, A> accessor) {
547    
548                    return toString(list, accessor, StringPool.COMMA);
549            }
550    
551            /**
552             * @see ArrayUtil#toString(Object[], Accessor, String)
553             */
554            public static <T, A> String toString(
555                    List<? extends T> list, Accessor<T, A> accessor, String delimiter) {
556    
557                    if (isEmpty(list)) {
558                            return StringPool.BLANK;
559                    }
560    
561                    StringBundler sb = new StringBundler(2 * list.size() - 1);
562    
563                    for (int i = 0; i < list.size(); i++) {
564                            T bean = list.get(i);
565    
566                            A attribute = accessor.get(bean);
567    
568                            if (attribute != null) {
569                                    sb.append(attribute);
570                            }
571    
572                            if ((i + 1) != list.size()) {
573                                    sb.append(delimiter);
574                            }
575                    }
576    
577                    return sb.toString();
578            }
579    
580            /**
581             * @see ArrayUtil#toString(Object[], String)
582             */
583            public static String toString(List<?> list, String param) {
584                    return toString(list, param, StringPool.COMMA);
585            }
586    
587            /**
588             * @see ArrayUtil#toString(Object[], String, String)
589             */
590            public static String toString(
591                    List<?> list, String param, String delimiter) {
592    
593                    if (isEmpty(list)) {
594                            return StringPool.BLANK;
595                    }
596    
597                    StringBundler sb = new StringBundler(2 * list.size() - 1);
598    
599                    for (int i = 0; i < list.size(); i++) {
600                            Object bean = list.get(i);
601    
602                            Object value = null;
603    
604                            if (Validator.isNull(param)) {
605                                    value = String.valueOf(bean);
606                            }
607                            else {
608                                    value = BeanPropertiesUtil.getObject(bean, param);
609                            }
610    
611                            if (value != null) {
612                                    sb.append(value);
613                            }
614    
615                            if ((i + 1) != list.size()) {
616                                    sb.append(delimiter);
617                            }
618                    }
619    
620                    return sb.toString();
621            }
622    
623            public static <T> List<T> unique(List<T> list) {
624                    Set<T> set = new LinkedHashSet<>();
625    
626                    set.addAll(list);
627    
628                    if (list.size() == set.size()) {
629                            return list;
630                    }
631    
632                    return new ArrayList<>(set);
633            }
634    
635            private static final Class<? extends List<?>> _unmodifiableListClass;
636    
637            static {
638                    List<Object> unmodifiableList = Collections.<Object>unmodifiableList(
639                            new LinkedList<Object>());
640    
641                    _unmodifiableListClass =
642                            (Class<? extends List<?>>)unmodifiableList.getClass();
643            }
644    
645    }