且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

java.util.ArrayList无法转换为java.lang.Comparable

更新时间:2022-10-19 16:59:11

反射是一种非常糟糕的方法。您在此代码中绝对没有类型安全。您不能保证实际上存在一个使用您提供的名称作为字符串的方法。您不能保证不接受任何参数。您不知道它将引发什么异常。



如果您使用Java 8 plus,则实现特定的比较器将是微不足道的:

  Comparator< Object>比较器= Comparator.comparing(Object :: toString); 

但是缺少Java 8功能并不是反思的原因。



定义一个抽象类:

 抽象类AbstractComparator< T,C扩展了Comparable< ;?超级C>实现Comparator< T> {
abstract C toComparable(T object);

@Override public int compare(T a,T b){
return toComparable(a).compareTo(toComparable(b));
}

比较器< T> reverse(){
返回新的Comparator< T>(){
@Override public int compare(T a,T b){
返回Comparable(b).compareTo(toComparable(a) );
}
}
}
}

然后针对您的特定情况实施此操作:

  Comparator< Object>比较器=新的AbstractComparator< Object,String> {
@Override String toComparable(Object object){return object.toString(); }
} .reverse();

如果您正在使用Guava或其他具有 Function功能的库$类似于c $ c>的类,或者很乐意自己定义它,您当然可以采用组合方法,而不是使用继承:

  Comparator< Object>比较器=新的ConcreteComparator<>(新函数< Object,String>(){
@Override public String apply(Object object){
return object.toString();
}
});

假设您在比较器或要比较的事物周围不使用原始类型, ClassCastException s现在将是不可能的。


I have UniversalComparator and it does all the task related to sorting, It uses reflection API to recognized the method name and invocatio target.

Now what happened is, I need to sort the sites, previously it was sorted using "name", now what happened is, user need to upload documents in frequency of monthly, quarterly,semi and annually.

REQUIREMENT

If document not uploaded in any of the frequency, that data represent with white color, rest of the blocks are reprsented as red color.

There are six SITES right now, first site has only one white block second site has no white block. third site has no white block four has three white block fifth has three white block sixth has three white block

so the count is 1 0 0 3 3

Now whta I did, I cretaed an ArrayList of Integer and store all the count now I need to sort the list of SITE Block on behalf of this count so it should be like

0 0 1 3 3

CODE

package com.lear.common.utility;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;



public class UniversalComparator implements Comparator {

    /**
     * static final int ASCENDING
     */
    public static final int ASCENDING = 1;

    /**
     * static final int DESCENDING
     */
    public static final int DESCENDING = -1;

    /*
     * int for descAscIndicator
     */
    private int descAscIndicator = 1;

    /*
     * String to store method Name
     */
    private String methodName = "toString";

    /**
     * Constructor for UniversalComparator
     * 
     * @param descAscIndicator
     *            int to store descAscIndicator.
     */
    public UniversalComparator(int descAscIndicator) {
        this.descAscIndicator = descAscIndicator;
    }

    /**
     * Constructor for UniversalComparator
     * 
     * @param methodName
     *            : name of method as criteria
     * @param descAscIndicator
     *            : order of sorting
     */
    public UniversalComparator(String methodName, int descAscIndicator) {
        this(descAscIndicator);
        this.methodName = methodName;
    }

    /**
     * This Method compare Two Objects
     * 
     * @param o1
     *            : An Instance of Object.
     * @param o2
     *            : An Instance of Object.
     * @return int
     */
    public int compare(Object o1, Object o2) {
        Object comp1 = null;
        Object comp2 = null;

        try {
            Method o1_Method = (o1.getClass()).getMethod(methodName, null);
            Method o2_Method = (o2.getClass()).getMethod(methodName, null);
            comp1 = o1_Method.invoke(o1, null);
            comp2 = o2_Method.invoke(o2, null);

        } catch (NoSuchMethodException e) {
            throw new RuntimeException("Method does not exist" + e.getMessage());
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Illegal access" + e.getMessage());
        } catch (InvocationTargetException e) {
            throw new RuntimeException("InvocationTargetException"
                    + e.getMessage());
        }
        Comparable c1 = (Comparable) comp1;
        Comparable c2 = (Comparable) comp2;
        return c1.compareTo(c2) * descAscIndicator;
    }

    /**
     * Check for Equality obect
     * 
     * @param obj
     *            : An Instance of Object.
     * @return boolean return true if equal or false if not
     */
    public boolean equals(Object obj) {
        return this.equals(obj);
    }
}

ScoreCardManager.java

List<Integer> naSiteDataList = new ArrayList<Integer>();

public String getComparativeSiteAnalysis(Integer divId, String lang, int selectedYear) {

// PLENTY OF CODE HERE
    int annualDataCount = site.getComparativeColorAnnual().equalsIgnoreCase("White") ? 1 : 0;
                naSiteDataCount = monthlyDataCount + quaterlyDataCount + semiAnnualDataCount + annualDataCount;
                naSiteDataList.add(naSiteDataCount);
                naSiteCounter.add(naSiteDataCount);
                site.setNaSiteCount(naSiteDataList);
                site.setNaSiteCounter(naSiteCounter);
                System.out.println("datacount is" + naSiteDataCount);
            }
          // THIS LINE
            Collections.sort(sites, new UniversalComparator("getNaSiteCount", 1));

Site.java

 public class Site{

// lot of properties

    private List<Integer> naSiteCount;

    public List<Integer> getNaSiteCount() {
            return naSiteCount;
        }

        public void setNaSiteCount(List<Integer> naSiteCount) {
            this.naSiteCount = naSiteCount;
        }

}

Reflection is a really awful approach to this. You have absolutely no type safety in this code. You have no guarantee that a method with the name you supply as a string actually exists. You have no guarantee that it takes no arguments. You have no idea what exceptions it might throw.

If you were working in Java 8 plus, it would be trivial to implement specific comparators:

Comparator<Object> comparator = Comparator.comparing(Object::toString);

but the lack of Java 8 features isn't a reason to do it with reflection.

Define an abstract class:

abstract class AbstractComparator<T, C extends Comparable<? super C>> implements Comparator<T> {
  abstract C toComparable(T object);

  @Override public int compare(T a, T b) {
    return toComparable(a).compareTo(toComparable(b));
  }

  Comparator<T> reverse() {
    return new Comparator<T>() {
      @Override public int compare(T a, T b) {
        return toComparable(b).compareTo(toComparable(a));
      }
    }
  }
}

and then implement this for your specific cases:

Comparator<Object> comparator = new AbstractComparator<Object, String> {
  @Override String toComparable(Object object) { return object.toString(); }
}.reverse();

If you are using Guava or some other library with a Function-like class, or are happy to define it yourself, you can of course take a compositional approach, rather than using inheritance:

Comparator<Object> comparator = new ConcreteComparator<>(new Function<Object, String>() {
  @Override public String apply(Object object) {
    return object.toString();
  }
});

Provided you don't use raw types around either the comparator or the things you are comparing, ClassCastExceptions will now be impossible.