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