java - 如何在不复制数据的情况下在Java中获取数组的子数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3395547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:54:45  来源:igfitidea点击:

How to get a sub array of array in Java, without copying data?

javaarrayscontainers

提问by Illarion Kovalchuk

I have some library of classes, working with my data, which is being read into buffer. Is it possible somehow to avoid copying arrays again and again, passing parts of data deeper and deeper into processing methods? Well, it sounds strange, but in my particular case, there's a special writer, which divides data into blocks and writes them individually into different locations, so it just performs System.arraycopy, gets what it needs and calls underlying writer, with that new sub array. And this happens many times. What is the best approach to refactor such code?

我有一些类库,处理我的数据,这些数据被读入缓冲区。是否有可能以某种方式避免一次又一次地复制数组,将部分数据越来越深入地传递到处理方法中?嗯,这听起来很奇怪,但在我的特殊情况下,有一个特殊的写入器,它将数据分成块并将它们单独写入不同的位置,所以它只是执行 System.arraycopy,获取它需要的东西并调用底层写入器,使用新的子数组。而且这种情况发生了很多次。重构此类代码的最佳方法是什么?

采纳答案by Markus Kull

Many classes in Java accept a subset of an arrays as parameter. E.g. Writer.write(char cbuf[], int off, int len). Maybe this already suffices for your usecase.

Java 中的许多类都接受数组的子集作为参数。例如 Writer.write(char cbuf[], int off, int len)。也许这对于您的用例已经足够了。

回答by Manuel Selva

Have a look on Arrays.copyOfRange(***)methods.

看看Arrays.copyOfRange(***)方法。

回答by rsp

You could take the same approach as the Stringclass takes; create a class for immutable objects which are constructed from an array, a start offset and an end offset which offers access to the sub-array. The user of such an object does not have to know the distinction between the whole array or a sub-array. The constructor does not have to copy the array, just store the array reference and its boundaries.

您可以采用与String课堂相同的方法;为由数组、起始偏移量和结束偏移量构造的不可变对象创建一个类,提供对子数组的访问。这种对象的用户不必知道整个数组或子数组之间的区别。构造函数不必复制数组,只需存储数组引用及其边界。

回答by Ricky Clarkson

Arrays.asList(array).subList(x, y).

This method doesn't give you an array, but a List, which is far more flexible.

这种方法不会给你一个数组,而是给你一个List,这要灵活得多。

回答by Kotten

You could use (ArrayList).subList(value1, value2) i belive, perhaps that could help in your case? That is ofcourse if you want to use an ArrayList.

你可以使用 (ArrayList).subList(value1, value2) 我相信,也许这对你的情况有帮助?如果您想使用 ArrayList,那当然是可以的。

回答by Roman Nikitchenko

There is no real way to wrap any data without copying and receive real array in Java. You just cannot create new array over existing memory. You have basically 2 options:

在 Java 中没有真正的方法来包装任何数据而不复制和接收真实数组。您不能在现有内存上创建新数组。您基本上有两个选择:

  • Use methods that can accept range of array. This was already recommended.
  • Use wrapper that gives some kind of abstraction that is close to array and is suitable for many applications. Will be described below.
  • 使用可以接受数组范围的方法。这已经被推荐了。
  • 使用提供某种类似于数组的抽象并且适用于许多应用程序的包装器。下面将进行说明。

You may use java.nio.Bufferclasses hierarchy, especially java.nio.ByteBufferwhich offers buffer abstraction on whole array or sub-ranges. Often it is what people need. This also offers many interesting abilities like 'zero copy' flip and flexible byte area representation.

您可以使用java.nio.Buffer类层次结构,尤其是java.nio.ByteBuffer它在整个数组或子范围上提供缓冲区抽象。通常这是人们所需要的。这也提供了许多有趣的功能,例如“零复制”翻转和灵活的字节区域表示。

Here is example of wrapping using java.nio.ByteBuffer. This should be very close to what you need. At least for some operations.

这是使用java.nio.ByteBuffer. 这应该非常接近您的需要。至少对于某些操作。

byte [] a1 = {0, 0, 1, 0};
ByteBuffer buf = ByteBuffer.wrap(a1,1,2);

Then you can do on bufany ByteBufferoperation.

然后你可以对buf任何ByteBuffer操作进行。

Just a warning, buf.array()returns original a1array (backend) with all elements.

只是一个警告,buf.array()返回a1包含所有元素的原始数组(后端)。

回答by Joachim

There is no way to declare a subarray in Java if you use built in arrays like byte[]. The reason is: The length of the array is stored with the data, not with the declaration of the reference to it. Hence a subarray which does not copy the data has no place where it can store the length! So for basic types you can use the mentioned efficient byte array copies and for higher types (List) there are methods available.

如果您使用像 byte[] 这样的内置数组,则无法在 Java 中声明子数组。原因是:数组的长度与数据一起存储,而不是与对它的引用的声明一起存储。因此,不复制数据的子数组没有可以存储长度的地方!因此,对于基本类型,您可以使用提到的高效字节数组副本,对于更高的类型(列表),有可用的方法。

回答by Orestis P.

Perhaps instead of working with arrays you should work with a different type that maintains a reference to a slice of the original array, instead of copying the data over, similar to ArraySegment in C#. An additional benefit to this is that you can also shift the slice over the original array on-demand, without creating new instances. Pseudo code:

也许不是使用数组,您应该使用不同的类型,该类型维护对原始数组切片的引用,而不是复制数据,类似于 C# 中的 ArraySegment。这样做的另一个好处是,您还可以按需将切片转移到原始阵列上,而无需创建新实例。伪代码:

public class ArraySegment<T> implements Iterable<T> 
{
      private int from, to;
      private T[] original;

      public ArraySegment<T>(T[] original, int from, int to)
      {
          //constructor stuff
      }

      public T get(int index)
      {
           return source[index + from];
      }

      public int size()
      {
          return to - from + 1;
      }

      @Override
      public Iterator<T> iterator()
      {
          //Iterator that iterates over the slice
      }

      //Can support setters on from/to variables
}

回答by djenning90

Google's Guava libraries support the slice concept in the form of a ByteSource.

Google 的 Guava 库以ByteSource的形式支持切片概念。

Google Guavais a readily available open-source package of functionality, written from the ground up to follow Google best practices, which depend on significant array slicing capabilities.

Google Guava是一个随时可用的开源功能包,从头开始编写以遵循 Google 最佳实践,这些实践依赖于重要的数组切片功能。