java.util.ArrayList无法转换为java.lang.Comparable [英] java.util.ArrayList cannot be cast to java.lang.Comparable

查看:188
本文介绍了java.util.ArrayList无法转换为java.lang.Comparable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有UniversalComparator,它完成了所有与排序有关的任务,它使用反射API来识别方法名称和调用目标。



现在发生了什么事,我需要对网站进行排序,以前它是使用 name 进行排序的,现在发生的是,用户需要上传

需求



如果未以任何频率上载文档,则该数据以白色颜色表示,其余块表示为红色

现在有六个SITES,
第一个站点只有一个白色块,
第二个站点没有白色块。
第三个站点没有白块
四个有三个白块
第五个有三个白块
第六个有三个白块



所以计数是
1
0
0
3
3



现在我做了吗,我创建了一个ArrayList of Integer并存储了所有计数
现在我需要代表该计数对SITE Block列表进行排序,所以它应该像



0
0
1
3
3



CODE

 包com.lear.common.utility; 

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



公共类UniversalComparator实现比较器{

/ **
*静态最终int升序
* /
public static final int ASCENDING = 1;

/ **
*静态最终int降序
* /
公共静态最终ins降序= -1;

/ *
* descAscIndicator的整数
* /
private int descAscIndicator = 1;

/ *
*存储方法名称的字符串
* /
private字符串methodName = toString;

/ **
* UniversalComparator的构造函数
*
* @param descAscIndicator
*用于存储descAscIndicator的int。
* /
public UniversalComparator(int descAscIndicator){
this.descAscIndicator = descAscIndicator;
}

/ **
* UniversalComparator的构造函数
*
* @param methodName
*:方法的名称作为条件
* @param descAscIndicator
*:排序顺序
* /
public UniversalComparator(String methodName,int descAscIndicator){
this(descAscIndicator);
this.methodName = methodName;
}

/ **
*此方法比较两个对象
*
* @param o1
*:对象的实例。
* @param o2
*:对象的实例。
* @return int
* /
public int compare(Object o1,Object o2){
Object comp1 = null;
对象comp2 = null;

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

} catch(NoSuchMethodException e){
抛出新的RuntimeException(方法不存在 + e.getMessage());
} catch(IllegalAccessException e){
抛出新的RuntimeException(非法访问 + e.getMessage());
} catch(InvocationTargetException e){
throw new RuntimeException( InvocationTargetException
+ e.getMessage());
}
Comparable c1 =(Comparable)comp1;
可比较c2 =(可比较)comp2;
return c1.compareTo(c2)* descAscIndicator;
}

/ **
*检查是否相等
*
* @param obj
*:对象的实例。
* @return boolean return true等于或否则返回
* /
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){

//此处有很多代码
int AnnualDataCount = site.getComparativeColorAnnual()。equalsIgnoreCase (白色)? 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);
}
//这条线
Collections.sort(sites,new UniversalComparator( getNaSiteCount,1));

Site.java

 公共类站点{

//很多物业

私有列表< Integer> naSiteCount;

公共列表< Integer> getNaSiteCount(){
return naSiteCount;
}

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

}

解决方案

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



如果您使用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功能的库的类,或者很乐意自己定义它,您当然可以采用组合方法,而不是使用继承:

  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.

这篇关于java.util.ArrayList无法转换为java.lang.Comparable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