Java tutorial
/* * Copyright (C) 2008 feilong * * 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. */ package com.feilong.core.util; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.commons.collections4.comparators.ReverseComparator; import org.apache.commons.lang3.Validate; import com.feilong.core.util.comparator.BeanComparatorUtil; import com.feilong.core.util.comparator.PropertyComparator; import static com.feilong.core.bean.ConvertUtil.toArray; import static com.feilong.core.bean.ConvertUtil.toList; import static com.feilong.core.bean.ConvertUtil.toMap; /** * ?. * * <h3>:</h3> * <blockquote> * <ol> * <li>?,jdk?sort, * * <pre class="code"> * {@link java.util.Arrays#sort(Object[])} * </pre> * * * * <pre class="code"> * {@link java.util.Collections#sort(List)} * </pre> * * void,?23? * * </li> * <li>,bean list???</li> * </ol> * </blockquote> * * @author <a href="http://feitianbenyue.iteye.com/">feilong</a> * @since 1.8.0 */ public final class SortUtil { /** Don't let anyone instantiate this class. */ private SortUtil() { //AssertionError?. ?????. ???. //see Effective Java 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } //***************************************************************************************** /** * <code>arrays</code> ?. * * <h3>????:</h3> * * <blockquote> * * <pre class="code"> * * public static String toSalesPropertiesIdsJson(Long...itemPropertiesIdLongs){ * Arrays.sort(itemPropertiesIdLongs); * return JsonUtil.format(itemPropertiesIdLongs, 0, 0); * } * * </pre> * * ???: * * <pre class="code"> * * public static String toSalesPropertiesIdsJson(Long...itemPropertiesIdLongs){ * return JsonUtil.format(sort(itemPropertiesIdLongs), 0, 0); * } * </pre> * * <b>?:</b> * * <pre class="code"> * * <span style="color:green">// ,??</span> * private Long getDefaultCategoryId(Long[] categoriesIds){ * Arrays.sort(categoriesIds); * return categoriesIds[0]; * } * * </pre> * * ???: * * <pre class="code"> * * <span style="color:green">// ,??</span> * private Long getDefaultCategoryId(Long[] categoriesIds){ * return sort(categoriesIds)[0]; * } * </pre> * * </blockquote> * * @param <T> * the generic type * @param arrays * the arrays * @return <code>array</code> null, empty array<br> * @see java.util.Arrays#sort(Object[]) */ @SafeVarargs public static <T> T[] sort(T... arrays) { if (null == arrays) { return toArray(); } Arrays.sort(arrays); return arrays; } /** * <code>arrays</code> <code>comparator</code> ?. * * @param <T> * the generic type * @param arrays * the arrays * @param comparator * the comparator * @return <code>array</code> null, empty array<br> * @see java.util.Arrays#sort(Object[], Comparator) */ public static <T> T[] sort(T[] arrays, Comparator<? super T> comparator) { if (null == arrays) { return toArray(); } Arrays.sort(arrays, comparator); return arrays; } //***************************************************************************************** /** * ? <code>list</code> ?. * * <p> * {@link java.util.Collections#sort(List) Collections.sort} {@link java.util.Arrays#sort(Object[]) Arrays.sort} * </p> * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * * List{@code <Integer>} list = toList(5, 10, 3, 2); * LOGGER.debug(JsonUtil.format(sort(list), 0, 0)); * * </pre> * * <b>:</b> * * <pre class="code"> * [2,3,5,10] * </pre> * * </blockquote> * * @param <T> * the generic type * @param list * the list * @return <code>list</code> null, {@link Collections#emptyList()}<br> * @see java.util.Collections#sort(List) */ public static <T extends Comparable<? super T>> List<T> sort(List<T> list) { if (null == list) { return emptyList(); } Collections.sort(list); return list; } /** * ? <code>list</code>, <code>comparator</code> ?. * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * * List{@code <User>} list = new ArrayList{@code <User>}(); * list.add(new User(12L, 18)); * list.add(new User(2L, 36)); * list.add(new User(5L, 22)); * list.add(new User(1L, 8)); * SortUtil.sort(list, new PropertyComparator{@code <User>}("id")); * LOGGER.debug(JsonUtil.format(list)); * * </pre> * * <b>:</b> * * <pre class="code"> * [{ "id": 1, "age": 8 }, { "id": 2, "age": 36 }, { "id": 5, "age": 22 }, { "id": 12, "age": 18 }] * </pre> * * ,?: * * <pre class="code"> * SortUtil.sort(list, "id"); * </pre> * * </blockquote> * * @param <O> * the generic type * @param list * the list * @param comparator * the comparator * @return <code>list</code> null, {@link Collections#emptyList()}<br> * @see java.util.Collections#sort(List, Comparator) */ public static <O> List<O> sort(List<O> list, Comparator<? super O> comparator) { if (null == list) { return emptyList(); } Collections.sort(list, comparator); return list; } //***************************************************************************************** /** * ? <code>list</code>, <code>propertyName</code> ?. * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * * List{@code <User>} list = toList(// * new User(12L, 18), * new User(2L, 36), * new User(2L, 2), * new User(2L, 30), * new User(1L, 8)); * SortUtil.sort(list, "age"); * LOGGER.debug(JsonUtil.formatWithIncludes(list, "id", "age")); * * </pre> * * <b>:</b> * * <pre class="code"> * [ * {"id": 2,"age": 2}, * {"id": 1,"age": 8}, * {"id": 12,"age": 18}, * {"id": 2,"age": 30}, * {"id": 2,"age": 36} * ] * </pre> * * </blockquote> * * <h3>2:</h3> * * <blockquote> * * <pre class="code"> * User id12 = new User(12L, 18); * User id2 = new User(2L, 36); * User id5 = new User(5L, 22); * User id1 = new User(1L, 8); * List<User> list = toList(id12, id2, id5, id1); * sort(list, "id"); * assertThat(list, contains(id1, id2, id5, id12)); * </pre> * * </blockquote> * * @param <O> * the generic type * @param list * the list * @param propertyName * O??,Possibly indexed and/or nested name of the property to be modified,?? * <a href="../bean/BeanUtil.html#propertyName">propertyName</a> * @return <code>list</code> null, {@link Collections#emptyList()}<br> * @throws NullPointerException * <code>propertyNames</code> null * @throws IllegalArgumentException * <code>propertyNames</code> empty * @see BeanComparatorUtil#propertyComparator(String) * @see #sort(List, Comparator) */ public static <O> List<O> sort(List<O> list, String propertyName) { if (null == list) { return emptyList(); } Validate.notEmpty(propertyName, "propertyName can't be null/empty!"); return sort(list, BeanComparatorUtil.propertyComparator(propertyName)); } /** * ? <code>list</code>,(?)?. * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * * List{@code <User>} list = new ArrayList{@code <User>}(); * list.add(new User(12L, 18)); * list.add(new User(2L, 36)); * list.add(new User(2L, 2)); * list.add(new User(2L, 30)); * list.add(new User(1L, 8)); * SortUtil.sort(list, "id", "age"); * LOGGER.debug(JsonUtil.formatWithIncludes(list, "id", "age")); * * </pre> * * <b>:</b> * * <pre class="code"> [{"id": 1,"age": 8}, {"id": 2,"age": 2}, {"id": 2,"age": 30}, {"id": 2,"age": 36}, {"id": 12,"age": 18}] * </pre> * * </blockquote> * * @param <O> * the generic type * @param list * the list * @param propertyNames * O??,Possibly indexed and/or nested name of the property to be modified,?? * <a href="../bean/BeanUtil.html#propertyName">propertyName</a> * @return <code>list</code> null, {@link Collections#emptyList()}<br> * @throws NullPointerException * <code>propertyNames</code> null * @throws IllegalArgumentException * <code>propertyNames</code> empty , null * @see BeanComparatorUtil#chainedComparator(String...) * @see org.apache.commons.collections4.ComparatorUtils#chainedComparator(java.util.Comparator...) * @see #sort(List, Comparator) */ public static <O> List<O> sort(List<O> list, String... propertyNames) { if (null == list) { return emptyList(); } Validate.notEmpty(propertyNames, "propertyNames can't be null/empty!"); Validate.noNullElements(propertyNames, "propertyName:%s has empty value", propertyNames); return sort(list, BeanComparatorUtil.chainedComparator(propertyNames)); } //************************************************************************************************* /** * ? <code>list</code>, <code>propertyName</code> ? <code>propertyValues</code> ?. * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * * User zhangfei = new User("", 23); * User guanyu = new User("", 30); * User liubei = new User("", 25); * List{@code <User>} list = toList(zhangfei, guanyu, liubei); * * List{@code <User>} select = CollectionsUtil.select(list, "name", "", ""); * Collections.sort(select, new PropertyComparator{@code <User>}("name", new FixedOrderComparator{@code <>}("", ""))); * LOGGER.debug(JsonUtil.formatWithIncludes(select, "name", "age")); * * </pre> * * ?: * * <pre class="code"> * * List{@code <User>} select2 = CollectionsUtil.select(list, "name", "", ""); * LOGGER.debug(JsonUtil.formatWithIncludes(SortUtil.sortByFixedOrderPropertyValues(select2, "name", "", ""), "name", "age")); * * </pre> * * <b>:</b> * * <pre class="code"> [{ "age": 25, "name": "" }, { "age": 30, "name": "" } ] * </pre> * * </blockquote> * * @param <O> * the generic type * @param <V> * the value type * @param list * the list * @param propertyName * O??,Possibly indexed and/or nested name of the property to be modified,?? * <a href="../bean/BeanUtil.html#propertyName">propertyName</a> * @param propertyValues * the property values * @return <code>list</code> null, {@link Collections#emptyList()}<br> * @throws NullPointerException * <code>propertyName</code> null * @throws IllegalArgumentException * <code>propertyName</code> blank * @see BeanComparatorUtil#propertyComparator(String, Object...) * @see #sort(List, Comparator) */ @SafeVarargs public static <O, V> List<O> sortByFixedOrderPropertyValues(List<O> list, String propertyName, V... propertyValues) { if (null == list) { return emptyList(); } Validate.notBlank(propertyName, "propertyName can't be blank!"); return sort(list, BeanComparatorUtil.propertyComparator(propertyName, propertyValues)); } /** * ? <code>list</code>, <code>propertyName</code> ? <code>propertyValues</code> ?. * * @param <O> * the generic type * @param <V> * the value type * @param list * the list * @param propertyName * O??,Possibly indexed and/or nested name of the property to be modified,?? * <a href="../bean/BeanUtil.html#propertyName">propertyName</a> * @param propertyValues * the property values * @return <code>list</code> null, {@link Collections#emptyList()}<br> * @throws NullPointerException * <code>propertyName</code> null * @throws IllegalArgumentException * <code>propertyName</code> blank * @see BeanComparatorUtil#propertyComparator(String, List) * @see #sort(List, Comparator) */ public static <O, V> List<O> sortByFixedOrderPropertyValues(List<O> list, String propertyName, List<V> propertyValues) { if (null == list) { return emptyList(); } Validate.notBlank(propertyName, "propertyName can't be blank!"); return sort(list, BeanComparatorUtil.propertyComparator(propertyName, propertyValues)); } //*******************************?**************************************************** /** * key asc??. * * <h3>:</h3> * <blockquote> * * <pre class="code"> * Map{@code <String, Comparable>} map = new HashMap{@code <String, Comparable>}(); * * map.put("a", 123); * map.put("c", 345); * map.put("b", 8); * * LOGGER.debug(JsonUtil.format(SortUtil.sortByKeyAsc(map))); * </pre> * * <b>:</b> * * <pre class="code"> * { * "a": 123, * "b": 8, * "c": 345 * } * </pre> * * </blockquote> * * <h3>?:</h3> * <blockquote> * <p> * ? {@link java.util.TreeMap#TreeMap(Map)},TreeMap?? keynull, ? <code>map</code>,keynull, * {@link NullPointerException} * </p> * </blockquote> * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return <code>map</code> null, {@link Collections#emptyMap()}<br> * ? {@link TreeMap} * @see java.util.TreeMap#TreeMap(Map) * @since 1.8.0 move from MapUtil */ public static <K, V> Map<K, V> sortByKeyAsc(Map<K, V> map) { if (null == map) { return emptyMap(); } return new TreeMap<K, V>(map); } /** * key desc ??. * * <h3>:</h3> * <blockquote> * * <pre class="code"> * Map{@code <String, Comparable>} map = new HashMap{@code <String, Comparable>}(); * * map.put("a", 123); * map.put("c", 345); * map.put("b", 8); * * LOGGER.debug(JsonUtil.format(SortUtil.sortByKeyDesc(map))); * </pre> * * <b>:</b> * * <pre class="code"> * { * "c": 345, * "b": 8, * "a": 123 * } * </pre> * * </blockquote> * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return <code>map</code> null, {@link Collections#emptyMap()}<br> * @see ReverseComparator#ReverseComparator(Comparator) * @see PropertyComparator#PropertyComparator(String) * @see #sort(Map, Comparator) * @since 1.8.0 move from MapUtil */ public static <K, V> Map<K, V> sortByKeyDesc(Map<K, V> map) { if (null == map) { return emptyMap(); } return sort(map, new ReverseComparator<Map.Entry<K, V>>(new PropertyComparator<Map.Entry<K, V>>("key"))); } /** * ?value ???(asc). * * <h3>:</h3> * <blockquote> * * <pre class="code"> * Map{@code <String, Comparable>} map = new HashMap{@code <String, Comparable>}(); * map.put("a", 123); * map.put("c", 345); * map.put("b", 8); * LOGGER.debug(JsonUtil.format(SortUtil.sortByValueAsc(map))); * </pre> * * <b>:</b> * * <pre class="code"> * { * "b": 8, * "a": 123, * "c": 345 * } * </pre> * * </blockquote> * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return <code>map</code> null, {@link Collections#emptyMap()}<br> * @see #sort(Map, Comparator) * @since 1.8.0 move from MapUtil */ public static <K, V extends Comparable<V>> Map<K, V> sortByValueAsc(Map<K, V> map) { if (null == map) { return emptyMap(); } return sort(map, new PropertyComparator<Map.Entry<K, V>>("value")); } /** * ?value ???(desc). * * <h3>:</h3> * <blockquote> * * <pre class="code"> * Map{@code <String, Comparable>} map = new LinkedHashMap{@code <String, Comparable>}(); * * map.put("a", 123); * map.put("c", 345); * map.put("b", 8); * * LOGGER.debug(JsonUtil.format(SortUtil.sortByValueDesc(map))); * </pre> * * <b>:</b> * * <pre class="code"> * { * "c": 345, * "a": 123, * "b": 8 * } * </pre> * * </blockquote> * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return <code>map</code> null, {@link Collections#emptyMap()}<br> * @see #sort(Map, Comparator) * @since 1.8.0 move from MapUtil */ public static <K, V extends Comparable<V>> Map<K, V> sortByValueDesc(Map<K, V> map) { if (null == map) { return emptyMap(); } return sort(map, new ReverseComparator<Map.Entry<K, V>>(new PropertyComparator<Map.Entry<K, V>>("value"))); } /** * {@link java.util.Map.Entry Entry} <code>mapEntryComparator</code> ? <code>map</code>?. * * <p> * {@link java.util.Map.Entry Entry}?, ?key??,?value?? * </p> * * <h3>:</h3> * <blockquote> * * map * * <pre class="code"> * Map{@code <String, Integer>} map = new HashMap{@code <String, Integer>}(); * * map.put("a13", 123); * map.put("a2", 345); * map.put("a8", 8); * </pre> * * ? : * * <pre class="code"> * LOGGER.debug(JsonUtil.format(SortUtil.sortByKeyAsc(map))); * </pre> * * <b>:</b> * * <pre class="code"> * { * "a13": 123, * "a2": 345, * "a8": 8 * } * </pre> * * ? a13?,? Comparator,?? * * <pre class="code"> * PropertyComparator{@code <Entry<String, Integer>>} propertyComparator = new PropertyComparator{@code <Map.Entry<String, Integer>>}( * "key", * new RegexGroupNumberComparator("a(\\d*)")); * LOGGER.debug(JsonUtil.format(SortUtil.sort(map, propertyComparator))); * </pre> * * <b>:</b> * * <pre class="code"> * { * "a2": 345, * "a8": 8, * "a13": 123 * } * </pre> * * </blockquote> * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @param mapEntryComparator * {@link java.util.Map.Entry Entry} {@link Comparator} * @return <code>map</code> null, {@link Collections#emptyMap()}<br> * <code>mapEntryComparator</code> null, {@link NullPointerException}<br> * @see java.util.Collections#sort(List, Comparator) * @since 1.8.0 move from MapUtil */ public static <K, V> Map<K, V> sort(Map<K, V> map, Comparator<Map.Entry<K, V>> mapEntryComparator) { if (null == map) { return emptyMap(); } Validate.notNull(mapEntryComparator, "mapEntryComparator can't be null!"); List<Map.Entry<K, V>> mapEntryList = toList(map.entrySet()); return toMap(sort(mapEntryList, mapEntryComparator)); } }