All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.boon.sort.Sorting Maven / Gradle / Ivy

Go to download

Simple opinionated Java for the novice to expert level Java Programmer. Low Ceremony. High Productivity. A real boon to Java to developers!

There is a newer version: 0.34
Show newest version
/*
 * Copyright 2013-2014 Richard M. Hightower
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  		http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * __________                              _____          __   .__
 * \______   \ ____   ____   ____   /\    /     \ _____  |  | _|__| ____    ____
 *  |    |  _//  _ \ /  _ \ /    \  \/   /  \ /  \\__  \ |  |/ /  |/    \  / ___\
 *  |    |   (  <_> |  <_> )   |  \ /\  /    Y    \/ __ \|    <|  |   |  \/ /_/  >
 *  |______  /\____/ \____/|___|  / \/  \____|__  (____  /__|_ \__|___|  /\___  /
 *         \/                   \/              \/     \/     \/       \//_____/
 *      ____.                     ___________   _____    ______________.___.
 *     |    |____ ___  _______    \_   _____/  /  _  \  /   _____/\__  |   |
 *     |    \__  \\  \/ /\__  \    |    __)_  /  /_\  \ \_____  \  /   |   |
 * /\__|    |/ __ \\   /  / __ \_  |        \/    |    \/        \ \____   |
 * \________(____  /\_/  (____  / /_______  /\____|__  /_______  / / ______|
 *               \/           \/          \/         \/        \/  \/
 */

package org.boon.sort;

import org.boon.*;
import org.boon.core.Typ;
import org.boon.core.reflection.BeanUtils;
import org.boon.core.Conversions;
import org.boon.core.reflection.Fields;
import org.boon.core.reflection.fields.FieldAccess;

import java.text.Collator;
import java.util.*;

import static org.boon.core.Conversions.toArray;

public class Sorting {

    /**
     * Gets the logger.
     */
    private static final Logger log = Boon.configurableLogger(Sorting.class.getName());


    /** Takes a list an an array or sorts
     *
     * @param list list to sorts
     * @param sorts what you want to sore the list by
     */
    public static void sort(List list, Sort... sorts) {
        Sort.sorts(sorts).sort(list);
    }



    /**
     * Sort a list.
     * @param list the list you want to sort
     * @param sortBy what you want to sort the list by
     * @param ascending do you want ascending order
     * @param nullsFirst do you want nulls first
     */
    public static void sort( List list, String sortBy, boolean ascending, boolean nullsFirst ) {
        if ( list == null || list.size() == 0 ) {
            return;
        }

        if (sortBy.equals("this")) {

            Collections.sort(list, thisUniversalComparator(ascending, nullsFirst));
            return;
        }
        Iterator iterator = list.iterator();
        Object object = iterator.next();

        Map fields = null;

        if (object != null) {
          fields = BeanUtils.getFieldsFromObject( object );
        } else {
            while(iterator.hasNext()) {

                object = iterator.next();
                if (object!=null) {
                    fields = BeanUtils.getFieldsFromObject( object );
                    break;
                }
            }

        }


        if (fields!=null) {

            final FieldAccess field = fields.get( sortBy );

            if ( field != null ) {

                Collections.sort( list, Sorting.universalComparator(field, ascending, nullsFirst) );

            }
        }
    }


    /**
     * Sort collection.
     * @param collection the collection you want to sort
     * @param sortBy what you want to sort the list by
     * @param ascending do you want ascending order
     * @param nullsFirst do you want nulls first
     */
    public static  Collection  sort( Class componentType, Collection collection, String sortBy, boolean ascending, boolean nullsFirst ) {

        if (collection instanceof List) {
            sort ((List) collection, sortBy, ascending, nullsFirst);
            return collection;
        } else {
            V[] array = toArray(componentType, collection);
            sort(array, sortBy, ascending, nullsFirst);
            if (collection instanceof LinkedHashSet) {
                return new LinkedHashSet<>(Lists.list(array));
            } else {
                return Lists.list(array);
            }
        }
    }


    /**
     * Sort map entries.
     * @param map  the map entries you want to sort
     * @param sortBy what you want to sort the list by
     * @param ascending do you want ascending order
     * @param nullsFirst do you want nulls first
     */
    public static  Collection>  sortEntries( Class componentType, Map map,
                                                            String sortBy, boolean ascending, boolean nullsFirst ) {

        return sort ((Class) componentType, (Collection) map.entrySet() , sortBy, ascending, nullsFirst);

    }

    /**
     * Sort map values.
     * @param map  the map entries you want to sort
     * @param sortBy what you want to sort the list by
     * @param ascending do you want ascending order
     * @param nullsFirst do you want nulls first
     */
    public static  Collection>  sortValues( Class componentType, Map map,
                                                                   String sortBy, boolean ascending, boolean nullsFirst ) {

        return sort ((Class) componentType, (Collection) map.values() , sortBy, ascending, nullsFirst);

    }


