Skip to content

Commit 7a9e101

Browse files
authored
Merge pull request lingcoder#209 from cogitates/master
Fix issue lingcoder#117 数组部分 第三,第四小节
2 parents 9015594 + 9807b4b commit 7a9e101

File tree

1 file changed

+260
-0
lines changed

1 file changed

+260
-0
lines changed

docs/book/21-Arrays.md

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)