Как протестировать, соответствует ли тип возврата метода Списку <Строка>

Ответ, предоставленный rcs, работает и прост. Однако, если вы работаете с большими наборами данных и нуждаетесь в повышении производительности, существует более быстрая альтернатива:

library(data.table)
data = data.table(Category=c("First","First","First","Second","Third", "Third", "Second"), 
                  Frequency=c(10,15,5,2,14,20,3))
data[, sum(Frequency), by = Category]
#    Category V1
# 1:    First 30
# 2:   Second  5
# 3:    Third 34
system.time(data[, sum(Frequency), by = Category] )
# user    system   elapsed 
# 0.008     0.001     0.009 

Давайте сравним это с тем же, используя data.frame и выше:

data = data.frame(Category=c("First","First","First","Second","Third", "Third", "Second"),
                  Frequency=c(10,15,5,2,14,20,3))
system.time(aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum))
# user    system   elapsed 
# 0.008     0.000     0.015 

И если вы хотите сохранить столбец, это синтаксис:

data[,list(Frequency=sum(Frequency)),by=Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34

Разница станет более заметной с более крупными наборами данных, как показывает следующий код:

data = data.table(Category=rep(c("First", "Second", "Third"), 100000),
                  Frequency=rnorm(100000))
system.time( data[,sum(Frequency),by=Category] )
# user    system   elapsed 
# 0.055     0.004     0.059 
data = data.frame(Category=rep(c("First", "Second", "Third"), 100000), 
                  Frequency=rnorm(100000))
system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
# user    system   elapsed 
# 0.287     0.010     0.296 

Для множественных агрегаций вы можете комбинировать lapply и .SD следующим образом

data[, lapply(.SD, sum), by = Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34
15
задан Michal 9 October 2008 в 08:26
поделиться

4 ответа

Решение этого в целом действительно не легко сделать себя с помощью только инструменты, обеспеченные самим Java. Существует много особых случаев (вложенные классы, введите границы параметра...) заботиться о. Вот почему я записал библиотеку для создания универсального отражения типа легче: gentyref. Я добавил пример кода (в форме теста JUnit), чтобы показать, как использовать его для решения этой проблемы: StackoverflowQ182872Test.java. В основном Вы просто звоните GenericTypeReflector.isSuperType использование TypeToken (идея от Neil Gafter ), чтобы видеть, ли List<String> супертип типа возврата.

я также добавил 5-й тестовый сценарий, чтобы показать, что дополнительное преобразование на типе (GenericTypeReflector.getExactReturnType) возврата для замены параметров типа их значениями иногда необходимо.

4
ответ дан 1 December 2019 в 04:41
поделиться

Этот поток на форумах java.net мог бы быть полезным (хотя я должен признать, что не понял все, что они сказали).

0
ответ дан 1 December 2019 в 04:41
поделиться

Я попробовал этот код, и он возвращает фактический универсальный класс типа, таким образом, кажется, что информация о типе может быть получена. Однако это только работает на метод 1 и 2. Метод 3, кажется, не возвращается, список ввел Строку, как плакат предполагает и поэтому перестал работать.

public class Main {
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    try{
        Method m = Main.class.getDeclaredMethod("method1", new Class[]{});
        instanceOf(m, List.class, String.class);
        m = Main.class.getDeclaredMethod("method2", new Class[]{});
        instanceOf(m, List.class, String.class);
        m = Main.class.getDeclaredMethod("method3", new Class[]{});
        instanceOf(m, List.class, String.class);
        m = Main.class.getDeclaredMethod("method4", new Class[]{});
        instanceOf(m, StringList.class);
    }catch(Exception e){
        System.err.println(e.toString());
    }
}

public static boolean instanceOf (
        Method m, 
        Class<?> returnedBaseClass, 
        Class<?> ... genericParameters) {
    System.out.println("Testing method: " + m.getDeclaringClass().getName()+"."+ m.getName());
    boolean instanceOf = false;
    instanceOf = returnedBaseClass.isAssignableFrom(m.getReturnType());
    System.out.println("\tReturn type test succesfull: " + instanceOf + " (expected '"+returnedBaseClass.getName()+"' found '"+m.getReturnType().getName()+"')");
    System.out.print("\tNumber of generic parameters matches: ");
    Type t = m.getGenericReturnType();
    if(t instanceof ParameterizedType){
        ParameterizedType pt = (ParameterizedType)t;
        Type[] actualGenericParameters = pt.getActualTypeArguments();
        instanceOf = instanceOf
            && actualGenericParameters.length == genericParameters.length;
        System.out.println("" + instanceOf + " (expected "+ genericParameters.length +", found " + actualGenericParameters.length+")");
        for (int i = 0; instanceOf && i < genericParameters.length; i++) {
            if (actualGenericParameters[i] instanceof Class) {
                instanceOf = instanceOf
                        && genericParameters[i].isAssignableFrom(
                            (Class) actualGenericParameters[i]);
                System.out.println("\tGeneric parameter no. " + (i+1) + " matches: " + instanceOf + " (expected '"+genericParameters[i].getName()+"' found '"+((Class) actualGenericParameters[i]).getName()+"')");
            } else {
                instanceOf = false;
                System.out.println("\tFailure generic parameter is not a class");
            }
        }
    } else {
        System.out.println("" + true + " 0 parameters");
    }
    return instanceOf;
}
public List<String> method1() {
    return null;
}
public ArrayList<String> method2() {
    return new ArrayList<String>();
}
public StringList method3() {
    return null;
}
public <T extends StringList> T method4() {
    return null;
}

Это производит:

Testing method: javaapplication2.Main.method1
        Return type test succesfull: true (expected 'java.util.List' found 'java.util.List')
        Number of generic parameters matches: true (expected 1, found 1)
        Generic parameter no. 1 matches: true (expected 'java.lang.String' found 'java.lang.String')
Testing method: javaapplication2.Main.method2
        Return type test succesfull: true (expected 'java.util.List' found 'java.util.ArrayList')
        Number of generic parameters matches: true (expected 1, found 1)
        Generic parameter no. 1 matches: true (expected 'java.lang.String' found 'java.lang.String')
Testing method: javaapplication2.Main.method3
        Return type test succesfull: false (expected 'java.util.List' found 'com.sun.org.apache.xerces.internal.xs.StringList')
        Number of generic parameters matches: true 0 parameters
Testing method: javaapplication2.Main.method4
        Return type test succesfull: true (expected 'com.sun.org.apache.xerces.internal.xs.StringList' found 'com.sun.org.apache.xerces.internal.xs.StringList')
        Number of generic parameters matches: true 0 parameters
9
ответ дан 1 December 2019 в 04:41
поделиться

Я думаю, что Вы уже на правильном пути. Просто продолжайте использовать getGenericSuperclass () и getGenericInterface (), пока Вы не начнете возвращать параметризованные типы...

Так в основном:

//For string list
ParameterizedType type = (ParameterizedType)StringList.class.getGenericSuperclass();
System.out.println( type.getActualTypeArguments()[0] );

//for a descendant of string list
Class clazz = (Class)StringListChild.class.getGenericSuperclass();
ParameterizedType type = (ParameterizedType)clazz.getGenericSuperclass();
System.out.println( type.getActualTypeArguments()[0] );

Вы хотели бы создать что-то, что было рекурсивно, который проверит на это - возможно, даже повышаются цепочка, ища java.util. Список.

0
ответ дан 1 December 2019 в 04:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: