1.不可變集合
1.1 什么是不可變集合
? 是一個(gè)長(zhǎng)度不可變,內(nèi)容也無法修改的集合
1.2 使用場(chǎng)景
? 如果某個(gè)數(shù)據(jù)不能被修改,把它防御性地拷貝到不可變集合中是個(gè)很好的實(shí)踐。
? 當(dāng)集合對(duì)象被不可信的庫調(diào)用時(shí),不可變形式是安全的。
簡(jiǎn)單理解:
? 不想讓別人修改集合中的內(nèi)容
比如說:
1,斗地主的54張牌,是不能添加,不能刪除,不能修改的
2,斗地主的打牌規(guī)則:?jiǎn)螐?,?duì)子,三張,順子等,也是不能修改的
3,用代碼獲取的操作系統(tǒng)硬件信息,也是不能被修改的
1.3 不可變集合分類
- 不可變的list集合
- 不可變的set集合
- 不可變的map集合
1.4 不可變的list集合
public class ImmutableDemo1 {
public static void main(String[] args) {
/*
創(chuàng)建不可變的List集合
"張三", "李四", "王五", "趙六"
*/
//一旦創(chuàng)建完畢之后,是無法進(jìn)行修改的,在下面的代碼中,只能進(jìn)行查詢操作
List<String> list = List.of("張三", "李四", "王五", "趙六");
System.out.println(list.get(0));
System.out.println(list.get(1));
System.out.println(list.get(2));
System.out.println(list.get(3));
System.out.println("---------------------------");
for (String s : list) {
System.out.println(s);
}
System.out.println("---------------------------");
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("---------------------------");
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
System.out.println("---------------------------");
//list.remove("李四");
//list.add("aaa");
list.set(0,"aaa");
}
}
1.5 不可變的Set集合
public class ImmutableDemo2 {
public static void main(String[] args) {
/*
創(chuàng)建不可變的Set集合
"張三", "李四", "王五", "趙六"
細(xì)節(jié):
當(dāng)我們要獲取一個(gè)不可變的Set集合時(shí),里面的參數(shù)一定要保證唯一性
*/
//一旦創(chuàng)建完畢之后,是無法進(jìn)行修改的,在下面的代碼中,只能進(jìn)行查詢操作
Set<String> set = Set.of("張三", "張三", "李四", "王五", "趙六");
for (String s : set) {
System.out.println(s);
}
System.out.println("-----------------------");
Iterator<String> it = set.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("-----------------------");
//set.remove("王五");
}
}
1.6 不可變的Map集合
1.6.1:鍵值對(duì)個(gè)數(shù)小于等于10
public class ImmutableDemo3 {
public static void main(String[] args) {
/*
創(chuàng)建Map的不可變集合
細(xì)節(jié)1:
鍵是不能重復(fù)的
細(xì)節(jié)2:
Map里面的of方法,參數(shù)是有上限的,最多只能傳遞20個(gè)參數(shù),10個(gè)鍵值對(duì)
細(xì)節(jié)3:
如果我們要傳遞多個(gè)鍵值對(duì)對(duì)象,數(shù)量大于10個(gè),在Map接口中還有一個(gè)方法
*/
//一旦創(chuàng)建完畢之后,是無法進(jìn)行修改的,在下面的代碼中,只能進(jìn)行查詢操作
Map<String, String> map = Map.of("張三", "南京", "張三", "北京", "王五", "上海",
"趙六", "廣州", "孫七", "深圳", "周八", "杭州",
"吳九", "寧波", "鄭十", "蘇州", "劉一", "無錫",
"陳二", "嘉興");
Set<String> keys = map.keySet();
for (String key : keys) {
String value = map.get(key);
System.out.println(key + "=" + value);
}
System.out.println("--------------------------");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
System.out.println("--------------------------");
}
}
1.6.2:鍵值對(duì)個(gè)數(shù)大于10
public class ImmutableDemo4 {
public static void main(String[] args) {
/*
創(chuàng)建Map的不可變集合,鍵值對(duì)的數(shù)量超過10個(gè)
*/
//1.創(chuàng)建一個(gè)普通的Map集合
HashMap<String, String> hm = new HashMap<>();
hm.put("張三", "南京");
hm.put("李四", "北京");
hm.put("王五", "上海");
hm.put("趙六", "北京");
hm.put("孫七", "深圳");
hm.put("周八", "杭州");
hm.put("吳九", "寧波");
hm.put("鄭十", "蘇州");
hm.put("劉一", "無錫");
hm.put("陳二", "嘉興");
hm.put("aaa", "111");
//2.利用上面的數(shù)據(jù)來獲取一個(gè)不可變的集合
/*
//獲取到所有的鍵值對(duì)對(duì)象(Entry對(duì)象)
Set<Map.Entry<String, String>> entries = hm.entrySet();
//把entries變成一個(gè)數(shù)組
Map.Entry[] arr1 = new Map.Entry[0];
//toArray方法在底層會(huì)比較集合的長(zhǎng)度跟數(shù)組的長(zhǎng)度兩者的大小
//如果集合的長(zhǎng)度 > 數(shù)組的長(zhǎng)度 :數(shù)據(jù)在數(shù)組中放不下,此時(shí)會(huì)根據(jù)實(shí)際數(shù)據(jù)的個(gè)數(shù),重新創(chuàng)建數(shù)組
//如果集合的長(zhǎng)度 <= 數(shù)組的長(zhǎng)度:數(shù)據(jù)在數(shù)組中放的下,此時(shí)不會(huì)創(chuàng)建新的數(shù)組,而是直接用
Map.Entry[] arr2 = entries.toArray(arr1);
//不可變的map集合
Map map = Map.ofEntries(arr2);
map.put("bbb","222");*/
//Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));
Map<String, String> map = Map.copyOf(hm);
map.put("bbb","222");
}
}
2.方法引用
2.1體驗(yàn)方法引用
-
方法引用的出現(xiàn)原因
在使用Lambda表達(dá)式的時(shí)候,我們實(shí)際上傳遞進(jìn)去的代碼就是一種解決方案:拿參數(shù)做操作
那么考慮一種情況:如果我們?cè)贚ambda中所指定的操作方案,已經(jīng)有地方存在相同方案,那是否還有必要再寫重復(fù)邏輯呢?答案肯定是沒有必要
那我們又是如何使用已經(jīng)存在的方案的呢?
這就是我們要講解的方法引用,我們是通過方法引用來使用已經(jīng)存在的方案
-
代碼演示
public interface Printable { void printString(String s); } public class PrintableDemo { public static void main(String[] args) { //在主方法中調(diào)用usePrintable方法 // usePrintable((String s) -> { // System.out.println(s); // }); //Lambda簡(jiǎn)化寫法 usePrintable(s -> System.out.println(s)); //方法引用 usePrintable(System.out::println); } private static void usePrintable(Printable p) { p.printString("愛生活愛Java"); } }
2.2方法引用符
-
方法引用符
:: 該符號(hào)為引用運(yùn)算符,而它所在的表達(dá)式被稱為方法引用
-
推導(dǎo)與省略
- 如果使用Lambda,那么根據(jù)“可推導(dǎo)就是可省略”的原則,無需指定參數(shù)類型,也無需指定的重載形式,它們都將被自動(dòng)推導(dǎo)
- 如果使用方法引用,也是同樣可以根據(jù)上下文進(jìn)行推導(dǎo)
- 方法引用是Lambda的孿生兄弟
2.3引用類方法
? 引用類方法,其實(shí)就是引用類的靜態(tài)方法
-
格式
類名::靜態(tài)方法
-
范例
Integer::parseInt
Integer類的方法:public static int parseInt(String s) 將此String轉(zhuǎn)換為int類型數(shù)據(jù)
-
練習(xí)描述
- 定義一個(gè)接口(Converter),里面定義一個(gè)抽象方法 int convert(String s);
- 定義一個(gè)測(cè)試類(ConverterDemo),在測(cè)試類中提供兩個(gè)方法
- 一個(gè)方法是:useConverter(Converter c)
- 一個(gè)方法是主方法,在主方法中調(diào)用useConverter方法
-
代碼演示
public interface Converter { int convert(String s); } public class ConverterDemo { public static void main(String[] args) { //Lambda寫法 useConverter(s -> Integer.parseInt(s)); //引用類方法 useConverter(Integer::parseInt); } private static void useConverter(Converter c) { int number = c.convert("666"); System.out.println(number); } }
-
使用說明
Lambda表達(dá)式被類方法替代的時(shí)候,它的形式參數(shù)全部傳遞給靜態(tài)方法作為參數(shù)
2.4引用對(duì)象的實(shí)例方法
? 引用對(duì)象的實(shí)例方法,其實(shí)就引用類中的成員方法
-
格式
對(duì)象::成員方法
-
范例
“HelloWorld”::toUpperCase
String類中的方法:public String toUpperCase() 將此String所有字符轉(zhuǎn)換為大寫
-
練習(xí)描述
-
定義一個(gè)類(PrintString),里面定義一個(gè)方法
public void printUpper(String s):把字符串參數(shù)變成大寫的數(shù)據(jù),然后在控制臺(tái)輸出
-
定義一個(gè)接口(Printer),里面定義一個(gè)抽象方法
void printUpperCase(String s)
-
定義一個(gè)測(cè)試類(PrinterDemo),在測(cè)試類中提供兩個(gè)方法
- 一個(gè)方法是:usePrinter(Printer p)
- 一個(gè)方法是主方法,在主方法中調(diào)用usePrinter方法
-
-
代碼演示
public class PrintString { //把字符串參數(shù)變成大寫的數(shù)據(jù),然后在控制臺(tái)輸出 public void printUpper(String s) { String result = s.toUpperCase(); System.out.println(result); } } public interface Printer { void printUpperCase(String s); } public class PrinterDemo { public static void main(String[] args) { //Lambda簡(jiǎn)化寫法 usePrinter(s -> System.out.println(s.toUpperCase())); //引用對(duì)象的實(shí)例方法 PrintString ps = new PrintString(); usePrinter(ps::printUpper); } private static void usePrinter(Printer p) { p.printUpperCase("HelloWorld"); } }
-
使用說明
Lambda表達(dá)式被對(duì)象的實(shí)例方法替代的時(shí)候,它的形式參數(shù)全部傳遞給該方法作為參數(shù)
2.5引用類的實(shí)例方法
? 引用類的實(shí)例方法,其實(shí)就是引用類中的成員方法
-
格式
類名::成員方法
-
范例
String::substring
public String substring(int beginIndex,int endIndex)
從beginIndex開始到endIndex結(jié)束,截取字符串。返回一個(gè)子串,子串的長(zhǎng)度為endIndex-beginIndex
-
練習(xí)描述
-
定義一個(gè)接口(MyString),里面定義一個(gè)抽象方法:
String mySubString(String s,int x,int y);
-
定義一個(gè)測(cè)試類(MyStringDemo),在測(cè)試類中提供兩個(gè)方法
- 一個(gè)方法是:useMyString(MyString my)
- 一個(gè)方法是主方法,在主方法中調(diào)用useMyString方法
-
-
代碼演示
public interface MyString { String mySubString(String s,int x,int y); } public class MyStringDemo { public static void main(String[] args) { //Lambda簡(jiǎn)化寫法 useMyString((s,x,y) -> s.substring(x,y)); //引用類的實(shí)例方法 useMyString(String::substring); } private static void useMyString(MyString my) { String s = my.mySubString("HelloWorld", 2, 5); System.out.println(s); } }
-
使用說明
? Lambda表達(dá)式被類的實(shí)例方法替代的時(shí)候
? 第一個(gè)參數(shù)作為調(diào)用者
? 后面的參數(shù)全部傳遞給該方法作為參數(shù)
2.6引用構(gòu)造器
? 引用構(gòu)造器,其實(shí)就是引用構(gòu)造方法
-
l格式
類名::new
-
范例
Student::new
-
練習(xí)描述
-
定義一個(gè)類(Student),里面有兩個(gè)成員變量(name,age)
并提供無參構(gòu)造方法和帶參構(gòu)造方法,以及成員變量對(duì)應(yīng)的get和set方法
-
定義一個(gè)接口(StudentBuilder),里面定義一個(gè)抽象方法
Student build(String name,int age);
-
定義一個(gè)測(cè)試類(StudentDemo),在測(cè)試類中提供兩個(gè)方法
- 一個(gè)方法是:useStudentBuilder(StudentBuilder s)
- 一個(gè)方法是主方法,在主方法中調(diào)用useStudentBuilder方法
-
-
代碼演示
public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public interface StudentBuilder { Student build(String name,int age); } public class StudentDemo { public static void main(String[] args) { //Lambda簡(jiǎn)化寫法 useStudentBuilder((name,age) -> new Student(name,age)); //引用構(gòu)造器 useStudentBuilder(Student::new); } private static void useStudentBuilder(StudentBuilder sb) { Student s = sb.build("林青霞", 30); System.out.println(s.getName() + "," + s.getAge()); } }
-
使用說明
Lambda表達(dá)式被構(gòu)造器替代的時(shí)候,它的形式參數(shù)全部傳遞給構(gòu)造器作為參數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-723889.html
后記
????????美好的一天,到此結(jié)束,下次繼續(xù)努力!欲知后續(xù),請(qǐng)看下回分解,寫作不易,感謝大家的支持??! ??????文章來源地址http://www.zghlxwxcb.cn/news/detail-723889.html
到了這里,關(guān)于從零開始學(xué)習(xí) Java:簡(jiǎn)單易懂的入門指南之不可變集合、方法引用(二十六)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!