    /**
     * Sort map keys.
     * @param map  the map entries you want to sort
     * @param sortBy what you want to sort the list by
     * @param ascending do you want ascending order
     * @param nullsFirst do you want nulls first
     */
    public static  Collection>  sortKeys( Class componentType, Map map,
                                                                  String sortBy, boolean ascending, boolean nullsFirst ) {

        return sort ((Class) componentType, (Collection) map.keySet() , sortBy, ascending, nullsFirst);

    }





    /**
     * Sort collection.
     * @param iterable the iterable you want to sort
     * @param sortBy what you want to sort the list by
     * @param ascending do you want ascending order
     * @param nullsFirst do you want nulls first
     */
    public static  Iterable sort( Class componentType, Iterable iterable, String sortBy, boolean ascending, boolean nullsFirst ) {

        if (iterable instanceof List) {
            sort ((List) iterable, sortBy, ascending, nullsFirst);
            return iterable;
        } else if (iterable instanceof  Collection) {
            return sort (componentType, (Collection) iterable, sortBy, ascending, nullsFirst);
        } else {
            List list = Lists.list(iterable);
            sort ( list, sortBy, ascending, nullsFirst);
            return list;
        }
    }

    /**
     * Sort an array.
     * @param array the list you want to sort
     * @param sortBy what you want to sort the list by
     * @param ascending do you want ascending order
     * @param nullsFirst do you want nulls first
     */
    public static  void  sort( T[] array, String sortBy, boolean ascending, boolean nullsFirst ) {
        if ( array == null || array.length == 0 ) {
            return;
        }

        if (sortBy.equals("this")) {

            Arrays.sort(array, thisUniversalComparator(ascending, nullsFirst));
            return;
        }

        Object object = array[0];

        Map fields = null;

        if (object != null) {
            fields = BeanUtils.getFieldsFromObject( object );
        } else {
            for (int index=1; index< array.length; index++) {

                object = array[index];
                if (object!=null) {
                    fields = BeanUtils.getFieldsFromObject( object );
                    break;
                }
            }

        }


        if (fields!=null) {

            final FieldAccess field = fields.get( sortBy );

            if ( field != null ) {

                Arrays.sort( array, Sorting.universalComparator(field, ascending, nullsFirst) );

            }
        }
    }


    /**
     * Sorts a list based on the natural ascending order.
     * This puts null values last.
     * @param list the list you want to sort.
     */
    public static void sort( List list ) {
        sort( list, "this", true, false);
    }

    /**
     * Sorts a array based on the natural ascending order.
     * This puts null values last.
     * @param array the list you want to sort.
     */
    public static  void sort( T[] array ) {
        sort( array, "this", true, false);
    }

    /**
     * Sorts a collection based on the natural ascending order.
     * This puts null values last.
     * @param collection the list you want to sort.
     */
    public static  Collection sort( Class componentType, Collection collection ) {
        return sort( componentType, collection, "this", true, false);
    }

    /**
     * Sorts a iterable based on the natural ascending order.
     * This puts null values last.
     * @param iterable the list you want to sort.
     */
    public static  Iterable sort( Class componentType, Iterable iterable ) {
        return sort( componentType, iterable, "this", true, false);
    }




    /**
     * Sorts a list based on the natural ascending order and puts null values first.
     * @param list the list you want to sort.
     */
    public static void sortNullsFirst( List list ) {

        sort(list, "this", true, true);
    }

    /**
     * Sorts an array based on the natural ascending order and puts null values first.
     * @param array the list you want to sort.
     */
    public static  void sortNullsFirst( T[] array ) {

        sort(array, "this", true, true);
    }

    /**
     * Sorts a collection based on the natural ascending order.
     * This puts null values first.
     * @param collection the collection you want to sort.
     */
    public static  Collection sortNullsFirst( Class componentType, Collection collection ) {
        return sort( componentType, collection, "this", true, true);
    }


    /**
     * Sorts an iterable based on the natural ascending order.
     * This puts null values first.
     * @param iterable the list you want to sort.
     */
    public static  Iterable sortNullsFirst( Class componentType, Iterable iterable ) {
        return sort( componentType, iterable, "this", true, true);
    }





    /**
     * Sorts a list based on the natural order descending order.
     * This puts null values last.
     * @param list the list you want to sort.
     */
    public static void sortDesc( List list ) {
        sort( list, "this", false, false);

    }

    /**
     * Sorts a array based on the natural order descending order.
     * This puts null values last.
     * @param array the list you want to sort.
     */
    public static  void sortDesc( T[] array ) {
        sort( array, "this", false, false);

    }

