Estou procurando um método em Java que retornará um segmento de uma matriz. Um exemplo seria obter a matriz de bytes que contém os 4º e 5º bytes de uma matriz de bytes. Não quero ter que criar uma nova matriz de bytes na memória heap apenas para fazer isso. No momento, tenho o seguinte código:
doSomethingWithTwoBytes(byte[] twoByteArray);
void someMethod(byte[] bigArray)
{
byte[] x = {bigArray[4], bigArray[5]};
doSomethingWithTwoBytes(x);
}
Eu gostaria de saber se havia uma maneira de fazer apenas doSomething(bigArray.getSubArray(4, 2))
onde 4 é o deslocamento e 2 é o comprimento, por exemplo.
Respostas:
Isenção de responsabilidade: Esta resposta não está de acordo com as restrições da pergunta:
( Sinceramente, acho que minha resposta merece ser excluída. A resposta de @ unique72 está correta. Vou deixar essa edição descansar um pouco e depois excluirei essa resposta. )
Não conheço uma maneira de fazer isso diretamente com matrizes sem alocação de heap adicional, mas as outras respostas usando um wrapper de sub-lista têm alocação adicional apenas para o wrapper - mas não o array - o que seria útil no caso de uma grande variedade.
Dito isto, se alguém procura concisão, o método utilitário
Arrays.copyOfRange()
foi introduzido no Java 6 (final de 2006?):fonte
copyOfRange
. Se fosse de código fechado, talvez pudesse ter passado. :)Arrays.asList(myArray)
delega para newArrayList(myArray)
, que não copia a matriz, mas apenas armazena a referência. UsarList.subList(start, end)
depois disso cria umSubList
que apenas faz referência à lista original (que ainda apenas faz referência à matriz). Nenhuma cópia da matriz ou seu conteúdo, apenas a criação do wrapper e todas as listas envolvidas são apoiadas pela matriz original. (Eu pensei que seria mais pesado.)fonte
Arrays
chamada confusaArrayList
, mas que é realmenteList
uma matriz, ao contrário dajava.util.ArrayList
qual faria uma cópia. Nenhuma nova alocação (do conteúdo da lista) e nenhuma dependência de terceiros. Esta é, acredito, a resposta mais correta.byte[]
no caso dele). Tudo o que você conseguiria seriaList<byte[]>
. E mudarbyte[] bigArray
paraByte[] bigArray
pode impor uma sobrecarga significativa de memória.sun.misc.Unsafe
classe.Se você está procurando uma abordagem de alias no estilo de ponteiro, para que nem precise alocar espaço e copiar os dados, acredito que não tenha sorte.
System.arraycopy()
será copiado da sua origem para o destino e a eficiência é reivindicada para este utilitário. Você precisa alocar a matriz de destino.fonte
array*copy*()
reutilizar a mesma memória? Não é exatamente o oposto do que um chamador esperaria?Uma maneira é envolver a matriz em
java.nio.ByteBuffer
, usar as funções absolutas de put / get e dividir o buffer para trabalhar em um subarray.Por exemplo:
Observe que você precisa chamar os dois
wrap()
eslice()
, uma vez que,wrap()
por si só, afeta as funções put / get relativas, não as absolutas.ByteBuffer
pode ser um pouco complicado de entender, mas provavelmente é implementado com eficiência e vale a pena aprender.fonte
StandardCharsets.UTF_8.decode(ByteBuffer.wrap(buffer, 0, readBytes))
Arrays.copyOfRange
?Arrays.copyOfRange
é provavelmente mais eficiente. Geralmente, você precisaria medir para o seu caso de uso específico.Use java.nio.Buffer. É um invólucro leve para buffers de vários tipos primitivos e ajuda a gerenciar fatias, posições, conversões, pedidos de bytes, etc.
Se seus bytes forem originários de um fluxo, os NIO Buffers poderão usar o "modo direto", que cria um buffer suportado por recursos nativos. Isso pode melhorar o desempenho em muitos casos.
fonte
Você pode usar o ArrayUtils.subarray no apache commons. Não é perfeito, mas um pouco mais intuitivo do que
System.arraycopy.
o lado negativo é que ele introduz outra dependência no seu código.fonte
Vejo que a resposta subList já está aqui, mas aqui está o código que demonstra que é uma verdadeira sublist, não uma cópia:
Porém, não acredito que exista uma boa maneira de fazer isso diretamente com matrizes.
fonte
fonte
Eles
List
permitem que você use e trabalhe comsubList
algo de forma transparente. Matrizes primitivas exigiriam que você acompanhasse algum tipo de limite de deslocamento.ByteBuffer
s têm opções semelhantes às que ouvi.Edit: Se você é responsável pelo método útil, você pode defini-lo com limites (como feito em muitos métodos relacionados à matriz no próprio java:
Não está claro, no entanto, se você trabalha com os próprios elementos da matriz, por exemplo, calcula algo e escreve o resultado?
fonte
Uma opção seria passar toda a matriz e os índices de início e fim e iterar entre eles, em vez de iterar sobre toda a matriz passada.
fonte
As referências Java sempre apontam para um objeto. O objeto possui um cabeçalho que, entre outras coisas, identifica o tipo concreto (para que as transmissões possam falhar com
ClassCastException
). Para matrizes, o início do objeto também inclui o comprimento, os dados seguem imediatamente depois na memória (tecnicamente, uma implementação é livre para fazer o que bem entender, mas seria imprudente fazer qualquer outra coisa). Portanto, você não pode ter uma referência que aponte em algum lugar de uma matriz.Em ponteiros C, aponte para qualquer lugar e para qualquer coisa, e você pode apontar para o meio de uma matriz. Mas você não pode transmitir ou descobrir com segurança quanto tempo a matriz é. Em D, o ponteiro contém um deslocamento no bloco e no comprimento da memória (ou um ponteiro equivalente ao final, não me lembro o que a implementação realmente faz). Isso permite que D divida matrizes. No C ++, você teria dois iteradores apontando para o início e o fim, mas o C ++ é um pouco estranho assim.
Então, voltando ao Java, não, você não pode. Como mencionado, o NIO
ByteBuffer
permite agrupar uma matriz e, em seguida, cortá-la, mas fornece uma interface estranha. É claro que você pode copiar, o que provavelmente é muito mais rápido do que você imagina. Você pode apresentar sua própriaString
abstração que permite dividir uma matriz (a implementação atual da SunString
tem umachar[]
referência mais um deslocamento inicial e comprimento, a implementação de desempenho mais alto apenas possui achar[]
).byte[]
é de baixo nível, mas qualquer abstração baseada em classe que você colocar fará uma bagunça terrível da sintaxe, até o JDK7 (talvez).fonte
substring
no HotSpot (esqueça qual build mudou isso). Por que você diz que o JDK7 permitiria uma sintaxe melhor que o ByteBuffer?[]
notação de matriz em tipos definidos pelo usuário, comoList
eByteBuffer
. Ainda esperando ...@ unique72 responda como uma função ou linha simples, pode ser necessário substituir Object pelo tipo de classe que você deseja 'cortar'. Duas variantes são fornecidas para atender a várias necessidades.
fonte
Que tal um
List
invólucro fino ?(Não testado)
fonte
Byte
objetos para todos osbyte
valores são armazenados em cache. Portanto, a sobrecarga do boxe deve ser bastante lenta.Eu precisava percorrer o final de uma matriz e não queria copiar a matriz. Minha abordagem foi tornar um Iterable sobre a matriz.
fonte
Isso é um pouco mais leve que Arrays.copyOfRange - sem intervalo ou negativo
fonte