ディレクトリ
Javaのストリーム&メソッドリファレンス
1.ストリームの流れ
1.1概要
コードセットを介して、従来の多段階
/*
传统的方式遍历集合,过滤集合,打印输出满足条件的集合
*/
import java.util.ArrayList;
public class Demo01LIst {
public static void main(String[] args) {
// 创建list集合,存储姓名
ArrayList<String> list = new ArrayList<>();
list.add("张无忌");
list.add("赵敏");
list.add("周芷若");
list.add("张强");
list.add("张三丰");
ArrayList<String> listA = new ArrayList<>();
for (String s : list) {
// 对list集合过滤,将张字开头的添加到listA集合中
if (s.startsWith("张")) {
listA.add(s);
}
}
ArrayList<String> listB = new ArrayList<>();
for (String s : listA) {
// 对listA集合过滤,只要名字长度为3的
if (s.length() == 3) {
listB.add(s);
}
}
// 遍历listB集合,打印输出
for (String s : listB) {
System.out.println(s);
}
}
}
より好ましくは、文言をストリーミング
import java.util.ArrayList;
/*
使用Stream流的方式,遍历集合,对集合中的数据进行过滤
Stream流式JDK1.8之后出现的
关注的是做什么,而不是怎么做
*/
public class Demo02Stream {
public static void main(String[] args) {
// 创建list集合,存储姓名
ArrayList<String> list = new ArrayList<>();
list.add("张无忌");
list.add("赵敏");
list.add("周芷若");
list.add("张强");
list.add("张三丰");
// 对list集合过滤,将张字开头的添加到listA集合中
// 对listA集合过滤,只要名字长度为3的
// 遍历listB集合,打印输出
list.stream()
.filter(name -> name.startsWith("张"))
.filter(name -> name.length() == 3)
.forEach(name -> System.out.println(name));
}
}
概要1.2ストリーミングの思考
注:伝統的なIOは、固有の印象をストリーム忘れてください!
filter
、map
、skip
関数モデルの操作であり、要素のセットは、実際に処理されていません。この方法の終わり場合にのみcount
実行されると、全体の動作は、モデル指定されたポリシーに従って実行されるであろう。ラムダ特性の実現の遅れのおかげ。
注:「ストリームフローは、」実際にモデル関数の要素の集合であり、それが設定されていない、データ構造ではなく、それ自体で任意の要素(またはアドレス値)を記憶していません
流れ(フロー)は、データ・ソース・キューからの要素であります
- 要素は、キューが形成され、オブジェクトの特定のタイプです。Javaの流れの中や要素を格納しませんが、オンデマンド・コンピューティング。
- データソースソースストリーム。そのような配列として収集することができます。
コレクション異なる前の操作、ストリーム操作二つの基本的な特徴があります。
- PIPELINING:中間の操作は、ストリームオブジェクト自体を返します。このような動作は、フロースタイル(FL uentスタイル)として、パイプの複数の直列に接続されていてもよいです。これは、遅延実行(怠惰)、短絡(ショート)など、動作を最適化します。
- 内部の反復:コレクションをトラバースする方法について過去にするか、イテレータのために強化されたが、集約外部反復で明示的に、これは外部の反復と呼ばれています。ストリームは、反復フロートラバーサルメソッド内の方法は、直接呼び出すことができます提供します。
(データソースを取得する(ソース)→→元、新しいストリームオブジェクト戻りを変更しない各ストリームオブジェクトを変換し、所望の結果を得るために、データ変換動作を実行した時間の流れは、典型的には3つの基本的なステップを含む場合導管へ鎖それらと同様の操作を許可するように構成することができる複数の変換)があってもよいです。
1.3取得の流れ
- java.util.stream.Streamは、
<T>
最も一般的なストリームインタフェースのJava 8の新規参入です。(これは、関数のインタフェースではありません。)
非常にシンプルなのストリームを取得し、いくつかの一般的な方法があります。
- すべての
Collection
コレクションはを通じて利用可能なstream
取得ストリームのデフォルトの方法。- デフォルトのストリーム
<E>
ストリーム()
- デフォルトのストリーム
- ストリームインタフェースの静的メソッド、対応するストリームの配列を取得することができます。
- 静的
<T>
ストリーム<T>
の(T ...値) - パラメータは変数パラメータであり、我々は配列を渡すことができます。
- 静的
- 例:
/*
获取stream流的两种方式
1. 所有Collection集合都可以通过默认方法 stream获取流
2. 可以使用Stream接口中的静态方法,of,将数组转换成流对象
*/
import java.util.*;
import java.util.stream.Stream;
public class Demo03GetStream {
public static void main(String[] args) {
// 把集合转换为Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Map<String, String> map = new HashMap<>();
// 获取键,存储到set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
// 获取值,存储到Collection集合
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
// 获取键值对(键与值的映射关系 entrySet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
// 把数组转换为Stream流
Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
// 可变参数可以传递数组
Integer[] arr = {1, 3, 4, 5};
Stream<Integer> stream7 = Stream.of(arr);
String[] arr2 = {"a", "b", "c", "d"};
Stream<String> stream8 = Stream.of(arr2);
}
}
1.4一般的な方法
二つの方法に分けることができ、非常に豊富な操作フローモデル、:
- 遅延方法:戻り値の型がまだある
Stream
メソッドインタフェース、チェーン通話のためのサポートの独自のタイプ。(ターミネーション法を除き、他の方法が遅延されます。) - メソッドの終了:戻り値の型は、もはやある
Stream
メソッド・インターフェースの独自の種類、したがって同様のサポートしませんStringBuilder
チェーンのコールの種類を。このセクションでは、本方法は終了含むcount
とforEach
方法を。
①は1ずつ処理:forEachの
名前のforEachが、しかし、forループのために、それぞれ異なります。
- 空のforEach(コンシューマー・アクション<スーパーT?>);
- この方法は、消費者インターフェース機能を受信し、各ストリームは、プロセスに要素を機能します。
- 消費者インタフェースは、消費者インタフェースの関数であり、あなたは、ラムダ式、消費データを渡すことができます。
Jotのは:
データ・ストリームを横断するためのforEachメソッドは、メソッドの最後で、トラバーサルの後に他の方法ストリームstreamを呼び出すために継続することはできません。
- 例:
import java.util.stream.Stream;
public class Demo04ForEach {
public static void main(String[] args) {
// 获取一个Stream流
Stream<String> stream = Stream.of("迪丽热巴", "古力娜扎", "马儿扎哈");
// 使用forEach,参数传递Lambda表达式
/*stream.forEach((String name) -> {
System.out.println(name);
});*/
// 优化Lambda表达式
stream.forEach(name -> System.out.println(name));
}
}
/*
print result:
迪丽热巴
古力娜扎
马儿扎哈
*/
②フィルタ:フィルタ
- フィルタ:データストリームのストリームをフィルタリングします。
- ストリーム
フィルタ(<?スーパーT>述語述語)。 - 述語フィルタメソッドのパラメータは、ラムダ式は、データのフィルタリングを転送することができ、機能インタフェースです。
- 述語抽象メソッド:
boolean test(T t);
- 例:
import java.util.stream.Stream;
// Stream<T> filter(Predicate<? super T> predicate);
public class Demo05Filter {
public static void main(String[] args) {
// 获取Stream流
Stream<String> stream = Stream.of("张三丰", "张三疯", "周芷若", "赵敏", "张翠山");
// 使用 filter方法进行过滤
// stream.filter((String name) -> {name.startsWith("张");});
// 使用 filter之后,返回一个新的流
Stream<String> newStream = stream.filter(name -> name.startsWith("张"));
// 逐一输出
newStream.forEach(name -> System.out.println(name));
/*
Stream流属于管道流,只能被消费(使用)一次
第一个Stream流调用完毕,数据就会流到下一个Stream上
而这时第一个Stream流已经使用完毕,就会关闭了
所以第一个Stream流就不能再调用方法了
IllegalStateException: stream has already been operated upon or closed
*/
// 已经被使用一次了,再次使用会抛出异常
// stream.forEach(name -> System.out.println(name));
}
}
③マッピング:マップ
- あなたが別のフロー要素マップに流れるように必要がある場合は、マップ・メソッドを使用することができます。
<R>
ストリーム<R>
マップ(関数マッパー<スーパーTは,? Rを拡張します?>);- インタフェースは、機能インターフェイスパラメータを必要とする関数、タイプTは別のストリームのRタイプに現在のデータ・ストリームを変換することができます。
- 抽象メソッドの機能:
R apply(T t);
- 例:
import java.util.stream.Stream;
public class Demo06Map {
public static void main(String[] args) {
// 获取一个String类的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
// 将String类型的整数,转换(映射)为 Integer类型的整数
Stream<Integer> stream2 = stream.map((String s) -> {
return Integer.parseInt(s);
});
// 遍历 stream2流
stream2.forEach(num -> System.out.println(num));
}
}
数:数を数える④
古いセットとCollection
の間でsize
のような方法をStream
提供するcount
要素の数が取得する前記方法。
- カウント:フロー内の要素数のストリームの統計情報を。
long count();
カウント方法は、メソッドの最後で、戻り値は、長整数型なので、あなたは、ストリームの流れの他のメソッドを呼び出すことはできません。
例:
import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo07Count {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Stream<Integer> stream = list.stream();
long count = stream.count();
System.out.println(count);
}
}
⑤最初の数へのアクセス:制限
- 制限:ストリームを傍受するための要素。
- この方法は、対流制限、アクセスのみ最初のnを取ることができます。
Stream<T> limit(long maxSize);
- パラメータは、長い長さは、パラメータの現在の設定よりも大きい場合、それは切り捨てられ、種類、そうでなければ、何も動作は行われません。
限界がある遅らせる方法取ら対流内の要素だけを、それが他の方法ストリームストリームを起動し続けることができ、新たなストリームを返します。
例:
import java.util.Arrays;
import java.util.stream.Stream;
public class Demo08Limit {
public static void main(String[] args) {
String[] arr = {"喜羊羊", "美羊羊", "暖羊羊", "灰太狼", "红太狼"};
Stream<String> stream = Arrays.stream(arr);
Stream<String> stream2 = stream.limit(3); // 截取前3个元素,并返回新的Stream流
stream2.forEach(name -> System.out.println(name));
}
}
⑥最初の数をスキップ:スキップ
- スキップ:スキップする要素を、
- あなたが最初の数の要素をスキップしたい場合は、この方法が取られた後、新たなスキップ・ストリームを取得するために使用することができます。
- ストリームは、
<T>
(長いn)はスキップ。- 流れの長さがnよりも大きい場合、Nは前スキップ、それ以外の場合は0の長さを与える空のストリームです。
import java.util.stream.Stream;
public class Demo09Skip {
public static void main(String[] args) {
String[] arr = {"喜羊羊", "美羊羊", "暖羊羊", "灰太狼", "红太狼"};
Stream<String> stream = Stream.of(arr);
// 跳过前3个
Stream<String> stream2 = stream.skip(3);
stream2.forEach(name -> System.out.println(name));
}
}
⑦組み合わせ:連結
- 連結:フローのために一緒に組み合わせます。
- 望ましい一つのストリームに結合二つの流れがある場合は、使用することができます
Stream
静的メソッドのインターフェースをconcat
- パブリック静的
ストリーム CONCAT(ストリームは、ストリームが<?Tを延長> <?Tが延びる> B) - 例:
import java.util.stream.Stream;
/*
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
*/
public class Demo10Concat {
public static void main(String[] args) {
String[] arr = {"喜羊羊", "美羊羊", "暖羊羊", "灰太狼", "红太狼"};
Stream<String> stream1 = Stream.of(arr);
Stream<String> stream2 = Stream.of("张三丰", "张三疯", "周芷若", "赵敏", "张翠山");
// 把以上两个流组合成为一个流
Stream<String> concat = Stream.concat(stream1, stream2);
// 遍历输出
concat.forEach(name -> System.out.println(name));
}
}
運動1.5:要素のセットを処理(従来の)
import java.util.ArrayList;
/*
题目:
现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以下若干操作步骤:
练习:集合元素处理(传统方式)
现在有两个ArrayList集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
5. 将两个队伍合并为一个队伍;存储到一个新集合中。
6. 根据姓名创建Person对象;存储到一个新集合中。
7. 打印整个队伍的Person对象信息。
*/
public class DemoStreamTest {
public static void main(String[] args) {
//第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
// 1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
ArrayList<String> oneA = new ArrayList<>();
for (String name : one) {
if (name.length() == 3) {
oneA.add(name);
}
}
// 2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
ArrayList<String> oneB = new ArrayList<>();
for (int i = 0; i < 3; i++) {
oneB.add(oneA.get(i));
}
//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
// 3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
ArrayList<String> twoA = new ArrayList<>();
for (String name : two) {
if (name.startsWith("张")) {
twoA.add(name);
}
}
// 4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
ArrayList<String> twoB = new ArrayList<>();
for (int i = 2; i < twoA.size(); i++) {
twoB.add(twoA.get(i));
}
// 5. 将两个队伍合并为一个队伍;存储到一个新集合中。
ArrayList<String> all = new ArrayList<>();
all.addAll(twoB);
all.addAll(oneB);
// 6. 根据姓名创建Person对象;存储到一个新集合中。
ArrayList<Person> list = new ArrayList<>();
for (String s : all) {
list.add(new Person(s));
}
for (Person person : list) {
System.out.println(person);
}
}
}
1.6演習:処理要素のコレクション(ストリームストリームモード)
import java.util.ArrayList;
import java.util.stream.Stream;
/*
题目:
现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以下若干操作步骤:
练习:集合元素处理(传统方式)
现在有两个ArrayList集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
5. 将两个队伍合并为一个队伍;存储到一个新集合中。
6. 根据姓名创建Person对象;存储到一个新集合中。
7. 打印整个队伍的Person对象信息。
*/
public class DemoStreamTest2 {
public static void main(String[] args) {
//第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
// 1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
// 2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);
//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
// 3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
// 4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);
// 5. 将两个队伍合并为一个队伍;存储到一个新集合中。
// 6. 根据姓名创建Person对象;存储到一个新集合中。
// 7. 打印整个队伍的Person对象信息。
Stream.concat(oneStream, twoStream).map(name -> new Person(name)).forEach(name-> System.out.println(name));
}
}
2.参照方法
2.1一般的な紹介
二重コロンは、::
基準演算子であり、それは式で参照されるメソッド参照。ラムダに既に存在発現される機能プログラムは、方法を実装した場合、本方法は、二重コロンでラムダ代替として挙げることができます。
- Printableインタフェース
/*
定义一个打印的函数式接口
*/
@FunctionalInterface
public interface Printable {
// 对字符串的抽象方法
public abstract void print(String s);
}
- Demo01Printable.java
public class Demo01Printable {
// 定义一个方法,参数传递Printable接口,对字符串进行打印
public static void printString(Printable p) {
p.print("HelloWorld");
}
public static void main(String[] args) {
printString((s) -> {
System.out.println(s);
});
/*
分析:
Lambda表达式的目的:打印参数传递的字符串
把参数 s 传递给 System.out对象,调用 out对象中的方法println对字符串输出
使用前提(注意):
1.System.out对象已经存在。
2.println方法也是存在的。
所以我们可以直接使用方法引用来优化 Lambda表达式
可以使用System.out方法直接引用(调用)println方法
*/
printString(System.out::println);
}
}
意味解析
例の実施形態では、System.out
対象は、すでに過負荷にprint(String x)
我々が、その後必要なものだけの方法をprintString
完全に同等以下の二つの方法を比較し、機能的なインタフェースパラメータの方法:
- ラムダ書かれた:S - >のSystem.out.println(S);
- メソッド引用文言:System.outに::のprintln();
- セマンティック手段のうちの第一種:ラムダ手によってパラメータの後に取得するには、その後に渡さ
System.out.println()
処理する方法。 - 第二等価セマンティック手段:から直接ラムダ置換方法。第2の方法は、より簡潔な既存のプログラムを再利用引用しながら、両方のバージョンは、全く同じ作用を行います。
System.out
println
注:
この方法は、ラムダタイプを受け取ることができ、特定の手法に渡されるパラメータで引用し、それ以外の場合は、例外がスローされます。
2.2オブジェクト名によって参照方法[メンバー]
- Printableインタフェース
/*
定义一个打印的函数式接口
*/
@FunctionalInterface
public interface Printable {
// 对字符串的抽象方法
public abstract void print(String s);
}
- MethodRefObject.java
public class MethodRefObject {
// 定义一个成员方法,参数传递字符串,将字符串大写输出
public void printUpperCaseString(String s) {
System.out.println(s.toUpperCase());
}
}
- DemoObjectMethodReference.java
public class DemoObjectMethodReference {
// 定义一个方法,参数传递Printable接口
public static void printString(Printable p) {
p.print("Hello Java");
}
public static void main(String[] args) {
printString((s) -> {
MethodRefObject obj = new MethodRefObject();
obj.printUpperCaseString(s);
});
/*
使用方法引用对Lambda进行优化
使用前提:对象和成员方法已经存在
*/
// 创建对象
MethodRefObject obj = new MethodRefObject();
printString(obj::printUpperCaseString);
}
}
2.3クラス名によって参照] [静的メソッド
- Calcableインタフェース
public interface Calcable {
// 定义一个抽象方法,参数传递一个整数,进行取模运算
public int methodAbs(int num);
}
- DemoStaticMethodRef.java
public class DemoStaticMethodRef {
// 定义一个方法,参数传递一个int型整数,一个Calcalbe接口
public static int method(int num, Calcable c) {
return c.methodAbs(num);
}
public static void main(String[] args) {
// 调用method方法,传递一个整数,取模运算
int num = method(-10, (n) -> {
return Math.abs(n);
});
System.out.println(num);
/*
通过类名称引用静态成员方法的前提:
1. 类存在
2. 静态成员方法存在且已经实现了
*/
int num2 = method(-100, Math::abs);
System.out.println(num2);
}
}
2.4スーパーの親クラスの共通の基準部材
- Greetableインタフェース
// 定义一个问候的接口
public interface Greetable {
public abstract void greet();
}
- Fu.java
public class Fu {
// 定义一个sayHello方法
public void sayHello() {
System.out.println("我是师父");
}
}
- Zi.java
/*
通过super引用父类的普通成员方法
*/
public class Zi extends Fu {
// 覆盖重写父类的 sayHello方法
@Override
public void sayHello() {
System.out.println("我是徒弟");
}
// 定义一个方法,参数传递Greetable接口
public void method(Greetable g) {
g.greet();
}
// 展示输出的方法,参数传递一个Greetable接口
public void show() {
/*method(() -> {
Fu fu = new Fu();
fu.sayHello();
});*/
// method(() -> super.sayHello());
method(super::sayHello);
}
}
- mainメソッド
public class DemoMain {
public static void main(String[] args) {
new Zi().show();
}
}
2.5現在のクラスメソッドの通常のメンバーによってこの参照
- Richableインタフェース
public interface Richable {
// 定义一个买东西的方法
public abstract void buy();
}
- Husband.java
public class Husband {
// 定义买房子的方法
public void buyHouse() {
System.out.println("杭州一套小楼!");
}
// 定义结婚的方法, 参数传递Richable接口
public void marry(Richable r) {
r.buy();
}
// 高兴方法,因为要结婚
public void soHappy() {
// this.marry(() -> {this.buyHouse();});
/*
this和调用的本类成员方法已经存在且实现
可以使用this引用本类的成员方法
*/
marry(this::buyHouse);
}
public static void main(String[] args) {
new Husband().soHappy();
}
}
引用された2.6クラスコンストラクタ(コンストラクタ)
- PersonBuilderインタフェース
@FunctionalInterface
public interface PersonBuilder {
// 定义方法,用来根据传递的姓名,创建Person对象,并返回
public abstract Person builderPerson(String name);
}
- DemoPerson.java
public class DemoPerson {
// 定义一个方法,参数传递姓名和PersonBuilder接口,打印对象姓名
public static void printName(String name, PersonBuilder pb) {
Person person = pb.builderPerson(name);
System.out.println(person);
}
public static void main(String[] args) {
// printName("迪丽热巴", (s) -> new Person(s));
/*
使用方法引用优化Lambda表达式
构造方法:new Person(String name);已知
创建对象:new 已知
就可以使用Person引用new创建对象
*/
printName("周元", Person::new); // 使用Person类的带参构造方法,创建对象
}
}
アレイに2.7コンストラクタ参照
- ArrayBuilderインタフェース
/*
数组创建接口
*/
@FunctionalInterface
public interface ArrayBuilder {
// 根据参数传递的长度,创建int型指定长度的数组
public abstract int[] builderArray(int length);
}
- DemoArray.java
import java.util.Arrays;
public class DemoArray {
/*
定义一个方法,参数传递要创建数组的长度和ArrayBuilder接口
方法内部传递的长度使用ArrayBuilder中的方法创建数组并返回
*/
public static int[] creatArray(int length, ArrayBuilder ab) {
return ab.builderArray(length);
}
public static void main(String[] args) {
int[] arrA = creatArray(10, (len) -> new int[len]);
System.out.println(Arrays.toString(arrA));
System.out.println(arrA.length);
/*
创建的是 int[] 类型的数组
数组的长度已知
使用 int[]引用new,根据传递的长度创建数组
*/
int[] arrB = creatArray(10, int[]::new);
System.out.println(arrB.length);
}
}