Quero criar uma nova matriz de objetos juntando duas matrizes menores.
Eles não podem ser nulos, mas o tamanho pode ser 0.
Não posso escolher entre essas duas maneiras: são equivalentes ou é mais eficiente (por exemplo, system.arraycopy () copia pedaços inteiros)?
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
System.arraycopy(publicThings, 0, things, 0, publicThings.length);
System.arraycopy(privateThings, 0, things, publicThings.length, privateThings.length);
ou
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
for (int i = 0; i < things.length; i++) {
if (i<publicThings.length){
things[i] = publicThings[i]
} else {
things[i] = privateThings[i-publicThings.length]
}
}
A única diferença é a aparência do código?
EDITAR: obrigado pela pergunta vinculada, mas eles parecem ter uma discussão não resolvida:
É realmente mais rápido se it is not for native types
: byte [], Object [], char []? em todos os outros casos, uma verificação de tipo é executada, qual seria o meu caso e, portanto, seria equivalente ... não?
Em outra pergunta vinculada, eles dizem que the size matters a lot
, para tamanho> 24, ganha system.arraycopy (), para menos de 10, manual para loop é melhor ...
Agora estou realmente confuso.
arraycopy()
é uma chamada nativa, que certamente é mais rápida.Respostas:
Eu sei que os testes JUnit não são realmente os melhores para benchmarking, mas
testHardCopyBytes levou 0,157s para ser concluído
e
testArrayCopyBytes levou 0,086s para ser concluído.
Acho que depende da máquina virtual, mas parece que ela copia blocos de memória em vez de copiar elementos de array único. Isso aumentaria absolutamente o desempenho.
EDIT:
Parece que o desempenho de System.arraycopy está em todo lugar. Quando Strings são usados em vez de bytes e as matrizes são pequenas (tamanho 10), obtenho estes resultados:
Aqui está o que parece quando os arrays estão no tamanho 0x1000000. Parece que System.arraycopy definitivamente vence com arrays maiores.
Que peculiar!
Obrigado, Daren, por apontar que as referências são copiadas de maneira diferente. Isso tornou esse problema muito mais interessante!
fonte
Arrays.copyOf(T[], int)
é mais fácil de ler. Internamente, ele usa oSystem.arraycopy()
que é uma chamada nativa.Você não pode obter isso mais rápido!
fonte
copyOf
nem sempre pode substituirarraycopy
, mas é apropriado para este caso de uso.Depende da máquina virtual, mas System.arraycopy deve fornecer o mais próximo que você pode obter do desempenho nativo.
Eu trabalhei por 2 anos como um desenvolvedor Java para sistemas embarcados (onde o desempenho é uma grande prioridade) e em todos os lugares que System.arraycopy poderia ser usado, eu o usei / vi principalmente em código existente. É sempre preferível a loops quando o desempenho é um problema. Se o desempenho não for um grande problema, eu iria com o loop. Muito mais fácil de ler.
fonte
Arrays.copy
não existe,Arrays.copyOf
é uma função de biblioteca.Em vez de depender de especulações e informações possivelmente desatualizadas, executei alguns benchmarks usando compasso de calibre. Na verdade, o Caliper vem com alguns exemplos, incluindo um
CopyArrayBenchmark
que mede exatamente essa questão! Tudo que você precisa fazer é correrMeus resultados são baseados no servidor VM de 64 bits Java HotSpot (TM) da Oracle, 1.8.0_31-b13, rodando em um MacBook Pro de meados de 2010 (macOS 10.11.6 com Intel Arrandale i7, 8 GiB de RAM). Não acredito que seja útil postar os dados de tempo brutos. Em vez disso, resumirei as conclusões com as visualizações de apoio.
Em suma:
for
loop manual para copiar cada elemento em um array recém-instanciado nunca é vantajoso, seja para arrays curtos ou longos.Arrays.copyOf(array, array.length)
earray.clone()
ambos são consistentemente rápidos. Essas duas técnicas são quase idênticas em desempenho; qual você escolher é uma questão de gosto.System.arraycopy(src, 0, dest, 0, src.length)
é quase tão rápido quanto e , mas não de forma consistente. (Veja o caso para 50000 s.) Por causa disso, e da verbosidade da chamada, eu recomendaria se você precisar de um controle fino sobre quais elementos são copiados e onde.Arrays.copyOf(array, array.length)
array.clone()
int
System.arraycopy()
Aqui estão os gráficos de tempo:
fonte
A execução de métodos nativos
Arrays.copyOf(T[], int)
tem alguma sobrecarga, mas não significa que não seja rápida porque você a executa usando JNI.A maneira mais fácil é escrever um benchmark e um teste.
Você pode verificar se
Arrays.copyOf(T[], int)
é mais rápido do que seufor
loop normal .O código de referência daqui : -
System.arraycopy()
usa JNI (Java Native Interface) para copiar um array (ou partes dele), por isso é extremamente rápido, como você pode confirmar aquifonte
System.arraycopy
não usa.System.arraycopy
não usa JNI, que é apenas para chamar bibliotecas de terceiros. Em vez disso, é uma chamada nativa, o que significa que há uma implementação nativa na VM para ela.Não é possível que
Arrays.copyOf
seja mais rápido do que,System.arraycopy
pois esta é a implementação decopyOf
:fonte
System.arraycopy()
é uma chamada nativa que copia a operação diretamente na memória. A cópia de memória única seria sempre mais rápida do que o loop forfonte