在 Java 中以通用方式实现可比较的方法进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18284636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:03:37  来源:igfitidea点击:

implementing comprable method in a generic way in Java for sorting

javasortinggenericscomparablecompareto

提问by brain storm

I am trying to implement a generic selection sort which can take any objects and do the sorting on it. I can promise to the compiler that whatever objects I am comparing, has the compareTo method implemented for it. But I get compile error for the following code

我正在尝试实现一个通用的选择排序,它可以接受任何对象并对其进行排序。我可以向编译器保证,无论我比较什么对象,都为它实现了 compareTo 方法。但是我收到以下代码的编译错误

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class SelectionSortGenerics implements Comparable<E> {

    private <E> void swap(E[] a, int i, int j) {
        if (i != j) {
            E temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }

    public <E> void selectionSort(E[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            // find index of smallest element
            int smallest = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[j].compareTo(a[smallest])<=0) {
                    smallest = j;
                }
            }

            swap(a, i, smallest);  // swap smallest to front
        }
    }

    public static void main(String[] args){
        SelectionSortGenerics firstsort = new SelectionSortGenerics();

        Integer[] arr = {3,4,1,5};
        System.out.println("before sorting int: "+ Arrays.toString(arr));
        firstsort.selectionSort(arr);
        System.out.println("After sorting int : "+Arrays.toString(arr));
         String[] arr1= {"acd","ded","dal","bad","cle"};
         System.out.println("before sorting String: "+ Arrays.toString(arr1));
         firstsort.selectionSort(arr1);
         System.out.println("After sorting String : "+Arrays.toString(arr1));
         Character[] arr2= {'c','e','a','d','c'};
         System.out.println("before sorting char: "+ Arrays.toString(arr2));
         firstsort.selectionSort(arr2);
         System.out.println("After sorting char : "+Arrays.toString(arr2));
    }
}

As you can see, the objects I am passing in main method are Integer, String and Character, which has compareTo methods. how would make the above code work. Anywhere, casting is needed? Thanks for your help.

如您所见,我在 main 方法中传递的对象是 Integer、String 和 Character,它们具有 compareTo 方法。如何使上述代码工作。任何地方都需要铸造?谢谢你的帮助。

采纳答案by Antimony

The following works for me. All I did was remove the <E>in the class declaration and changed <E>to <E extends Comparable<E>>in selectionSort.

以下对我有用。我所做的只是删除<E>类声明中的 并更改<E><E extends Comparable<E>>selectionSort 。

The generic <E>in the class declaration is unnecessary and potentially confusing since your class doesn't actually need to be generic. Only the methods in the class are generic, not the class itself.

<E>类声明中的泛型是不必要的并且可能会造成混淆,因为您的类实际上并不需要是泛型的。只有类中的方法是通用的,而不是类本身。

Second, the selectionSort method requires the element type passed in to be comparable to itself. You can represent this by E extends Comparable<E>.

其次, selectionSort 方法要求传入的元素类型与其自身具有可比性。你可以用 来表示E extends Comparable<E>

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class SelectionSortGenerics {

    private <E> void swap(E[] a, int i, int j) {
        if (i != j) {
            E temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }

    public <E extends Comparable<E>> void selectionSort(E[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            // find index of smallest element
            int smallest = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[j].compareTo(a[smallest])<=0) {
                    smallest = j;
                }
            }

            swap(a, i, smallest);  // swap smallest to front
        }
    }

    public static void main(String[] args){
        SelectionSortGenerics firstsort = new SelectionSortGenerics();

        Integer[] arr = {3,4,1,5};
        System.out.println("before sorting int: "+ Arrays.toString(arr));
        firstsort.selectionSort(arr);
        System.out.println("After sorting int : "+Arrays.toString(arr));
         String[] arr1= {"acd","ded","dal","bad","cle"};
         System.out.println("before sorting String: "+ Arrays.toString(arr1));
         firstsort.selectionSort(arr1);
         System.out.println("After sorting String : "+Arrays.toString(arr1));
         Character[] arr2= {'c','e','a','d','c'};
         System.out.println("before sorting char: "+ Arrays.toString(arr2));
         firstsort.selectionSort(arr2);
         System.out.println("After sorting char : "+Arrays.toString(arr2));
    }
}

