這裡寫目錄标題
- 屬性集
-
- API
-
- 加載屬性集
- setProperty
- getProperty
- stringPropertyNames
- 函數式接口
-
- 常用函數式接口
-
- Supplier
- Consumer
- Predicate
- Function
屬性集
Properties, 僅支援String類型的屬性映射
extends Hashtable implements Map
key - value
API
加載屬性集
void load(Reader)
void load(InputStream)
// 1.建立屬性集對象
Properties pro = new Properties();
// "root" "root"
// 2.通過流加載屬性集
方法一 String path = DemoProperties.class.getClassLoader().getResource("config.properties").getPath();
pro.load(new FileInputStream(path));
方法二 //此時類在package下,而properties檔案在src根目錄下,要加.getClassLoader()
InputStream is = DemoProperties.class.getClassLoader().getResourceAsStream("config.properties");
pro.load(is);
setProperty
public Object setProperty(String key, String value) :儲存⼀對屬性。
注意:隻是臨時的,檔案中的value并不會改變
// 4.直接給屬性集設定屬性
pro.setProperty("url", "http://www.baidu.com");
String url = pro.getProperty("url");
System.out.println(url);
getProperty
public String getProperty(String key) :使⽤此屬性清單中指定的鍵搜尋屬性值
// 3.獲得屬性集中的value值
String name = pro.getProperty("name");
System.out.println(name);
stringPropertyNames
public Set stringPropertyNames() :所有鍵的名稱的集合。
函數式接口
(JDK8的特性)
接口中隻有一個抽象方法
函數式程式設計: Lambda表達式(函數式接口作為方法的參數)
常用函數式接口
Supplier
生産者 - T get();
/*
為了使用Lambda表達式, 是以将Supplier作為方法參數使用
方法的目的: 為了傳回一個字元串對象
*/
public static String getInstance(Supplier<String> sup) {
// 調用Supplier 的get方法
return sup.get();
}
public static void main(String[] args) {
// 調用getInstance方法, 需要傳遞一個Supplier接口實作類
// 又因為Supplier接口是函數式接口, 是以可以使用Lambda表達式
String str = getInstance(() -> {
// 這是生産字元串的過程
return "hello";});
System.out.println(str);
}
/**
* 傳入一個數組, 獲得數組的最大值并傳回
* 還要使用Supplier這個接口
*/
public static int getMax(Supplier<Integer> sup) {
return sup.get();
}
public static void main(String[] args) {
int[] arr = {98, 23, 16, 34, 72};
int m = getMax(() -> {
int max = 0;
for(int i : arr) {
if (max < i) {
max = i;
}
}
return max;
});
System.out.println(m);
}
Consumer
消費者 - void accept(T t); 使用這個對象
/*
為了使用Lambda表達式, 需要将Consumer接口作為方法參數
因為Consumer接口的accept方法需要一個對象來消費, 是以再多傳入一個String參數
*/
public static void toUpper(String str, Consumer<String> consumer) {
consumer.accept(str);
}
public static void main(String[] args) {
toUpper("hello", s -> {
// 在這裡寫消費/使用這個s對象的代碼
// 我的消費方式: 将 s 進行反轉
String str = new StringBuilder(s).reverse().toString();
System.out.println(str);
});
s的由來:
/*new Consumer<String>(){
@Override
public void accept(String s) {
}
};*/
}
預設方法 - andThen(Consumer) -将兩個消費方式組合在一塊
/**
* 因為要使用andThen方法, 是以需要兩個Consumer對象
* 并且accept方法需要消費一個對象, 是以還需要一個String對象
*/
public static void methodAndThen(String str, Consumer<String> con1, Consumer<String> con2) {
con1.andThen(con2).accept(str);
}
public static void main(String[] args) {
methodAndThen("JavaGood",
// 第一次消費, 将字元串全部變大寫, 并且列印
s -> {
System.out.println(s.toUpperCase());
},
// 第2次消費, 将字元串全部變小寫, 并且列印
s -> {
System.out.println(s.toLowerCase());
});
}
消費案例
/**
* 請按照格式“ 姓名:XX。性别:XX。 ”的格式将資訊列印出 來
* str: "迪麗熱巴,女"
* 第一次消費: 姓名:迪麗熱巴.
* 第二次消費: 性别:女.
*/
public static void transfer(String str, Consumer<String> con1, Consumer<String> con2) {
con1.andThen(con2).accept(str);
}
public static void main(String[] args) {
String[] array = { "迪麗熱巴,女", "古力娜紮,女", "⻢爾紮哈,男" };
for (String str : array) {
transfer(str, s -> { // 姓名:迪麗熱巴.
String name = s.split(",")[0];
System.out.print("姓名: " + name + ". ");
}, s->{
String sex = s.split(",")[1];
System.out.println("性别: " + sex + ". ");
});
}
}
Predicate
對對象做判斷 - boolean test(T t);
public static void method01(String str, Predicate<String> pre) {
boolean b = pre.test(str);
System.out.println(b);
}
public static void main(String[] args) {
method01("張靓穎", (s) -> {
return s.length() == 2;
});
}
and(&&)
public static void strPredicate(String str, Predicate<String> pre1, Predicate<String> pre2) {
boolean b = pre1.and(pre2).test(str);
System.out.println(b);
}
public static void main(String[] args) {
strPredicate("Hello Tony!",
s -> s.length() > 10,
s -> s.startsWith("H"));
}
or(||)
public static void strPredicate(String str, Predicate<String> pre1, Predicate<String> pre2) {
boolean b1 = pre1.or(pre2).test(str);
System.out.println(b1);
}
public static void main(String[] args) {
strPredicate("Hello Tony!",
s -> s.split(" ").length > 0,
s -> s.endsWith("!"));
}
negate(!)
public static void m1(String str, Predicate<String> pre) {
boolean b1 = pre.negate().test(str);
System.out.println(b1);
}
public static void main(String[] args) {
m1("hello Tony !",
s -> s.split(" ")[1].length() > 3);
}
案例——篩選字元串到集合
public static boolean filterName(String str, Predicate<String> p1, Predicate<String> p2) {
boolean b = p1.and(p2).test(str);
return b;
}
public static void main(String[] args) {
String[] array = { "迪麗熱巴,女", "古力娜紮,女", "⻢爾紮哈,男", "趙麗穎,女" };
ArrayList<String> list = new ArrayList<>();
for (String str : array) {
boolean b = filterName(str,
// 1.必須為女生;
s -> s.split(",")[1].equals("女"),
// 2.姓名為4個字。
s -> s.split(",")[0].length() == 4
);
if (b) {
list.add(str);
}
}
System.out.println(list);
}
Function<T, R>
類型轉換 - R apply(T t);
// String -> Integer
public static void change(String str, Function<String, Integer> fun) {
int i = fun.apply(str);
System.out.println(i);
}
public static void main(String[] args) {
change("123", s -> Integer.valueOf(s));
}
預設方法 - andThen(Function)- 連續做兩種類型轉換
// 将 "123" -> 轉換成 int 後 +10
// String->Integer Function<String, Integer>
// 将 加完後的 int 值, 轉換成 String, 16進制的格式
// Integer->String Function<Integer, String>
public static void change(String str,
Function<String, Integer> fun1,
Function<Integer, String> fun2) {
String result = fun1.andThen(fun2).apply(str);
System.out.println(result);
}
public static void main(String[] args) {
change("123",
s -> Integer.valueOf(s) + 10,
i -> Integer.toBinaryString(i));
}
案例
/**
* String str = "趙麗穎, 20";
* 1. 将字元串截取數字年齡部分,得到字元串;
* "趙麗穎, 20" -> "20" Function<String, String>
* 2. 将上一步的字元串轉換成為int類型的數字;
* "20" -> 20 Function<String, Integer>
* 3. 将上一步的int數字累加100,得到結果int數字。
* 20 -> 120 Function<Integer, Integer>
*/
public class Demo03Test {
public static void change(String str, Function<String, String> fun1,
Function<String, Integer> fun2,
Function<Integer, Integer> fun3) {
int i = fun1.andThen(fun2).andThen(fun3).apply(str);
System.out.println(i);
}
public static void main(String[] args) {
change("趙麗穎, 20",
// "趙麗穎, 20" -> "20"
s -> s.split("[, ]+")[1],
// "20" -> 20
s -> Integer.valueOf(s),
// 20 -> 120
i -> i + 100 );
}
}
Stream流
操作 數組或者集合
簡化他們的操作
擷取流對象的方式
單列集合List、Set
// 1.單列集合獲得流對象 List Set
// List -> Stream
List<String> list = List.of("喜羊羊", "美羊羊","懶洋洋","暖洋洋");
Stream<String> streamList = list.stream();
// Set -> Stream
Set<String> set = Set.of("張無忌", "張三豐", "張翠山", "張飛");
Stream<String> streamSet = set.stream();
多列集合Map
// 2.多列集合 Map
Map<Integer, String> map = Map.of(1, "張飛", 2, "關羽", 3, "劉備", 4, "周瑜");
// 獲得map中的key
Set<Integer> keys = map.keySet();
Stream<Integer> streamKey = keys.stream();
// 獲得map中 key-value對 entry
Set<Map.Entry<Integer, String>> entries = map.entrySet();
Stream<Map.Entry<Integer, String>> streamEntry = entries.stream();
// 獲得value部分
Collection<String> values = map.values();
Stream<String> streamValues = values.stream();
數組
// 3.數組獲得Stream流的方式
Integer[] arrInt = {1,2,3,4,5};
Stream<Integer> streamInt = Stream.of(arrInt);
//傳入數組的方式可以使用可變長參數替代
Stream<Integer> streamInt2 = Stream.of(1, 2, 3, 4, 5);
常用API—延遲方法
filter
過濾器
filter(Predicate)
public static void main(String[] args) {
Stream<String> stream = Stream.of("喜羊羊", "張飛", "張三豐", "周瑜", "孫悟空");
/*stream.filter((String s)->{
// 想要保留的對象條件是..
return s.length() == 3;
});*/
// 優化寫法
stream.filter(s-> s.length() == 3)
.forEach(s-> System.out.println(s));
}
map
map(Function)
“映射”,将⼀種T類型轉換成為R類型。
public static void main(String[] args) {
Stream<String> stream = Stream.of("12", "34.5", "65.1", "3.14");
// 将這個 String 轉換成 Integer
/*stream.map((String s)->{return Integer.valueOf(s);});*/
Stream<Double> stream1 = stream.map(s -> Double.valueOf(s));
stream1.forEach(i-> System.out.println(i));
}
concat
組合,合并流
它是一個靜态方法
ublic static void main(String[] args) {
Stream<String> stream1 = Stream.of("喜羊羊", "美羊羊", "懶洋洋", "暖洋洋");
Stream<String> stream2 = Stream.of("張飛", "關羽", "劉備");
// 靜态方法
Stream<String> stream = Stream.concat(stream1, stream2);
stream.forEach(s -> System.out.println(s));
}
limit
limit(long)
skip
skip(long)
常用API—終結方法
forEach
逐⼀處理
它是終結方法,不能在後面繼續調用方法了
它的方法參數是函數式接口Consumer
public static void main(String[] args) {
//傳入數組的方式可以使用可變長參數替代
Stream<String> stream = Stream.of("喜羊羊", "張飛", "張三豐", "周瑜", "孫悟空");
// stream流自帶内部疊代
// forEach 是一個終結方法
stream.forEach((String s) -> {
// 消費這個s對象
s = s.substring(1);
System.out.println(s + "...");
});
}
羊羊...
飛...
三豐...
瑜...
悟空...
count
正如舊集合 Collection 當中的 size ⽅法⼀樣,流提供該⽅法傳回⼀個long值代表元素個數(不再像舊集合那樣是int值)
綜合案例
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
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("洪七公");
//第二支隊伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜紮");
two.add("張無忌");
two.add("趙麗穎");
two.add("張三豐");
two.add("尼古拉斯趙四");
two.add("張天愛");
two.add("張二狗");
// 1. 第一個隊伍隻要名字為3個字的成員姓名;存儲到一個新集合中。
// 2. 第一個隊伍篩選之後隻要前3個人;存儲到一個新集合中。
Stream<String> stream1 = one.stream().filter(name -> name.length() == 3)
.limit(3);
// 3. 第二個隊伍隻要姓張的成員姓名;存儲到一個新集合中。
// 4. 第二個隊伍篩選之後不要前2個人;存儲到一個新集合中。
Stream<String> stream2 = two.stream().filter(name->name.startsWith("張"))
.skip(2);
// 5. 将兩個隊伍合并為一個隊伍;存儲到一個新集合中。
Stream<String> newStream = Stream.concat(stream1, stream2);
// 6. 根據姓名建立Person對象;存儲到一個新集合中。
Stream<Person> personStream = newStream.map(name -> new Person(name));
// 7. 列印整個隊伍的Person對象資訊。
personStream.forEach(p -> System.out.println(p));
}