天天看點

Java day22——屬性集(配置檔案)、常用函數式接口、stream流屬性集函數式接口Stream流

這裡寫目錄标題

  • 屬性集
    • 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);
           
Java day22——屬性集(配置檔案)、常用函數式接口、stream流屬性集函數式接口Stream流

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

Java day22——屬性集(配置檔案)、常用函數式接口、stream流屬性集函數式接口Stream流
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));
    }