Как оптимизировать этот вложенный цикл? - PullRequest
2 голосов
/ 22 февраля 2011

Я создал метод, который работает достаточно хорошо (занимает ~ 4 секунды) на моем компьютере.Однако конечный пользователь будет использовать этот метод в среде удаленного рабочего стола, где выполнение одного и того же запроса занимает от 25 до 50 секунд.Как я могу оптимизировать эту программу?

private void compareAndPopulateArrays(List<String> listOfGenIdsFromXml,
        List<String> listOfGenIdsFromDB, String dburl)
        throws ClassNotFoundException, SQLException {
    mdbAccessor = new MDBAccessor();
    for (int x = 0; x < listOfGenIdsFromXml.size(); x++) {
        Boolean matching_id_found = false;
        for (int y = 0; y < listOfGenIdsFromDB.size(); y++) {
            if (listOfGenIdsFromXml.get(x)
                    .equals(listOfGenIdsFromDB.get(y)) || equalsLanguageCodeIgnore(listOfGenIdsFromXml.get(x),listOfGenIdsFromDB.get(y))) {
                addNewMatchingRecognition(listOfGenIdsFromXml,
                        listOfGenIdsFromDB, dburl, x, y);
                matching_id_found = true;
            }
        }
        if (!(matching_id_found == true)) {
            newRecognitions.add(new NewRecognition(listOfGenIdsFromXml
                    .get(x)));
        }
    }
}
    private void addNewMatchingRecognition(List<String> listOfGenIdsFromXml,
        List<String> listOfGenIdsFromDB, String dburl, int x, int y)
        throws ClassNotFoundException, SQLException {
    String gen_id_Xml = listOfGenIdsFromXml.get(x);
    String gen_id_DB = listOfGenIdsFromDB.get(y);
    int issue_id = mdbAccessor.getIssueId(gen_id_DB, dburl);
    String issue_expression = mdbAccessor.getIssueExpression(gen_id_DB,
            dburl);
    String issue_detail = mdbAccessor.getIssueDetails(gen_id_DB, dburl);
    matchingRecognitions.add(new MatchingRecognition(gen_id_Xml, gen_id_DB,
            issue_id, issue_detail, issue_expression));
}

И все методы mdbAccessor выглядят примерно так:

public int getIssueId(String gen_id, String dburl) throws ClassNotFoundException,
        SQLException {
    Connection connection = setupConnection(dburl);
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement
            .executeQuery("SELECT issue_id FROM es_it WHERE gen_id='&&"
                    + gen_id + "' OR gen_id='&" + gen_id + "'");

    if (resultSet.next()){
        int getint = resultSet.getInt(1);
        resultSet.close();
        connection.close();
        return getint;
    }else{
        resultSet.close();
        connection.close();
        return -1;
    }
}

equalsLanguageCodeIgnore:

    public boolean equalsLanguageCodeIgnore(String gen_id, String gen_id_DB) {
    if (genIdsAreEqualMinusLanguageCode(gen_id, gen_id_DB)) {
        return true;
    } else {
        return false;
    }
}

private boolean genIdsAreEqualMinusLanguageCode(String gen_id,
        String gen_id_DB) {
    return gen_id_DB.contains("P-XX-")
            && gen_id.substring(5).equals(gen_id_DB.substring(5));
}

Новое и улучшенноеКласс MDBAccessor:

public class MDBAccessor {
private Connection connection;
private Statement statement;

public void setupConnection(String dburl)
        throws ClassNotFoundException, SQLException {
        connection = DriverManager
            .getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq="
                    + dburl);
        statement = connection.createStatement();
}

public void closeConnection() throws SQLException{
    connection.close();
}
////
public int getIssueId(String gen_id) throws ClassNotFoundException,
            SQLException {
        ResultSet resultSet = statement
                .executeQuery("SELECT issue_id FROM es_it WHERE gen_id='&&"
                        + gen_id + "' OR gen_id='&" + gen_id + "'");

        if (resultSet.next()){
            int getint = resultSet.getInt(1);
            resultSet.close();
            return getint;
        }else{
            resultSet.close();
            return -1;
        }
    }

Ответы [ 2 ]

5 голосов
/ 22 февраля 2011
  1. Получите предметы один раз и раздайте их, а не списки и индексы.Это ограничит количество поисков в списках, которые, как я ожидаю, довольно велики.В зависимости от вашей версии Java вы можете использовать конструкцию для каждого для удобства чтения.
  2. Я полагаю, вы можете объединить доступ к базе данных в один запрос, что позволит сохранитьвремя.

    int issue_id = mdbAccessor.getIssueId (gen_id_DB, dburl);String issue_expression = mdbAccessor.getIssueExpression (gen_id_DB, dburl);String issue_detail = mdbAccessor.getIssueDetails (gen_id_DB, dburl);

  3. Вы, похоже, открываете и закрываете DB для каждого запроса.Откройте его один раз и закройте в конце функции, так как открытие и закрытие соединения с БД обходится дорого (особенно в отношении Access IIRC).Скорее всего, вы захотите сделать объект подключения членом вашего класса MDBAccessor.Не забудьте использовать конструкцию try finally , чтобы убедиться, что она закрыта.


Рекомендуемый рефакторинг для удобства чтения

private void compareAndPopulateArrays(List<String> xmlGenIds,
        List<String> dbGenIds, String dbUrl)
        throws ClassNotFoundException, SQLException {
    //Better yet move it into an init method or the class constructor
    mdbAccessor = new MDBAccessor(dbUrl);
    for (String currXmlId : xmlGenIds) {
        Boolean matchingIdFound = false;
        for (String currDbId : dbGenIds) {
            if (currXmlId.equals(currDbId) || 
                    equalsLanguageCodeIgnore(currXmlId,currDbId)) {
                addNewMatchingRecognition(currDbId, currXmlId);
                matchingIdFound = true;
            }
        }
        if (!matchingIdFound) {
            newRecognitions.add(new NewRecognition(currDbId));
        }
    }
}
1 голос
/ 22 февраля 2011

Вы можете попытаться сделать несколько коротких из хэш-карты из listOfGenIdsFromDB и заменить внутренний цикл поиском по карте, это уменьшит необходимость многократной итерации по listOfGenIdsFromDB.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...