Supondo que eu tenho um ArrayList
ArrayList<MyClass> myList;
E eu quero ligar para oArray, existe uma razão de desempenho para usar
MyClass[] arr = myList.toArray(new MyClass[myList.size()]);
sobre
MyClass[] arr = myList.toArray(new MyClass[0]);
?
Eu prefiro o segundo estilo, já que é menos detalhado, e presumi que o compilador garantirá que a matriz vazia não seja realmente criada, mas estou pensando se isso é verdade.
Obviamente, em 99% dos casos, não faz diferença de uma maneira ou de outra, mas eu gostaria de manter um estilo consistente entre meu código normal e meus loops internos otimizados ...
java
performance
coding-style
itsadok
fonte
fonte
Respostas:
Por outro lado, a versão mais rápida, no Hotspot 8, é:
Eu executei um micro benchmark usando jmh, os resultados e o código estão abaixo, mostrando que a versão com uma matriz vazia supera consistentemente a versão com uma matriz presized. Observe que, se você puder reutilizar uma matriz existente do tamanho correto, o resultado poderá ser diferente.
Resultados de benchmark (pontuação em microssegundos, menor = melhor):
Para referência, o código:
Você pode encontrar resultados semelhantes, análise completa e discussão na publicação do blog Matrizes de Sabedoria dos Antigos . Para resumir: o compilador JVM e JIT contém várias otimizações que permitem criar e inicializar de maneira barata uma nova matriz de tamanho correto e essas otimizações não podem ser usadas se você mesmo criar a matriz.
fonte
MyClass[] arr = myList.stream().toArray(MyClass[]::new);
.. que eu acho que seriam mais lentos. Além disso, gostaria de ver referências para a diferença com a declaração de matriz. Como na diferença entre:MyClass[] arr = new MyClass[myList.size()]; arr = myList.toArray(arr);
eMyClass[] arr = myList.toArray(new MyClass[myList.size()]);
... ou não deve haver nenhuma diferença? Eu acho que esses dois são um problema que está fora dostoArray
acontecimentos das funções. Mas ei! Não achei que aprenderia sobre outras diferenças complexas.toArray
diretamente (quanto menor o tamanho, maior a sobrecarga relativa)A partir do ArrayList no Java 5 , o array já estará preenchido se tiver o tamanho certo (ou for maior). Consequentemente
criará um objeto de matriz, preencha-o e retorne-o para "arr". Por outro lado
criará duas matrizes. O segundo é uma matriz de MyClass com comprimento 0. Portanto, há uma criação de objeto para um objeto que será descartado imediatamente. Na medida em que o código-fonte sugere, o compilador / JIT não pode otimizar este para que ele não seja criado. Além disso, o uso do objeto de comprimento zero resulta em conversão (ões) dentro do método toArray () -.
Veja a fonte de ArrayList.toArray ():
Use o primeiro método para que apenas um objeto seja criado e evite vazamentos (implícitos, porém caros).
fonte
new Myclass[0]
é mais rápido: shipilev.net/blog/2016/arrays-wisdom-ancientsNa inspeção JetBrains Intellij Idea:
fonte
As JVMs modernas otimizam a construção de matriz reflexiva nesse caso, portanto a diferença de desempenho é pequena. Nomear a coleção duas vezes nesse código padrão não é uma boa idéia, portanto, evitaria o primeiro método. Outra vantagem do segundo é que ele trabalha com coleções sincronizadas e simultâneas. Se você quiser otimizar, reutilize a matriz vazia (matrizes vazias são imutáveis e podem ser compartilhadas) ou use um criador de perfil (!).
fonte
private static final MyClass[] EMPTY_MY_CLASS_ARRAY = new MyClass[0]
não impede a matriz retornada de ser construído por reflexão, mas não impedir que um conjunto adicional a ser construído cada cada vez.MyClass[] arr = myList.stream().toArray(MyClass[]::new);
Ajudaria ou prejudicaria as coleções sincronizadas e simultâneas. E porque? Por favor.O toArray verifica se a matriz passada é do tamanho certo (ou seja, grande o suficiente para caber nos elementos da sua lista) e, se sim, usa isso. Consequentemente, se o tamanho da matriz for menor que o necessário, uma nova matriz será criada reflexivamente.
No seu caso, uma matriz de tamanho zero é imutável; portanto, ela pode ser elevada com segurança a uma variável final estática, o que pode tornar seu código um pouco mais limpo, o que evita a criação da matriz em cada chamada. Uma nova matriz será criada dentro do método de qualquer maneira, portanto é uma otimização de legibilidade.
Indiscutivelmente, a versão mais rápida é passar a matriz com um tamanho correto, mas, a menos que você possa provar que esse código é um gargalo de desempenho, prefira a legibilidade ao tempo de execução, até que seja provado o contrário.
fonte
O primeiro caso é mais eficiente.
Isso ocorre porque no segundo caso:
o tempo de execução realmente cria uma matriz vazia (com tamanho zero) e, em seguida, dentro do método toArray cria outra matriz para ajustar os dados reais. Essa criação é feita usando reflexão usando o seguinte código (extraído de jdk1.5.0_10):
Ao usar o primeiro formulário, você evita a criação de uma segunda matriz e também o código de reflexão.
fonte
O segundo é marginalmente mais legível, mas há tão pouca melhoria que não vale a pena. O primeiro método é mais rápido, sem desvantagens no tempo de execução, e é isso que eu uso. Mas eu escrevo da segunda maneira, porque é mais rápido digitar. Em seguida, meu IDE o sinaliza como um aviso e se oferece para corrigi-lo. Com um único toque de tecla, ele converte o código do segundo tipo para o primeiro.
fonte
Usar 'toArray' com a matriz do tamanho correto terá um desempenho melhor, pois a alternativa criará primeiro a matriz com tamanho zero e depois a matriz com o tamanho correto. No entanto, como você diz, a diferença provavelmente será insignificante.
Além disso, observe que o compilador javac não executa nenhuma otimização. Atualmente, todas as otimizações são executadas pelos compiladores JIT / HotSpot em tempo de execução. Não conheço nenhuma otimização em torno de 'toArray' em nenhuma JVMs.
A resposta para sua pergunta, portanto, é basicamente uma questão de estilo, mas por uma questão de consistência deve fazer parte de todos os padrões de codificação aos quais você adere (documentado ou não).
fonte
código de amostra para inteiro:
fonte