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<E>(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<E>();
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<E>();
152                    }
153    
154                    return new ArrayList<E>(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<E>();
165                    }
166    
167                    List<E> list = new ArrayList<E>(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<E>();
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<String>();
189                    }
190    
191                    List<String> list = new ArrayList<String>();
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<E>();
213                    }
214    
215                    List<E> list = new ArrayList<E>(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<E>();
227                    }
228    
229                    List<E> list = new ArrayList<E>(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 isUnmodifiableList(List<?> list) {
259                    return _unmodifiableListClass.isInstance(list);
260            }
261    
262            /**
263             * @deprecated As of 6.2.0
264             */
265            @Deprecated
266            public static <E> boolean remove(List<? extends E> list, E element) {
267                    Iterator<? extends E> itr = list.iterator();
268    
269                    while (itr.hasNext()) {
270                            E curElement = itr.next();
271    
272                            if ((curElement == element) || curElement.equals(element)) {
273                                    itr.remove();
274    
275                                    return true;
276                            }
277                    }
278    
279                    return false;
280            }
281    
282            public static <E> List<E> remove(List<E> list, List<? extends E> remove) {
283                    if (isEmpty(list) || isEmpty(remove)) {
284                            return list;
285                    }
286    
287                    list = copy(list);
288    
289                    for (E element : remove) {
290                            list.remove(element);
291                    }
292    
293                    return list;
294            }
295    
296            public static <E> Iterator<E> reverseIterator(List<E> list) {
297                    final ListIterator<E> listIterator = list.listIterator(list.size());
298    
299                    return new Iterator<E>() {
300    
301                            @Override
302                            public boolean hasNext() {
303                                    return listIterator.hasPrevious();
304                            }
305    
306                            @Override
307                            public E next() {
308                                    return listIterator.previous();
309                            }
310    
311                            @Override
312                            public void remove() {
313                                    listIterator.remove();
314                            }
315    
316                    };
317            }
318    
319            public static <E> List<E> sort(List<E> list) {
320                    return sort(list, null);
321            }
322    
323            public static <E> List<E> sort(
324                    List<E> list, Comparator<? super E> comparator) {
325    
326                    if (isUnmodifiableList(list)) {
327                            list = copy(list);
328                    }
329    
330                    Collections.sort(list, comparator);
331    
332                    return list;
333            }
334    
335            public static <E> List<E> subList(List<E> list, int start, int end) {
336                    if (start < 0) {
337                            start = 0;
338                    }
339    
340                    if ((end < 0) || (end > list.size())) {
341                            end = list.size();
342                    }
343    
344                    if (start < end) {
345                            return list.subList(start, end);
346                    }
347    
348                    return Collections.emptyList();
349            }
350    
351            public static <T, A> A[] toArray(
352                    List<? extends T> list, Accessor<T, A> accessor) {
353    
354                    if (isEmpty(list)) {
355                            return (A[])Array.newInstance(accessor.getAttributeClass(), 0);
356                    }
357    
358                    A[] array = (A[])Array.newInstance(
359                            accessor.getAttributeClass(), list.size());
360    
361                    for (int i = 0; i < list.size(); i++) {
362                            T bean = list.get(i);
363    
364                            A attribute = accessor.get(bean);
365    
366                            array[i] = attribute;
367                    }
368    
369                    return array;
370            }
371    
372            public static List<Boolean> toList(boolean[] array) {
373                    if (ArrayUtil.isEmpty(array)) {
374                            return new ArrayList<Boolean>();
375                    }
376    
377                    List<Boolean> list = new ArrayList<Boolean>(array.length);
378    
379                    for (boolean value : array) {
380                            list.add(value);
381                    }
382    
383                    return list;
384            }
385    
386            public static List<Character> toList(char[] array) {
387                    if (ArrayUtil.isEmpty(array)) {
388                            return new ArrayList<Character>();
389                    }
390    
391                    List<Character> list = new ArrayList<Character>(array.length);
392    
393                    for (char value : array) {
394                            list.add(value);
395                    }
396    
397                    return list;
398            }
399    
400            public static List<Double> toList(double[] array) {
401                    if (ArrayUtil.isEmpty(array)) {
402                            return new ArrayList<Double>();
403                    }
404    
405                    List<Double> list = new ArrayList<Double>(array.length);
406    
407                    for (double value : array) {
408                            list.add(value);
409                    }
410    
411                    return list;
412            }
413    
414            public static <E> List<E> toList(E[] array) {
415                    if (ArrayUtil.isEmpty(array)) {
416                            return new ArrayList<E>();
417                    }
418    
419                    return new ArrayList<E>(Arrays.asList(array));
420            }
421    
422            public static List<Float> toList(float[] array) {
423                    if (ArrayUtil.isEmpty(array)) {
424                            return new ArrayList<Float>();
425                    }
426    
427                    List<Float> list = new ArrayList<Float>(array.length);
428    
429                    for (float value : array) {
430                            list.add(value);
431                    }
432    
433                    return list;
434            }
435    
436            public static List<Integer> toList(int[] array) {
437                    if (ArrayUtil.isEmpty(array)) {
438                            return new ArrayList<Integer>();
439                    }
440    
441                    List<Integer> list = new ArrayList<Integer>(array.length);
442    
443                    for (int value : array) {
444                            list.add(value);
445                    }
446    
447                    return list;
448            }
449    
450            public static <T, A> List<A> toList(List<T> list, Accessor<T, A> accessor) {
451                    List<A> aList = new ArrayList<A>(list.size());
452    
453                    for (T t : list) {
454                            aList.add(accessor.get(t));
455                    }
456    
457                    return aList;
458            }
459    
460            public static <T, V extends T> List<T> toList(List<V> vlist) {
461                    return new ArrayList<T>(vlist);
462            }
463    
464            public static List<Long> toList(long[] array) {
465                    if (ArrayUtil.isEmpty(array)) {
466                            return new ArrayList<Long>();
467                    }
468    
469                    List<Long> list = new ArrayList<Long>(array.length);
470    
471                    for (long value : array) {
472                            list.add(value);
473                    }
474    
475                    return list;
476            }
477    
478            public static List<Short> toList(short[] array) {
479                    if (ArrayUtil.isEmpty(array)) {
480                            return new ArrayList<Short>();
481                    }
482    
483                    List<Short> list = new ArrayList<Short>(array.length);
484    
485                    for (short value : array) {
486                            list.add(value);
487                    }
488    
489                    return list;
490            }
491    
492            public static <T> long[] toLongArray(
493                    List<? extends T> list, Accessor<T, Long> accessor) {
494    
495                    if (isEmpty(list)) {
496                            return (long[])Array.newInstance(long.class, 0);
497                    }
498    
499                    long[] array = (long[])Array.newInstance(long.class, list.size());
500    
501                    for (int i = 0; i < list.size(); i++) {
502                            T bean = list.get(i);
503    
504                            Long attribute = accessor.get(bean);
505    
506                            array[i] = attribute;
507                    }
508    
509                    return array;
510            }
511    
512            /**
513             * @see ArrayUtil#toString(Object[], Accessor)
514             */
515            public static <T, A> String toString(
516                    List<? extends T> list, Accessor<T, A> accessor) {
517    
518                    return toString(list, accessor, StringPool.COMMA);
519            }
520    
521            /**
522             * @see ArrayUtil#toString(Object[], Accessor, String)
523             */
524            public static <T, A> String toString(
525                    List<? extends T> list, Accessor<T, A> accessor, String delimiter) {
526    
527                    if (isEmpty(list)) {
528                            return StringPool.BLANK;
529                    }
530    
531                    StringBundler sb = new StringBundler(2 * list.size() - 1);
532    
533                    for (int i = 0; i < list.size(); i++) {
534                            T bean = list.get(i);
535    
536                            A attribute = accessor.get(bean);
537    
538                            if (attribute != null) {
539                                    sb.append(attribute);
540                            }
541    
542                            if ((i + 1) != list.size()) {
543                                    sb.append(delimiter);
544                            }
545                    }
546    
547                    return sb.toString();
548            }
549    
550            /**
551             * @see ArrayUtil#toString(Object[], String)
552             */
553            public static String toString(List<?> list, String param) {
554                    return toString(list, param, StringPool.COMMA);
555            }
556    
557            /**
558             * @see ArrayUtil#toString(Object[], String, String)
559             */
560            public static String toString(
561                    List<?> list, String param, String delimiter) {
562    
563                    if (isEmpty(list)) {
564                            return StringPool.BLANK;
565                    }
566    
567                    StringBundler sb = new StringBundler(2 * list.size() - 1);
568    
569                    for (int i = 0; i < list.size(); i++) {
570                            Object bean = list.get(i);
571    
572                            Object value = null;
573    
574                            if (Validator.isNull(param)) {
575                                    value = String.valueOf(bean);
576                            }
577                            else {
578                                    value = BeanPropertiesUtil.getObject(bean, param);
579                            }
580    
581                            if (value != null) {
582                                    sb.append(value);
583                            }
584    
585                            if ((i + 1) != list.size()) {
586                                    sb.append(delimiter);
587                            }
588                    }
589    
590                    return sb.toString();
591            }
592    
593            public static <T> List<T> unique(List<T> list) {
594                    Set<T> set = new LinkedHashSet<T>();
595    
596                    set.addAll(list);
597    
598                    if (list.size() == set.size()) {
599                            return list;
600                    }
601    
602                    return new ArrayList<T>(set);
603            }
604    
605            private static Class<? extends List<?>> _unmodifiableListClass;
606    
607            static {
608                    List<Object> unmodifiableList = Collections.<Object>unmodifiableList(
609                            new LinkedList<Object>());
610    
611                    _unmodifiableListClass =
612                            (Class<? extends List<?>>)unmodifiableList.getClass();
613            }
614    
615    }