Массив методов двоичного поиска Java

Я пытаюсь эффективно искать погоду, когда подкласс реализует метод, имя которого у меня есть в строке с именем _szMethodName. Я могу получить массив всех методов, которые реализует подкласс, выполнив Method[] _arrClassMethodsList = class.getMethods();. Затем я могу сравнить имя метода со строковым именем функции, которую я ищу, чтобы определить, будет ли класс реализовывать этот конкретный метод. В настоящее время у меня это работает в цикле for, но по мере роста подкласса это замедляется.

Для реализации цикла:

for (Method method : class.getMethods()){
       if(method.getName().equals(_szMethodName)){
          //method exists in subclass
          break;
      }
}

Массив методов из class.getMethods() отсортирован в алфавитном порядке.(Только в Java >=7). Я надеялся, что смогу использовать это, используя бинарный поиск или какую-либо другую оптимизацию массива вместо использования цикла for. Однако я еще не смог понять, как реализовать функцию бинарного поиска Java в массиве. Я пробовал использовать компаратор или сравнимый, но пока не добился успеха. Моя последняя реализация компаратора приведена ниже, но в ней есть ошибки, которые я еще не смог устранить.

Текущая попытка использования компаратора:

Comparator<Method> c = new Comparator <Method>() {
    public int compare(Method method, String string) {
        return method.getName().compareTo(string);
    }
};

Method[] _arrClassMethodsList = class.getMethods();
int index = Arrays.binarySearch(_arrClassMethodsList, _szMethodName, c);

Будем очень признательны за любую помощь или примеры того, как заставить эту работу работать. Спасибо!


person Krejko    schedule 20.02.2013    source источник


Ответы (2)


Почему бы вам не использовать метод http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getMethod%28java.lang.String,%20java.lang.Class...%29, чтобы напрямую получить метод, если он доступен, и позволить JVM эффективно выполнять эту работу за вас?

Кстати, в документации getMethods говорится: «Элементы в возвращаемом массиве не отсортированы и не в каком-либо конкретном порядке< /сильный>". Для бинарного поиска нужны отсортированные данные. Это означает, что вам сначала нужно отсортировать массив.

ПРИМЕЧАНИЕ: вам следует взглянуть на этот метод getMatchingAccessibleMethod, который, вероятно, делает то, что вы ожидаете.

person poussma    schedule 20.02.2013
comment
Это будет работать только для общедоступных методов. Для тех это звучит как разумный способ сделать это. - person tehlexx; 20.02.2013
comment
есть ли способ сделать это, не зная параметров, которые принимает метод? Все, что у меня есть, это строковое имя метода, который я ищу. - person Krejko; 20.02.2013
comment
Если я получу список параметров, есть ли способ получить их классы из него в массиве, чтобы перейти к «getMethod ()»? Я экспериментирую с одним из решений: Class _arrParameterClasses[]; для (Объект _oParameters: _arrParameters) {Class parameterClass = _oParameters.getClass(); _arrParameterClasses.add (класс параметров); } foundMethod = cl.getMethod(_szMethodName, _arrParameterClasses); (есть ли лучший способ дополнить комментарий блоком кода?) - person Krejko; 20.02.2013
comment
Это не так просто из-за полиморфизма. Если у вас есть метод sort(Collection c) и вы вызываете его с sort(new ArrayList<>()), getMethod(sort, new Class[]{ArrayList.class}) ничего не вернет, но будет работать, если параметры вызова метода точно соответствуют объявленным аргументам. посмотри мою заметку - person poussma; 20.02.2013

Казалось бы, единственный реальный способ сделать это — повторно реализовать двоичный поиск, извлекая имя метода во время поиска. Моя окончательная реализация ниже. Спасибо всем за помощь.

public final Method NOT_FOUND = null;
private Method findMethodInDelegateClassWithParameters (String _szMethodName)
{
    @SuppressWarnings("rawtypes")
    Class _cDelegateClass = m_oDelegate.getClass();

    //Get and sort array for binary search if not done, ensure methods are alphabetical before Java 7 
    if (_arrSortedMethods==null){
        _arrSortedMethods = _cDelegateClass.getMethods();   
        Arrays.sort(_arrSortedMethods, new Comparator<Method>() {
               public int compare(Method m1, Method m2) {
                   return m1.getName().compareTo(m2.getName());
               }
        });
    }

    return binarySearchForMethodNamed(_arrSortedMethods, _szMethodName);
}

public Method binarySearchForMethodNamed(Method[] _arrMethods, String _szMethodName) {
    int left = 0;
    int right = _arrMethods.length - 1;
    return binarySearchMethods(_arrMethods, _szMethodName, left, right);
    }

private Method binarySearchMethods(Method[] _arrMethods, String _szMethodName, int left, int right) {
    if (right < left) {
            return NOT_FOUND;
    }

    int mid = (left + right) >>> 1;
    String _szArrayMethodName = _arrMethods[mid].getName();
    if (_szMethodName.compareTo(_szArrayMethodName)>0) {
            return binarySearchMethods(_arrMethods, _szMethodName, mid + 1, right);
    } else if (_szMethodName.compareTo(_szArrayMethodName)<0) {
            return binarySearchMethods(_arrMethods, _szMethodName, left, mid - 1);
    } else {
            return _arrMethods[mid];
    }               
}
person Krejko    schedule 22.02.2013