@@ -306,10 +306,270 @@ a = d;
306306< ! -- Returning an Array -- >
307307## 返回数组
308308
309+ 假设你写了一个方法,这个方法不是返回一个元素,而是返回多个元素。对C ++ / C 这样的语言来说这是很困难的,因为你无法返回一个数组,只能是返回一个指向数组的指针。这会带来一些问题,因为对数组生存期的控制变得很混乱,这会导致内存泄露。
310+
311+ 而在Java 中,你只需返回数组,你永远不用为数组担心,只要你需要它,它就可用,垃圾收集器会在你用完后把它清理干净。
312+
313+ 下面,我们返回一个 ** 字符串** 数组:
314+
315+ ```Java
316+ // arrays/IceCreamFlavors.java
317+ // Returning arrays from methods
318+ import java. util. * ;
319+ import static onjava. ArrayShow . * ;
320+
321+ public class IceCreamFlavors {
322+ private static SplittableRandom rand =
323+ new SplittableRandom (47 );
324+ static final String [] FLAVORS = {
325+ " Chocolate" , " Strawberry" , " Vanilla Fudge Swirl" ,
326+ " Mint Chip" , " Mocha Almond Fudge" , " Rum Raisin" ,
327+ " Praline Cream" , " Mud Pie"
328+ };
329+ public static String [] flavorSet (int n ) {
330+ if (n > FLAVORS . length)
331+ throw new IllegalArgumentException (" Set too big" );
332+ String [] results = new String [n];
333+ boolean [] picked = new boolean [FLAVORS . length];
334+ for (int i = 0 ; i < n; i++ ) {
335+ int t;
336+ do
337+ t = rand. nextInt(FLAVORS . length);
338+ while (picked[t]);
339+ results[i] = FLAVORS [t];
340+ picked[t] = true ;
341+ }
342+ return results;
343+ }
344+ public static void main (String [] args ) {
345+ for (int i = 0 ; i < 7 ; i++ )
346+ show(flavorSet(3 ));
347+ }
348+ }
349+ /* Output:
350+ [Praline Cream, Mint Chip, Vanilla Fudge Swirl]
351+ [Strawberry, Vanilla Fudge Swirl, Mud Pie]
352+ [Chocolate, Strawberry, Vanilla Fudge Swirl]
353+ [Rum Raisin, Praline Cream, Chocolate]
354+ [Mint Chip, Rum Raisin, Mocha Almond Fudge]
355+ [Mocha Almond Fudge, Mud Pie, Vanilla Fudge Swirl]
356+ [Mocha Almond Fudge, Mud Pie, Mint Chip]
357+ */
358+ ```
359+
360+
361+
362+ ** flaverset()** 创建名为 ** results** 的 ** String ** 类型的数组。 这个数组的大小 ** n** 取决于你传进方法的参数。然后选择从数组 ** FLAVORS ** 中随机选择flavors并且把它们放进 ** results** 里并返回。返回一个数组就像返回其他任何的对象一样,实际上返回的是引用。数组是在 ** flavorSet()** 中或者在其他的什么地方创建的并不重要。垃圾收集器会清理你用完的数组,你需要的数组则会保留。
363+
364+ 如果你必须要返回一系列不同类型的元素,你可以使用 [泛型](book/ generics) 中介绍的 ** 元组** 。
365+
366+ 注意,当 ** flavorSet()** 随机选择 flavors,它应该确保某个特定的选项被选中。这在一个 ** do ** 循环中执行,它将一直做出随机选择直到它发现一个元素不在 ** picked** 数组中。(一个字符串
367+
368+ 比较将显示出随机选中的元素是不是已经存在于 ** results** 数组中)。如果成功了,它将添加条目并且寻找下一个( ** i** 递增)。输出结果显示 ** flvorSet()** 每一次都是按照随机顺序选择 flavors。
369+
370+ 直到书中的这个点,随机数通过 ** java.util. Random ** 类生成的,这个类从Java 1.0 就有,甚至被更新以提供Java 8 流。现在我们可以介绍Java 8 中的 ** SplittableRandom ** ,它不只是以线性操作工作(你最终会学到),还提供了一个高质量的随机数。我们将在这本书的后面部分使用 ** SplittableRandom ** 。
309371
310372< ! -- Multidimensional Arrays -- >
311373## 多维数组
312374
375+ 要创建多维的基元数组,你要用大括号来界定数组中的向量:
376+
377+ ```Java
378+ // arrays/MultidimensionalPrimitiveArray.java
379+ import java. util. * ;
380+
381+ public class MultidimensionalPrimitiveArray {
382+ public static void main (String [] args ) {
383+ int [][] a = {
384+ { 1 , 2 , 3 , },
385+ { 4 , 5 , 6 , },
386+ };
387+ System . out. println(Arrays . deepToString(a));
388+ }
389+ }
390+ /* Output:
391+ [[1, 2, 3], [4, 5, 6]]
392+ */ 。
393+ ```
394+
395+ 每个嵌套的大括号都代表了数组的一个维度。
396+
397+ 这个例子使用 ** array. deepToString()** 方法,这将多维数组转换成 ** String ** 类型,就像在输出中显示的那样。
398+
399+ 你也可以使用 ** new ** 分配数组。 这是一个使用 **new** 表达式分配的三维数组:
400+
401+ ```Java
402+ // arrays/ThreeDWithNew.java
403+ import java.util.*;
404+
405+ public class ThreeDWithNew {
406+ public static void main (String [] args ) {
407+ // 3-D array with fixed length:
408+ int [][][] a = new int [2 ][2 ][4 ];
409+ System . out. println(Arrays . deepToString(a));
410+ }
411+ }
412+ /* Output:
413+ [[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0,
414+ 0]]]
415+ */
416+ ```
417+
418+ 倘若你不对基元数组进行显式的初始化,它的值会自动初始化。而对象数组将被初始化为 ** null ** 。
419+
420+ 组成矩阵的数组中每一个向量都可以是任意长度的(这叫做不规则数组):
421+
422+ ```Java
423+ // arrays/RaggedArray.java
424+ import java. util. * ;
425+
426+ public class RaggedArray {
427+ static int val = 1 ;
428+ public static void main (String [] args ) {
429+ SplittableRandom rand = new SplittableRandom (47 );
430+ // 3-D array with varied-length vectors:
431+ int [][][] a = new int [rand. nextInt(7 )][][];
432+ for (int i = 0 ; i < a. length; i++ ) {
433+ a[i] = new int [rand. nextInt(5 )][];
434+ for (int j = 0 ; j < a[i]. length; j++ ) {
435+ a[i][j] = new int [rand. nextInt(5 )];
436+ Arrays . setAll(a[i][j], n - > val++ ); // [1]
437+ }
438+ }
439+ System . out. println(Arrays . deepToString(a));
440+ }
441+ }
442+ /* Output:
443+ [[[1], []], [[2, 3, 4, 5], [6]], [[7, 8, 9], [10, 11,
444+ 12], []]]
445+ */
446+ ```
447+
448+ 第一个 ** new ** 创建了一个数组,这个数组首元素长度随机,其余的则不确定。第二个在for循环中的 **new** 给数组填充了元素,第三个 **new** 为数组的最后一个索引填充元素。
449+
450+ * **[1]** Java 8 增加了 **Arrays .setAll()** 方法,其使用生成器来生成插入数组中的值。此生成器符合函数接口 ** IntunaryOperator ** ,只使用一个非 ** 默认** 的方法 ** ApplyAsint(int 操作数)** 。 ** Arrays . setAll()** 传递当前数组索引作为操作数,因此一个选项是提供 ** n - > n** 的lambda表达式来显示数组的索引(在上面的代码中很容易尝试)。这里,我们忽略索引,只是插入递增计数器的值。
451+
452+ 非基元的对象数组也可以定义为不规则数组。这里,我们收集了许多使用大括号的 ** new ** 表达式:
453+
454+ ```Java
455+ // arrays/MultidimensionalObjectArrays.java
456+ import java.util.*;
457+
458+ public class MultidimensionalObjectArrays {
459+ public static void main (String [] args ) {
460+ BerylliumSphere [][] spheres = {
461+ { new BerylliumSphere (), new BerylliumSphere () },
462+ { new BerylliumSphere (), new BerylliumSphere (),
463+ new BerylliumSphere (), new BerylliumSphere () },
464+ { new BerylliumSphere (), new BerylliumSphere (),
465+ new BerylliumSphere (), new BerylliumSphere (),
466+ new BerylliumSphere (), new BerylliumSphere (),
467+ new BerylliumSphere (), new BerylliumSphere () },
468+ };
469+ System . out. println(Arrays . deepToString(spheres));
470+ }
471+ }
472+ /* Output:
473+ [[Sphere 0, Sphere 1], [Sphere 2, Sphere 3, Sphere 4,
474+ Sphere 5], [Sphere 6, Sphere 7, Sphere 8, Sphere 9,
475+ Sphere 10, Sphere 11, Sphere 12, Sphere 13]]
476+ */
477+ ```
478+
479+ 数组初始化时使用自动装箱技术:
480+
481+ ```Java
482+ // arrays/AutoboxingArrays.java
483+ import java. util. * ;
484+
485+ public class AutoboxingArrays {
486+ public static void main (String [] args ) {
487+ Integer [][] a = { // Autoboxing:
488+ { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 },
489+ { 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 },
490+ { 51 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 },
491+ { 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 },
492+ };
493+ System . out. println(Arrays . deepToString(a));
494+ }
495+ }
496+ /* Output:
497+ [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [21, 22, 23, 24, 25,
498+ 26, 27, 28, 29, 30], [51, 52, 53, 54, 55, 56, 57, 58,
499+ 59, 60], [71, 72, 73, 74, 75, 76, 77, 78, 79, 80]]
500+ */
501+ ```
502+
503+ 以下是如何逐个构建非基元的对象数组:
504+
505+ ```Java
506+ // arrays/AssemblingMultidimensionalArrays.java
507+ // Creating multidimensional arrays
508+ import java. util. * ;
509+
510+ public class AssemblingMultidimensionalArrays {
511+ public static void main (String [] args ) {
512+ Integer [][] a;
513+ a = new Integer [3 ][];
514+ for (int i = 0 ; i < a. length; i++ ) {
515+ a[i] = new Integer [3 ];
516+ for (int j = 0 ; j < a[i]. length; j++ )
517+ a[i][j] = i * j; // Autoboxing
518+ }
519+ System . out. println(Arrays . deepToString(a));
520+ }
521+ }
522+ /* Output:
523+ [[0, 0, 0], [0, 1, 2], [0, 2, 4]]
524+ */
525+ ```
526+
527+ ** i * j** 在这里只是为了向 ** Integer ** 中添加有趣的值。
528+
529+ ** Arrays . deepToString()** 方法同时适用于基元数组和对象数组:
530+
531+ ```JAVA
532+ // arrays/MultiDimWrapperArray.java
533+ // (c)2017 MindView LLC: see Copyright.txt
534+ // We make no guarantees that this code is fit for any purpose.
535+ // Visit http://OnJava8.com for more book information.
536+ // Multidimensional arrays of "wrapper" objects
537+ import java. util. * ;
538+
539+ public class MultiDimWrapperArray {
540+ public static void main (String [] args ) {
541+ Integer [][] a1 = { // Autoboxing
542+ { 1 , 2 , 3 , },
543+ { 4 , 5 , 6 , },
544+ };
545+ Double [][][] a2 = { // Autoboxing
546+ { { 1.1 , 2.2 }, { 3.3 , 4.4 } },
547+ { { 5.5 , 6.6 }, { 7.7 , 8.8 } },
548+ { { 9.9 , 1.2 }, { 2.3 , 3.4 } },
549+ };
550+ String [][] a3 = {
551+ { " The" , " Quick" , " Sly" , " Fox" },
552+ { " Jumped" , " Over" },
553+ { " The" , " Lazy" , " Brown" , " Dog" , " &" , " friend" },
554+ };
555+ System . out. println(
556+ " a1: " + Arrays . deepToString(a1));
557+ System . out. println(
558+ " a2: " + Arrays . deepToString(a2));
559+ System . out. println(
560+ " a3: " + Arrays . deepToString(a3));
561+ }
562+ }
563+ /* Output:
564+ a1: [[1, 2, 3], [4, 5, 6]]
565+ a2: [[[1.1, 2.2], [3.3, 4.4]], [[5.5, 6.6], [7.7,
566+ 8.8]], [[9.9, 1.2], [2.3, 3.4]]]
567+ a3: [[The, Quick, Sly, Fox], [Jumped, Over], [The,
568+ Lazy, Brown, Dog, &, friend]]
569+ */
570+ ```
571+
572+ 同样的,在 ** Integer ** 和 ** Double ** 数组中,自动装箱为可为你创建包装器对象。
313573
314574< ! -- Arrays and Generics -- >
315575## 泛型数组
0 commit comments