传递给 Arrays.setAll() 的生成器函数可以使用它接收到的数组索引修改现有的数组元素:
ModifyExisting.java
import java.util.Arrays;
import static com.example.test.ArrayShow.show;
public class ModifyExisting {
public static void main(String[] args) {
double[] da = new double[7];
Arrays.setAll(da, new Rand.Double()::get);
show(da);
Arrays.setAll(da, n -> da[n] / 100); // [1]
show(da);
}
}
Rand.java
import java.util.*;
import java.util.function.*;
import static com.example.test.ConvertTo.primitive;
public interface Rand {
int MOD = 10_000;
class Boolean implements Supplier<java.lang.Boolean> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Boolean get() {
return r.nextBoolean();
}
public java.lang.Boolean get(int n) {
return get();
}
public java.lang.Boolean[] array(int sz) {
java.lang.Boolean[] result =
new java.lang.Boolean[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pboolean {
public boolean[] array(int sz) {
return primitive(new Boolean().array(sz));
}
}
class Byte
implements Supplier<java.lang.Byte> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Byte get() {
return (byte) r.nextInt(MOD);
}
public java.lang.Byte get(int n) {
return get();
}
public java.lang.Byte[] array(int sz) {
java.lang.Byte[] result =
new java.lang.Byte[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pbyte {
public byte[] array(int sz) {
return primitive(new Byte().array(sz));
}
}
class Character
implements Supplier<java.lang.Character> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Character get() {
return (char) r.nextInt('a', 'z' + 1);
}
public java.lang.Character get(int n) {
return get();
}
public java.lang.Character[] array(int sz) {
java.lang.Character[] result =
new java.lang.Character[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pchar {
public char[] array(int sz) {
return primitive(new Character().array(sz));
}
}
class Short
implements Supplier<java.lang.Short> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Short get() {
return (short) r.nextInt(MOD);
}
public java.lang.Short get(int n) {
return get();
}
public java.lang.Short[] array(int sz) {
java.lang.Short[] result =
new java.lang.Short[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pshort {
public short[] array(int sz) {
return primitive(new Short().array(sz));
}
}
class Integer
implements Supplier<java.lang.Integer> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Integer get() {
return r.nextInt(MOD);
}
public java.lang.Integer get(int n) {
return get();
}
public java.lang.Integer[] array(int sz) {
int[] primitive = new Pint().array(sz);
java.lang.Integer[] result =
new java.lang.Integer[sz];
for (int i = 0; i < sz; i++) {
result[i] = primitive[i];
}
return result;
}
}
class Pint implements IntSupplier {
SplittableRandom r = new SplittableRandom(47);
@Override
public int getAsInt() {
return r.nextInt(MOD);
}
public int get(int n) {
return getAsInt();
}
public int[] array(int sz) {
return r.ints(sz, 0, MOD).toArray();
}
}
class Long implements Supplier<java.lang.Long> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Long get() {
return r.nextLong(MOD);
}
public java.lang.Long get(int n) {
return get();
}
public java.lang.Long[] array(int sz) {
long[] primitive = new Plong().array(sz);
java.lang.Long[] result =
new java.lang.Long[sz];
for (int i = 0; i < sz; i++) {
result[i] = primitive[i];
}
return result;
}
}
class Plong implements LongSupplier {
SplittableRandom r = new SplittableRandom(47);
@Override
public long getAsLong() {
return r.nextLong(MOD);
}
public long get(int n) {
return getAsLong();
}
public long[] array(int sz) {
return r.longs(sz, 0, MOD).toArray();
}
}
class Float
implements Supplier<java.lang.Float> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Float get() {
return (float) trim(r.nextDouble());
}
public java.lang.Float get(int n) {
return get();
}
public java.lang.Float[] array(int sz) {
java.lang.Float[] result =
new java.lang.Float[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pfloat {
public float[] array(int sz) {
return primitive(new Float().array(sz));
}
}
static double trim(double d) {
return
((double) Math.round(d * 1000.0)) / 100.0;
}
class Double implements Supplier<java.lang.Double> {
SplittableRandom r = new SplittableRandom(47);
@Override
public java.lang.Double get() {
return trim(r.nextDouble());
}
public java.lang.Double get(int n) {
return get();
}
public java.lang.Double[] array(int sz) {
double[] primitive =
new Rand.Pdouble().array(sz);
java.lang.Double[] result =
new java.lang.Double[sz];
for (int i = 0; i < sz; i++) {
result[i] = primitive[i];
}
return result;
}
}
class Pdouble implements DoubleSupplier {
SplittableRandom r = new SplittableRandom(47);
@Override
public double getAsDouble() {
return trim(r.nextDouble());
}
public double get(int n) {
return getAsDouble();
}
public double[] array(int sz) {
double[] result = r.doubles(sz).toArray();
Arrays.setAll(result,
n -> result[n] = trim(result[n]));
return result;
}
}
class String
implements Supplier<java.lang.String> {
SplittableRandom r = new SplittableRandom(47);
private int strlen = 7; // Default length
public String() {
}
public String(int strLength) {
strlen = strLength;
}
@Override
public java.lang.String get() {
return r.ints(strlen, 'a', 'z' + 1)
.collect(StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append).toString();
}
public java.lang.String get(int n) {
return get();
}
public java.lang.String[] array(int sz) {
java.lang.String[] result =
new java.lang.String[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
}
ConvertTo.java
public interface ConvertTo {
static boolean[] primitive(Boolean[] in) {
boolean[] result = new boolean[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i]; // Autounboxing
}
return result;
}
static char[] primitive(Character[] in) {
char[] result = new char[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static byte[] primitive(Byte[] in) {
byte[] result = new byte[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static short[] primitive(Short[] in) {
short[] result = new short[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static int[] primitive(Integer[] in) {
int[] result = new int[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static long[] primitive(Long[] in) {
long[] result = new long[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static float[] primitive(Float[] in) {
float[] result = new float[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static double[] primitive(Double[] in) {
double[] result = new double[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
// Convert from primitive array to wrapped array:
static Boolean[] boxed(boolean[] in) {
Boolean[] result = new Boolean[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i]; // Autoboxing
}
return result;
}
static Character[] boxed(char[] in) {
Character[] result = new Character[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static Byte[] boxed(byte[] in) {
Byte[] result = new Byte[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static Short[] boxed(short[] in) {
Short[] result = new Short[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static Integer[] boxed(int[] in) {
Integer[] result = new Integer[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static Long[] boxed(long[] in) {
Long[] result = new Long[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static Float[] boxed(float[] in) {
Float[] result = new Float[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
static Double[] boxed(double[] in) {
Double[] result = new Double[in.length];
for (int i = 0; i < in.length; i++) {
result[i] = in[i];
}
return result;
}
}
ArrayShow.java
import java.util.*;
public interface ArrayShow {
static void show(Object[] a) {
System.out.println(Arrays.toString(a));
}
static void show(boolean[] a) {
System.out.println(Arrays.toString(a));
}
static void show(byte[] a) {
System.out.println(Arrays.toString(a));
}
static void show(char[] a) {
System.out.println(Arrays.toString(a));
}
static void show(short[] a) {
System.out.println(Arrays.toString(a));
}
static void show(int[] a) {
System.out.println(Arrays.toString(a));
}
static void show(long[] a) {
System.out.println(Arrays.toString(a));
}
static void show(float[] a) {
System.out.println(Arrays.toString(a));
}
static void show(double[] a) {
System.out.println(Arrays.toString(a));
}
// Start with a description:
static void show(String info, Object[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, boolean[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, byte[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, char[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, short[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, int[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, long[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, float[] a) {
System.out.print(info + ": ");
show(a);
}
static void show(String info, double[] a) {
System.out.print(info + ": ");
show(a);
}
}
[1] Lambdas在这里特别有用,因为数组总是在lambda表达式的范围内。
我们很快就不得不面对并行的主题。例如,“并行”一词在许多Java库方法中使用。您可能听说过类似“并行程序运行得更快”这样的说法,这是有道理的—当您可以有多个处理器时,为什么只有一个处理器在您的程序上工作呢? 如果您认为您应该利用其中的“并行”,这是很容易被原谅的。
要是这么简单就好了。不幸的是,通过采用这种方法,您可以很容易地编写比非并行版本运行速度更慢的代码。在你深刻理解所有的问题之前,并行编程看起来更像是一门艺术而非科学。
以下是简短的版本:用简单的方法编写代码。不要开始处理并行性,除非它成为一个问题。您仍然会遇到并行性。在本章中,我们将介绍一些为并行执行而编写的Java库方法。因此,您必须对它有足够的了解,以便进行基本的讨论,并避免出现错误。
在阅读并发编程这一章之后,您将更深入地理解它(但是,唉,这还远远不够。只是这些的话,充分理解这个主题是不可能的)。
在某些情况下,即使您只有一个处理器,无论您是否显式地尝试并行,并行实现是惟一的、最佳的或最符合逻辑的选择。它是一个可以一直使用的工具,所以您必须了解它的相关问题。
最好从数据的角度来考虑并行性。对于大量数据(以及可用的额外处理器),并行可能会有所帮助。但您也可能使事情变得更糟。
在本书的其余部分,我们将遇到不同的情况:
流式编程产生优雅的代码。例如,假设我们想要创建一个数值由从零开始填充的长数组:
import java.util.stream.LongStream;
import static com.example.test.ArrayShow.show;
public class CountUpward {
static long[] fillCounted(int size) {
return LongStream.iterate(0, i -> i + 1).limit(size).toArray();
}
public static void main(String[] args) {
long[] l1 = fillCounted(20); // No problem
show(l1);
// On my machine, this runs out of heap space:
// - long[] l2 = fillCounted(10_000_000);
}
}
流 实际上可以存储到将近1000万,但是之后就会耗尽堆空间。常规的 setAll() 是有效的,但是如果我们能更快地处理如此大量的数字,那就更好了。
我们可以使用 setAll() 初始化更大的数组。如果速度成为一个问题,Arrays.parallelSetAll() 将(可能)更快地执行初始化(请记住并行性中描述的问题)。
import java.util.Arrays;
public class ParallelSetAll {
static final int SIZE = 10_000_000;
static void intArray() {
int[] ia = new int[SIZE];
Arrays.setAll(ia, new Rand.Pint()::get);
Arrays.parallelSetAll(ia, new Rand.Pint()::get);
}
static void longArray() {
long[] la = new long[SIZE];
Arrays.setAll(la, new Rand.Plong()::get);
Arrays.parallelSetAll(la, new Rand.Plong()::get);
}
public static void main(String[] args) {
intArray();
longArray();
}
}
数组分配和初始化是在单独的方法中执行的,因为如果两个数组都在 main() 中分配,它会耗尽内存(至少在我的机器上是这样。还有一些方法可以告诉Java在启动时分配更多的内存)。
您已经看到了 java.util.Arrays 中的 fill() 和 setAll()/parallelSetAll() 。该类包含许多其他有用的 静态 程序方法,我们将对此进行研究。
概述:
与使用for循环手工执行复制相比,copyOf() 和 copyOfRange() 复制数组要快得多。这些方法被重载以处理所有类型。
我们从复制 int 和 Integer 数组开始:
Count.java
import java.util.*;
import java.util.function.*;
import static com.example.test.ConvertTo.primitive;
public interface Count {
class Boolean
implements Supplier<java.lang.Boolean> {
private boolean b = true;
@Override
public java.lang.Boolean get() {
b = !b;
return java.lang.Boolean.valueOf(b);
}
public java.lang.Boolean get(int n) {
return get();
}
public java.lang.Boolean[] array(int sz) {
java.lang.Boolean[] result =
new java.lang.Boolean[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pboolean {
private boolean b = true;
public boolean get() {
b = !b;
return b;
}
public boolean get(int n) {
return get();
}
public boolean[] array(int sz) {
return primitive(new Boolean().array(sz));
}
}
class Byte
implements Supplier<java.lang.Byte> {
private byte b;
@Override
public java.lang.Byte get() {
return b++;
}
public java.lang.Byte get(int n) {
return get();
}
public java.lang.Byte[] array(int sz) {
java.lang.Byte[] result =
new java.lang.Byte[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pbyte {
private byte b;
public byte get() {
return b++;
}
public byte get(int n) {
return get();
}
public byte[] array(int sz) {
return primitive(new Byte().array(sz));
}
}
char[] CHARS =
"abcdefghijklmnopqrstuvwxyz".toCharArray();
class Character
implements Supplier<java.lang.Character> {
private int i;
@Override
public java.lang.Character get() {
i = (i + 1) % CHARS.length;
return CHARS[i];
}
public java.lang.Character get(int n) {
return get();
}
public java.lang.Character[] array(int sz) {
java.lang.Character[] result =
new java.lang.Character[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pchar {
private int i;
public char get() {
i = (i + 1) % CHARS.length;
return CHARS[i];
}
public char get(int n) {
return get();
}
public char[] array(int sz) {
return primitive(new Character().array(sz));
}
}
class Short
implements Supplier<java.lang.Short> {
short s;
@Override
public java.lang.Short get() {
return s++;
}
public java.lang.Short get(int n) {
return get();
}
public java.lang.Short[] array(int sz) {
java.lang.Short[] result =
new java.lang.Short[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pshort {
short s;
public short get() {
return s++;
}
public short get(int n) {
return get();
}
public short[] array(int sz) {
return primitive(new Short().array(sz));
}
}
class Integer
implements Supplier<java.lang.Integer> {
int i;
@Override
public java.lang.Integer get() {
return i++;
}
public java.lang.Integer get(int n) {
return get();
}
public java.lang.Integer[] array(int sz) {
java.lang.Integer[] result =
new java.lang.Integer[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pint implements IntSupplier {
int i;
public int get() {
return i++;
}
public int get(int n) {
return get();
}
@Override
public int getAsInt() {
return get();
}
public int[] array(int sz) {
return primitive(new Integer().array(sz));
}
}
class Long
implements Supplier<java.lang.Long> {
private long l;
@Override
public java.lang.Long get() {
return l++;
}
public java.lang.Long get(int n) {
return get();
}
public java.lang.Long[] array(int sz) {
java.lang.Long[] result =
new java.lang.Long[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Plong implements LongSupplier {
private long l;
public long get() {
return l++;
}
public long get(int n) {
return get();
}
@Override
public long getAsLong() {
return get();
}
public long[] array(int sz) {
return primitive(new Long().array(sz));
}
}
class Float
implements Supplier<java.lang.Float> {
private int i;
@Override
public java.lang.Float get() {
return java.lang.Float.valueOf(i++);
}
public java.lang.Float get(int n) {
return get();
}
public java.lang.Float[] array(int sz) {
java.lang.Float[] result =
new java.lang.Float[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pfloat {
private int i;
public float get() {
return i++;
}
public float get(int n) {
return get();
}
public float[] array(int sz) {
return primitive(new Float().array(sz));
}
}
class Double
implements Supplier<java.lang.Double> {
private int i;
@Override
public java.lang.Double get() {
return java.lang.Double.valueOf(i++);
}
public java.lang.Double get(int n) {
return get();
}
public java.lang.Double[] array(int sz) {
java.lang.Double[] result =
new java.lang.Double[sz];
Arrays.setAll(result, n -> get());
return result;
}
}
class Pdouble implements DoubleSupplier {
private int i;
public double get() {
return i++;
}
public double get(int n) {
return get();
}
@Override
public double getAsDouble() {
return get(0);
}
public double[] array(int sz) {
return primitive(new Double().array(sz));
}
}
}
ArrayCopying.java
import java.util.Arrays;
import static com.example.test.ArrayShow.show;
class Sup {
// Superclass
private int id;
Sup(int n) {
id = n;
}
@Override
public String toString() {
return getClass().getSimpleName() + id;
}
}
class Sub extends Sup { // Subclass
Sub(int n) {
super(n);
}
}
public class ArrayCopying {
public static final int SZ = 15;
public static void main(String[] args) {
int[] a1 = new int[SZ];
Arrays.setAll(a1, new Count.Integer()::get);
show("a1", a1);
int[] a2 = Arrays.copyOf(a1, a1.length); // [1]
// Prove they are distinct arrays:
Arrays.fill(a1, 1);
show("a1", a1);
show("a2", a2);
// Create a shorter result:
a2 = Arrays.copyOf(a2, a2.length / 2); // [2]
show("a2", a2);
// Allocate more space:
a2 = Arrays.copyOf(a2, a2.length + 5);
show("a2", a2);
// Also copies wrapped arrays:
Integer[] a3 = new Integer[SZ]; // [3]
Arrays.setAll(a3, new Count.Integer()::get);
Integer[] a4 = Arrays.copyOfRange(a3, 4, 12);
show("a4", a4);
Sub[] d = new Sub[SZ / 2];
Arrays.setAll(d, Sub::new); // Produce Sup[] from Sub[]:
Sup[] b = Arrays.copyOf(d, d.length, Sup[].class); // [4]
show(b); // This "downcast" works fine:
Sub[] d2 = Arrays.copyOf(b, b.length, Sub[].class); // [5]
show(d2); // Bad "downcast" compiles but throws exception:
Sup[] b2 = new Sup[SZ / 2];
Arrays.setAll(b2, Sup::new);
try {
Sub[] d3 = Arrays.copyOf(b2, b2.length, Sub[].class); // [6]
} catch (Exception e) {
System.out.println(e);
}
}
}
[1] 这是复制的基本方法;只需给出返回的复制数组的大小。这对于编写需要调整存储大小的算法很有帮助。复制之后,我们把a1的所有元素都设为1,以证明a1的变化不会影响a2中的任何东西。
[2] 通过更改最后一个参数,我们可以缩短或延长返回的复制数组。
[3] copyOf() 和 copyOfRange() 也可以使用包装类型。copyOfRange() 需要一个开始和结束索引。
[4] copyOf() 和 copyOfRange() 都有一个版本,该版本通过在方法调用的末尾添加目标类型来创建不同类型的数组。我首先想到的是,这可能是一种从原生数组生成包装数组的方法,反之亦然。
但这没用。它的实际用途是“向上转换”和“向下转换”数组。也就是说,如果您有一个子类型(派生类型)的数组,而您想要一个基类型的数组,那么这些方法将生成所需的数组。
[5] 您甚至可以成功地“向下强制转换”,并从超类型的数组生成子类型的数组。这个版本运行良好,因为我们只是“upcast”。
[6] 这个“数组转换”将编译,但是如果类型不兼容,您将得到一个运行时异常。在这里,强制将基类型转换为派生类型是非法的,因为派生对象中可能有基对象中没有的属性和方法。
实例表明,原生数组和对象数组都可以被复制。但是,如果复制对象的数组,那么只复制引用—不复制对象本身。这称为浅拷贝(有关更多细节,请参阅附录:传递和返回对象)。
还有一个方法 System.arraycopy() ,它将一个数组复制到另一个已经分配的数组中。这将不会执行自动装箱或自动卸载—两个数组必须是完全相同的类型。
数组 提供了 equals() 来比较一维数组,以及 deepEquals() 来比较多维数组。对于所有原生类型和对象,这些方法都是重载的。
数组相等的含义:数组必须有相同数量的元素,并且每个元素必须与另一个数组中的对应元素相等,对每个元素使用 equals()(对于原生类型,使用原生类型的包装类的 equals() 方法;例如,int的Integer.equals()。
import java.util.*;
public class ComparingArrays {
public static final int SZ = 15;
static String[][] twoDArray() {
String[][] md = new String[5][];
Arrays.setAll(md, n -> new String[n]);
for (int i = 0; i < md.length; i++) {
Arrays.setAll(md[i], new Rand.String()::get);
}
return md;
}
public static void main(String[] args) {
int[] a1 = new int[SZ], a2 = new int[SZ];
Arrays.setAll(a1, new Count.Integer()::get);
Arrays.setAll(a2, new Count.Integer()::get);
System.out.println("a1 == a2: " + Arrays.equals(a1, a2));
a2[3] = 11;
System.out.println("a1 == a2: " + Arrays.equals(a1, a2));
Integer[] a1w = new Integer[SZ], a2w = new Integer[SZ];
Arrays.setAll(a1w, new Count.Integer()::get);
Arrays.setAll(a2w, new Count.Integer()::get);
System.out.println("a1w == a2w: " + Arrays.equals(a1w, a2w));
a2w[3] = 11;
System.out.println("a1w == a2w: " + Arrays.equals(a1w, a2w));
String[][] md1 = twoDArray(), md2 = twoDArray();
System.out.println(Arrays.deepToString(md1));
System.out.println("deepEquals(md1, md2): " + Arrays.deepEquals(md1, md2));
System.out.println("md1 == md2: " + Arrays.equals(md1, md2));
md1[4][1] = "#$#$#$#";
System.out.println(Arrays.deepToString(md1));
System.out.println("deepEquals(md1, md2): " + Arrays.deepEquals(md1, md2));
}
}
最初,a1和a2是完全相等的,所以输出是true,但是之后其中一个元素改变了,这使得结果为false。a1w和a2w是对一个封装类型数组重复该练习。
md1 和 md2 是通过 twoDArray() 以相同方式初始化的多维字符串数组。注意,deepEquals() 返回 true,因为它执行了适当的比较,而普通的 equals() 错误地返回 false。如果我们更改数组中的一个元素,deepEquals() 将检测它。
stream() 方法很容易从某些类型的数组中生成元素流。
import java.util.*;
public class StreamFromArray {
public static void main(String[] args) {
String[] s = new Rand.String().array(10);
Arrays.stream(s).skip(3).limit(5).map(ss -> ss + "!").forEach(System.out::println);
int[] ia = new Rand.Pint().array(10);
Arrays.stream(ia).skip(3).limit(5)
.map(i -> i * 10).forEach(System.out::println);
Arrays.stream(new long[10]);
Arrays.stream(new double[10]);
// Only int, long and double work:
// - Arrays.stream(new boolean[10]);
// - Arrays.stream(new byte[10]);
// - Arrays.stream(new char[10]);
// - Arrays.stream(new short[10]);
// - Arrays.stream(new float[10]);
// For the other types you must use wrapped arrays:
float[] fa = new Rand.Pfloat().array(10);
Arrays.stream(ConvertTo.boxed(fa));
Arrays.stream(new Rand.Float().array(10));
}
}
只有“原生类型” int、long 和 double 可以与 Arrays.stream() 一起使用;对于其他的,您必须以某种方式获得一个包装类型的数组。
通常,将数组转换为流来生成所需的结果要比直接操作数组容易得多。请注意,即使流已经“用完”(您不能重复使用它),您仍然拥有该数组,因此您可以以其他方式使用它----包括生成另一个流。