    /**
     * Sorts a iterable based on the natural descending order.
     * This puts null values last.
     * @param iterable the iterable you want to sort.
     */
    public static  Iterable sortDesc( Class componentType, Iterable iterable ) {
        return sort( componentType, iterable, "this", false, false);
    }

    /**
     * Sorts a collection based on the natural descending order.
     * This puts null values last.
     * @param collection the collection you want to sort.
     */
    public static  Collection sortDesc( Class componentType, Collection collection ) {
        return sort( componentType, collection, "this", false, false);
    }





    /**
     * Sorts a list based on the natural order descending order.
     * This puts null values first.
     * @param list the list you want to sort.
     */
    public static void sortDescNullsFirst( List list ) {
        sort( list, "this", false, true);

    }



    /**
     * Sorts a array based on the natural order descending order.
     * This puts null values first.
     * @param array the list you want to sort.
     */
    public static  void sortDescNullsFirst( T[] array ) {
        sort( array, "this", false, true);

    }

    /**
     * Sorts a iterable based on the natural descending order.
     * This puts null values first.
     * @param iterable the iterable you want to sort.
     */
    public static  Iterable sortDescNullsFirst( Class componentType, Iterable iterable ) {
        return sort( componentType, iterable, "this", false, true);
    }

    /**
     * Sorts a collection based on the natural descending order.
     * This puts null values first.
     * @param collection the collection you want to sort.
     */
    public static  Collection sortDescNullsFirst( Class componentType, Collection collection ) {
        return sort( componentType, collection, "this", false, true);
    }


    /**
     *
     * Sorts lists ascending
     * Nulls last.
     * @param list the list you want to sort
     * @param sortBy what you want to sort the list by
     */
    public static void sort( List list, String sortBy ) {
        sort(list, sortBy, true, false);
    }




    /**
     *
     * Sorts array ascending
     * Nulls last.
     * @param array the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  void sort( T[] array, String sortBy ) {
        sort( array, sortBy, true, false);

    }

    /**
     *
     * Sorts iterable ascending
     * Nulls last.
     * @param iterable the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Iterable sort( Class componentType, Iterable iterable, String sortBy  ) {
        return sort( componentType, iterable, sortBy, true, false);
    }


    /**
     *
     * Sorts collection ascending
     * Nulls last.
     * @param collection the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Collection sort( Class componentType, Collection collection, String sortBy ) {
        return sort( componentType, collection, sortBy, true, false);
    }



    /**
     *
     * Sorts lists Ascending Null first
     * Nulls first.
     *
     * @param list the list you want to sort
     * @param sortBy what you want to sort the list by
     */
    public static void sortNullsFirst( List list, String sortBy ) {
        sort( list, sortBy, true, true);
    }



    /**
     *
     * Sorts array ascending
     * Nulls first.
     * @param array the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  void sortNullsFirst( T[] array, String sortBy ) {
        sort( array, sortBy, true, true);

    }

    /**
     *
     * Sorts iterable ascending
     * Nulls first.
     * @param iterable the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Iterable sortNullsFirst( Class componentType, Iterable iterable, String sortBy  ) {
        return sort( componentType, iterable, sortBy, true, true);
    }


    /**
     *
     * Sorts collection ascending
     * Nulls first.
     * @param collection the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Collection sortNullsFirst( Class componentType, Collection collection, String sortBy ) {
        return sort( componentType, collection, sortBy, true, true);
    }


    /**
     *
     * Sorts lists Descending
     * @param list the list you want to sort
     * @param sortBy what you want to sort the list by
     */
    public static void sortDesc( List list, String sortBy ) {
        sort(list, sortBy, false, false);
    }




    /**
     *
     * Sorts array Descending
     * Nulls last.
     * @param array the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  void sortDesc( T[] array, String sortBy ) {
        sort( array, sortBy, false, false);

    }

    /**
     *
     * Sorts iterable ascending
     * Nulls last.
     * @param iterable the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Iterable sortDesc( Class componentType, Iterable iterable, String sortBy  ) {
        return sort( componentType, iterable, sortBy, false, false);
    }


    /**
     *
     * Sorts collection ascending
     * Nulls last.
     * @param collection the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Collection sortDesc( Class componentType, Collection collection, String sortBy ) {
        return sort( componentType, collection, sortBy, false, false);
    }



    /**
     *
     * Sorts lists Descending
     * @param list the list you want to sort
     * @param sortBy what you want to sort the list by
     */
    public static void sortDescNullsFirst( List list, String sortBy ) {
        sort( list, sortBy, false, true);
    }


