2016-06-08 4 views
0

Итак, я старался максимально оптимизировать свой код. Следующий код, используемый для запуска на 5 секунд, однако мне удалось уменьшить его до примерно 1,4 секунды, однако его все еще недостаточно. Что я могу сделать, чтобы оптимизировать этот код еще больше? (Возможно, я должен упомянуть, что время, о котором я говорил, происходит, когда aux Map заканчивается 170080 ключами).оптимизация java 8 потоков операций

public List<String> getProdutosMaisCompradosQuantidade(int filial, int X){ 
    Map<String, ProdutoFilial> aux; 

    if(filial==0) { 
     aux = new HashMap<>(ValoresFixos.CATALOGO_PRODUTOS_TAMANHO_INICIAL); 
     filiais.stream() 
       .forEach((f) -> { 
        Map<String, ProdutoFilial> aux2 = f.getMapProdutosDadosFilialSemEncapsulamento(); 
        aux2.forEach((k,t) -> { 
          if(t.getQuantidade()>0){ 
           if(aux.containsKey(k)) aux.get(k).atualizarValores(t); 
           else aux.put(k,t); 
          } 
        }); 
       }); 
    } 
    else aux = filiais.get(filial-1).getMapProdutosDadosFilialSemEncapsulamento(); 

    List<String> list = 
     aux 
     .entrySet() 
     .stream() 
     .sorted(new ComparadorProdutoQuantidade()) 
     .map(e -> e.getKey()+"\n  | o Quantidade: "+e.getValue().getQuantidade()+"; Comprado por "+e.getValue().getNumeroCompradores()+" Clientes Distintos") 
     .collect(Collectors.toList()); 

    if(X>list.size()) X = list.size(); 
    list.subList(X, list.size()).clear(); 

    return list; 

} 

Все методы, которые я использую здесь почти O (1) сложность и компаратор не слишком налогообложения либо так, что не должно быть проблемой, есть то, что я не знаю, что может помочь мне оптимизировать этот поток операций? Возможно, можно использовать элемент entrySet, который я использую ...? Потому что это, вероятно, самая дорогая операция здесь ...

EDIT1: Может быть, я должен объяснить идею этого метода. Это главная цель состоит в том, чтобы заказать карту всп и возвращает список с ключами упорядоченными (ключи также изменены, но это не главная цель)

+0

Вы говорите о «заказе» ключей, но 'aux' - это HashMap, и у них нет определенного порядка. Вы думали о том, чтобы распараллелить все, используя, например, 'parallelStream()' вместо 'stream()'? Если вы не забудете синхронизацию 'aux'. – Robert

+0

O (1) только означает, что он не масштабируется с размером ввода. Например, для всех может потребоваться целый год. И для оптимизации нескольких секунд эти постоянные разницы во времени имеют черту различия (а иногда O (что-то большее, чем 1) на практике еще быстрее - обычно массивы и связанные структуры объектов). PS: было бы очень полезно, если бы вы перевели свой код, понимая, насколько валоры и produtos связаны друг с другом, намного легче понять ваш алгоритм или что это значит. – zapl

ответ

1

Вы могли бы попытаться заменить forEach заявления с map и collect, как описано в Java 8 - Best way to transform a list: map or foreach?

Тогда вы можете попробовать, если использование параллельного потока улучшает вашу производительность.

Возможно, вы можете заменить свою инструкцию, которая создает карту aux с помощью Stream API (с использованием Collectors.toMap и/или Collectors.groupingBy). Это считается более чистым, чем использование forEach, которое использует операции с сохранением состояния.

Есть уже достаточно много вопросов о том, как сделать это https://stackoverflow.com/search?q=groupingBy+[java-stream] или https://stackoverflow.com/search?q=toMap+[java-stream]

Если вам нужно быстрее решение (с меньшим количеством изменений), вы могли бы попытаться заменить Map с ConcurrentHashMap и использовать параллельно поток. Вы можете использовать its merge function, чтобы сделать ваши вычисления параллелизуемыми.

+0

Я пытался использовать Collectors вместо forEach, но я не мог найти способ сделать это так, как я притворяюсь, поэтому я попытался использовать parallelSetream, созданный потоком, и это было просто потрясающе, использовало его на остальной части моего кода и делало все более чем на пару секунд быстрее, как если бы это было ничто, я действительно удивлен и удивлен. Однако я хочу удостовериться, что я не испортил, я использую concurrentHashMaps, когда могу, и использую зарезервированное слово, синхронизированное по методам, которые действительно нельзя назвать одновременно, но есть ли что-нибудь еще, о чем я должен беспокоиться? –

+0

А также существует ли опасность использования параллельных потоков с помощью ArrayLists или HashSets? Пока я просто хочу получить доступ к данным и не изменять их –

+0

@ sharp_c-tudent: при использовании 'ConcurrentHashMap', это должно быть нормально, если вы используете атомарные операции, такие как merge. Что касается ограничений параллельных потоков, см. Http: // stackoverflow.com/questions/21163108/custom-thread-pool-in-java-8-parallel-stream – user140547

Смежные вопросы