回答by Vikas Chowdhury

 **Refer below method to implement generic sorting.You just have to pass list in sortElements    and  the name of the field on you want to enable sorting**
 /**
 * This method is used to sort the elements based on the fieldName specified.
 * Sorting order is Ascending order.
 * 
 * @param resultList
 *            e.g., List of ProductBrand
 * @param fieldName
 *            e.g., productBrandName list will be sorted according to this
 *            fieldName.
 * @throws Exception
 */
public static <Type> void sortElements(List<Type> resultList, final String fieldName, final boolean isDesc) throws Exception
{
  Collections. sort(resultList, new Comparator<Type>()
  {
          @Override
          public int compare(Type o1, Type o2)
         {
                return compareValue(o1, o2);
         }

          private int compareValue(Type o1, Type o2)
         {
                int returnValue = 0;
                try
               {
                      Field field = o1.getClass().getDeclaredField(fieldName);
                       boolean accessible = field.isAccessible();
                      field.setAccessible( true);
                      Object objectO1 = field.get(o1);
                      Object objectO2 = field.get(o2);
                       if (objectO1 instanceof Number)
                      {
                              if ((objectO1 != null && objectO2 != null)
                                           && (objectO1 instanceof Integer || objectO1 instanceof Long || objectO1 instanceof Byte))
                             {
                                    returnValue = Long.valueOf(objectO1 + "").compareTo(Long. valueOf(objectO2 + ""));
                             }
                              else if ((objectO1 != null && objectO2 != null) && (objectO1 instanceof Double || objectO1 instanceof Float))
                             {

                                    returnValue = Double.valueOf(objectO1 + "").compareTo(Double. valueOf(objectO2 + ""));

                             }
                      }
                       else if (objectO1 instanceof String || objectO1 instanceof Character)
                      {
                              if ((objectO1 != null) && objectO2 != null)
                             {
                                    returnValue = normalizedString(String.valueOf(objectO1)).compareToIgnoreCase(
                                                   normalizedString(String.valueOf(objectO2)));
                             }
                      }
                      field.setAccessible(accessible);
               }
                catch (Exception e)
               {
                      System. out.println("Error occured while sorting elements");
               }

                if (isDesc)
               {
                       if (returnValue > 0)
                      {
                              return -1;
                      }
                       else if (returnValue < 0)
                      {
                              return 1;
                      }
               }
                return returnValue;
         }
  });

}

}

 /**
 * This methods Normalizes the input string. Here we remove accent from the
 * character so that we can sort the string properly using normal characters.
 * 
 * @param str
 *            example <B> BSH Electrodom?sticos Espa?a S.A. </b>
 * @return Normalized String . <B> ex : BSH Electrodomesticos Espana S.A.</b>
 * 
 */
 public static String normalizedString(String str)
 {
   if (!isNullOrBlank(str))
  {
         String nfdNormalizedString = Normalizer. normalize(str, Normalizer.Form.NFD );
         Pattern pattern = Pattern.compile("\p{InCombiningDiacriticalMarks}+");
          return pattern.matcher(nfdNormalizedString).replaceAll("");
  }
   else
  {
          return "" ;
  }
 }

 /**
 * This function checks that the value is blank or null.
 * 
 * @param value
 *            value to be checked
 * @return true if value is blank or null
 */
 public static boolean isNullOrBlank(String value)
 {
   boolean retFlag = false;
   if (value == null || value.trim().equals("") || value.trim().equals("null" ))
  {
         retFlag = true;
  }
   return retFlag;
 }