    /**
     *
     * Sorts array Descending
     * Nulls first.
     * @param array the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  void sortDescNullsFirst( T[] array, String sortBy ) {
        sort( array, sortBy, false, true);

    }

    /**
     *
     * Sorts iterable ascending
     * Nulls first.
     * @param iterable the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Iterable sortDescNullsFirst( Class componentType, Iterable iterable, String sortBy  ) {
        return sort( componentType, iterable, sortBy, false, true);
    }


    /**
     *
     * Sorts collection ascending
     * Nulls first.
     * @param collection the list you want to sort
     * @param sortBy what you want to sort the array by
     */
    public static  Collection sortDescNullsFirst( Class componentType, Collection collection, String sortBy ) {
        return sort( componentType, collection, sortBy, false, true);
    }



    /**
     * This creates the universal comparator object which is used by the sort work horse.
     *
     * @param field The field we are sorting on.
     * @param ascending if this should be ascending or descending.
     * @return
     */
    public static Comparator universalComparator( final FieldAccess field, final boolean ascending,
                                                  final boolean nullsFirst) {
        return new Comparator() {
            @Override
            public int compare( Object o1, Object o2 ) {
                Object value1 = null;
                Object value2 = null;

                if ( ascending ) {
                    value1 = field.getValue( o1 );
                    value2 = field.getValue( o2 );
                } else {
                    value1 = field.getValue( o2 );
                    value2 = field.getValue( o1 );
                }
                return Sorting.compare(value1, value2, nullsFirst);
            }
        };
    }



    /**
     * This creates the universal comparator object used for "this".
     *
     * @param ascending if this should be ascending or descending.
     * @return
     */
    public static Comparator thisUniversalComparator( final boolean ascending,
                                                  final boolean nullsFirst) {
        return new Comparator() {
            @Override
            public int compare( Object o1, Object o2 ) {
                Object value1;
                Object value2;


                if ( ascending ) {
                    value1 =  ( o1 );
                    value2 =  ( o2 );
                } else {
                    value1 =  ( o2 );
                    value2 =  ( o1 );
                }

                return Sorting.compare(value1, value2, nullsFirst);
            }
        };
    }

    /**
     * This compares two values.
     * @param value1 value1
     * @param value2 value2
     * @return
     */
    public static int compare( Object value1, Object value2 ) {
        return compare(value1, value2, false);
    }

    /**
     * This compares two values.
     * If the objects are strings (CharSequence) they are always compared lexicographically.
     * If the objects are comparable they are always compared using a natural order.
     *
     * @param value1 value1
     * @param value2 value2
     * @param nullsLast put nulls last
     *
     * @return
     */
    public static int compare( Object value1, Object value2, boolean nullsLast ) {

        if ( value1 == null && value2 == null ) {
            return 0;
        } else if ( value1 == null && value2 != null ) {
            return nullsLast ? -1 : 1;
        } else if ( value1 != null && value2 == null ) {
            return nullsLast ? 1 : -1;
        }


        /** Objects are string like so compare using collator. */
        if ( value1 instanceof CharSequence ) {
            String str1 = Conversions.toString( value1 );
            String str2 = Conversions.toString( value2 );
            Collator collator = Collator.getInstance();
            return collator.compare( str1, str2 );

        /** Objects are comparable, yeah! */
        } else if ( Typ.isComparable( value1 ) && value1.getClass() == value2.getClass()) {
            Comparable c1 = Conversions.comparable(value1);
            Comparable c2 = Conversions.comparable(value2);
            return c1.compareTo( c2 );
        } else if (  value1 instanceof Integer && value2 instanceof Integer ) {
            Comparable c1 = Conversions.comparable(value1);
            Comparable c2 = Conversions.comparable(value2);
            return c1.compareTo( c2 );
        }
        else if (  value1 instanceof Double && value2 instanceof Double ) {
            Comparable c1 = Conversions.comparable(value1);
            Comparable c2 = Conversions.comparable(value2);
            return c1.compareTo( c2 );
        }
        else if (  value1 instanceof Long && value2 instanceof Long ) {
            Comparable c1 = Conversions.comparable(value1);
            Comparable c2 = Conversions.comparable(value2);
            return c1.compareTo( c2 );
        }
        else if (  value1 instanceof Number && value2 instanceof Number ) {
            Double c1 = Conversions.toDouble(value1);
            Double c2 = Conversions.toDouble(value2);
            return c1.compareTo( c2 );
        }
         else {
            /** Object are neither String like or comparable.
             * Ours it not to reason why, ours it to do or die.
             * Find the first sortable field and sort by that.
             * */
            String name = Fields.getSortableField( value1 );
            String sv1 = ( String ) BeanUtils.getPropByPath( value1, name );
            String sv2 = ( String ) BeanUtils.getPropByPath( value2, name );
            return Sorting.compare(sv1, sv2);

        }

    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy