属性集, 函数式编程, stream流

  • I/O流小结
  • 1. 属性集
  • 2. 函数式编程
  • 3. stream流

I/O流小结

文件复制:
BufferedInputStream/BufferedOutputStream
文件内容读写:
BufferedReader/PrintWriter
FileReader/FileWriter
对象读写:
ObjectInputStream/ObjectOutputStream

1. 属性集

Properties, 仅支持String类型的属性映射
extends Hashtable implements Map
key - value,
推荐使用的方法
void setProperty(String key, String value)
String getProperty(String key)
加载属性集:
void load(Reader)
void load(InputStream)
代码实现:

public class PropertiesTest {@Test//属性集创建//属性列表为HashTable的子类
// Properties类表示一组持久的属性。 Properties可以保存到流中或从流中加载。属性列表中的每个键及其对应的值都是一个字符串public void propertiesDefine(){//构造一个新的属性集Properties properties = new Properties();//不要使用get/put方法因为可以输入Object对象//添加键值对//键值一般用英文properties.setProperty("价格", "278");//参数只支持String类型properties.setProperty("评分", "特别好评");System.out.println(properties);//获取键对应的值System.out.println( properties.get("价格"));System.out.println( properties.get("评分"));//获取键值列表Set<String> key = properties.stringPropertyNames();//键值遍历for(String k: key) {System.out.println(k + "=" + properties.get(k));}}@Testpublic void read(){//构造一个新的属性集Properties properties = new Properties();//通过流加载属性集//在与类的同一个包中找目标文件String path = PropertiesTest.class.getResource("config.properties").getPath();System.out.println(path);try(FileInputStream fis = new FileInputStream(path);BufferedReader br = new BufferedReader(new InputStreamReader(fis, "gbk"))){//load(InputStream/Reader)properties.load(fis);//从输入字节流读取属性列表(键和元素对)。properties.load(br);//以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。//由于我的文件为gbk编码的,所以默认的ISO8859-1解码方式会生成乱码//如果用中文System.out.println(properties.getProperty("name"));//解决乱码String name = new String(properties.getProperty("name").getBytes("ISO8859-1"), "gbk");System.out.println(name);}catch (IOException e){e.printStackTrace();}}@Testpublic void write(){//构造一个新的属性集Properties properties = new Properties();//键值一般用英文properties.setProperty("name", "怪物猎人世界");properties.setProperty("price", "278");//参数只支持String类型properties.setProperty("review", "特别好评");//通过流打印属性集//在与类的同一个包中找目标文件String path = PropertiesTest.class.getResource("config.properties").getPath();System.out.println(path);try(PrintWriter pw = new PrintWriter(path, "gbk")){//list(PrintWriter/PrintStream)properties.list(pw);//将此属性列表打印到指定的输出流。}catch (IOException e){e.printStackTrace();}}
}

2. 函数式编程

JDK 8 特性
函数式编程: Lambda表达式(函数式接口作为方法的参数)
函数式接口: 接口中只有一个抽象方法
常用函数式接口: Supplier Consumer Predicate Function
Supplier: 生产者 - T get();

import java.util.Scanner;
import java.util.function.Supplier;public class SupplierTest {public static void main(String[] args) {Scanner console = new Scanner(System.in);//Supplier是一个函数式接口,因此可以用作lambda表达式或方法引用的赋值对象。String s = change(new Supplier<String>(){@Overridepublic String get() {return console.nextLine();}});System.out.println(s);//lambda简化s = change(() -> console.nextLine());System.out.println(s);}public static String change(Supplier<String> s){//生产者的意义就是生产对象//使用get方法生产对象,返回值为Supplier的泛型return s.get();};
}

Consumer: 消费者 - void accept(T t); 使用这个对象
默认方法 - andThen(Consumer)
将两个消费方式组合在一块

import java.util.Scanner;
import java.util.function.Consumer;public class ConsumerTest {public static void main(String[] args) {Scanner console = new Scanner(System.in);String s = console.nextLine();toCase(s, new Consumer<String>() {@Override//消费一个参数public void accept(String s) {System.out.println(s.toLowerCase());//全部小写}}, new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s.toUpperCase());//全部大写}});//lambda简化toCase(s, (s1) -> System.out.println(s.toLowerCase()), (s2) -> {System.out.println(s.toUpperCase());});}//消费一个数据,其数据类型由泛型决定, 返回void。public static void toCase(String s, Consumer<String> c, Consumer<String> a){//抽象方法accept,返回值为voidc.accept(s);a.accept(s);//可以将上面两步使用默认方法andThen连接,效果相同,返回值为voidc.andThen(a).accept(s);}
}

Predicate: 对对象做判断 - boolean test(T t);
默认方法 - or(||) and(&&) negate(!)

import java.util.ArrayList;
import java.util.function.Predicate;public class PredicateTest {//predicate接口:进行数据的判断//1.接口抽象方法 boolean test(T t) 。用于条件判断的场景:public static  boolean judge(String s,Predicate<String> one){return one.test(s);}//2.接口默认方法 and(predicate) 将多次test方法的结果相与,返回boolean结果public static  boolean judgeAnd(String s,Predicate<String> one, Predicate<String> two){return one.and(two).test(s);//等同于:one.test(s) && two.test(s)}//2.接口默认方法 or(predicate) 将多次test方法的结果相与,返回boolean结果public static  boolean judgeOr(String s,Predicate<String> one, Predicate<String> two){return one.or(two).test(s);//等同于:one.test(s) || two.test(s)}//3.默认接口方法 negate() 取反public static  boolean judgeNegate(String s,Predicate<String> one){return one.negate().test(s);//等同于:!one.test(s)}public static void main(String[] args) {//案例:数组当中有多条“姓名+性别”的信息如下,请通过 Predicate 接口的拼装将符合要求的字符串筛选到集合 ArrayList 中,需要同时满足两个条件://1. 必须为pc平台;//2. 名字为4个字。String[] array = new String[]{"怪物猎人,pc,278", "塞尔达传说,switch,315", "黎明杀机,pc,67", "女神异闻录5,ps4,199","光环,Xbox,250"};//创建一个ArrayList表ArrayList<String> list = new ArrayList<>();//使用Predicate接口的and方法满足上述条件for(String s : array){//将信息分离String[] info = s.split(",");//直接使用lambda简化函数式接口参数boolean b = judgeAnd(s,s1 ->  info[1].equals("pc"),//1. 必须为pc平台;s2 -> info[0].length() == 4); //2. 名字为4个字。if(b){//如果满足条件就添加进列表list.add(s);}}System.out.println(list);list.clear();//案例:只要价格低于100 或者 平台不是pc的就加入列表//使用Predicate接口的or和negate方法满足上述条件for(String s : array){//将信息分离String[] info = s.split(",");//直接使用lambda简化函数式接口参数boolean b = judgeOr(s,s1 ->  Integer.parseInt(info[2]) < 100,//1. 价格低于100s2 -> judgeNegate(info[1], (s3) -> s3.equals("pc"))); //2. 平台不是pcif(b){//如果满足条件就添加进列表list.add(s);}}System.out.println(list);}
}

Function<T, R>: 类型转换 - R apply(T t);
默认方法 - andThen(Function)
连续做两种类型转换

import java.util.function.Function;public class FunctionTest {//Function<T, R>接口用来根据一个类型的数据得到另一个类型的数据 T:输入类型 R:结果类型//apply方法用于类型转换public static Integer FunctionApply(String s, Function<String, Integer> one){return one.apply(s);}//andThen(after)方法返回一个组合函数,首先将此函数应用于其输入,然后将after函数应用于结果。public static String FunctionAndThen(String s, Function<String, Integer> one, Function<Integer, Integer> two, Function<Integer, String> three){return  one.andThen(two).andThen(three).apply(s);//相当于:three.apply(two.apply(one.apply(s)));}public static void main(String[] args) {String s = "怪物猎人";String change = FunctionAndThen(s, s1 -> s1.length(), i -> i * 100, i1 -> "价格为" + i1 + "元");System.out.println(change);}
}

3. stream流

当需要对多个元素进⾏操作(特别是多步操作)的时候,考虑到性能及便利性,我们应该⾸先拼好⼀个“模型”步骤⽅案,然后再按照⽅案去执⾏它。
这张图中展示了过滤、映射、跳过、计数等多步操作,这是⼀种集合元素的处理⽅案,⽽⽅案就是⼀种“函数模型”。图中的每⼀个⽅框都是⼀个“流”,调⽤指定的⽅法,可以从⼀个流模型转换为另⼀个流模型。⽽最右侧的数字3是最终结果。
这⾥的 filter 、 map 、 skip 都是在对函数模型进⾏操作,集合元素并没有真正被处理。只有当终结⽅法 count 执⾏的时候,整个模型才会按照指定策略执⾏操作。⽽这得益于Lambda的延迟执⾏特性。

备注:“Stream流”其实是⼀个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)。

Stream流: 操作 数组或者集合
获取流: 1.集合 Collection Map 2.数组

import java.util.*;
import java.util.stream.Stream;public class GetStream {//获取流.stream()方法public static void main(String[] args) {//1.单列集合获取流List<String> list = new ArrayList<>();Stream<String> listStream = list.stream();Set<String> set = new HashSet<>();Stream<String> setStream = set.stream();//2.多列集合获取流(使用方法获取单列集合,在通过单列集合获取流)Map<String, Integer> map = new HashMap<>();//获取键值流Set<String> keySet = map.keySet();Stream<String> keyStream = keySet.stream();//获取键值对流Set<Map.Entry<String, Integer>> entrySet = map.entrySet();Stream<Map.Entry<String, Integer>> entryStream = entrySet.stream();//获取values流Collection<Integer> values = map.values();Stream<Integer> valueStream = values.stream();//3.数组获取流(Stream<T>接口的静态方法 of())Integer[] arr = new Integer[]{1, 2, 3, 4, 5};Stream<Integer> arrStream = Stream.of(arr);//of方法重载,数组可用变长数组代替Stream<Integer> arrStream1 = Stream.of(1, 2, 3, 4, 5);}
}

常用API:
void forEach(Consumer) - 终结方法
Stream filter(Predicate) - 延迟方法
Predicate中test返回true, 是保留在流中的
Stream map(Function<T, R>) - 延迟方法
将 流中的 T类型的数据, 转成 R类型数据, 并且存入新的流中
static Stream concat(Stream, Stream)
将两个流拼接成一个

代码实现:

import org.junit.Test;import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;public class StreamAPI {//创建列表private static ArrayList<String> list;//给列表添加元素public void setList(){list = new ArrayList<>();list.add("黎明杀机");list.add("怪物猎人世界");list.add("饥荒");list.add("杀戮尖塔");list.add("星露谷物语");list.add("赛博朋克2077");list.add("神界:原罪2");list.add("文明6");}@Test//单元测试时并没有加载类,所以也没有运行静态方法public void forEachDemo(){setList();//forEach(消费者函数接口对象), 终结方法, 遍历消费list.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});System.out.println(list);}@Testpublic void filterDemo(){setList();//filter(判断接口对象), 延迟方法, 通过实现判断接口过滤流list.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {return s.length() == 2;}}).forEach(s -> System.out.println(s));//流并不是对原集合进行操作,只是在改变基于原集合的函数模型System.out.println(list);}@Testpublic void mapDemo(){setList();//map(函数接口对象), 延迟方法, 通过实现函数接口将流中的元素映射到另一个流Stream<Integer> length = list.stream().map(new Function<String, Integer>(){@Overridepublic Integer apply(String s) {return s.length();}});length.forEach(s -> System.out.println(s));}@Testpublic void countDemo(){setList();//count(), 终结方法, 返回元素个数,返回值为long类型long size = list.stream().count();System.out.println(size);}@Testpublic void limitDemo(){setList();//limit ⽅方法可以对流进行截取,只截取前n个。//limit(long size), 延迟方法, 参数是long类型,如果集合当前长度大于参数则进行截取;否则不进行操作。list.stream().limit(3).forEach(s -> System.out.println(s));}@Testpublic void skipDemo(){setList();//skip方法可以跳过前几个元素。//skip(long size), 延迟方法, 如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流list.stream().skip(3).forEach(s -> System.out.println(s));}@Testpublic void concatDemo(){setList();//concat方法可以组合两个流。//Stream.concat(Stream<T>, Stream<N>), 延迟方法, 将两个流合并为一个流Stream.concat(list.stream(), list.stream()).forEach(s -> System.out.println(s));}
}

案例

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;public class Example {public static void main(String[] args) {Set<String> set = new HashSet<>();set.add("黎明杀机");set.add("怪物猎人世界");set.add("饥荒");set.add("杀戮尖塔");set.add("星露谷物语");set.add("赛博朋克2077");set.add("神界:原罪2");set.add("文明6");
//        System.out.println("文明6".matches(".*\\d.*"));
//        System.out.println("饥荒".matches("^[\\u4E00-\\u9FA5]+$"));// 1. 第一个队伍只要名字全是中文游戏;存储到一个新集合中。// 2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。Stream<String> queue1 = set.stream().filter(name -> name.matches("^[\\u4E00-\\u9FA5]+$")).limit(3);// 3. 第二个队伍只要名字含有数字的游戏;存储到一个新集合中。// 4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。Stream<String> queue2 = set.stream().filter(name -> name.matches(".*\\d.*")).skip(2);// 5. 将两个队伍合并为一个队伍;存储到一个新集合中。Stream<String> appendQueue = Stream.concat(queue1, queue2);// 6. 根据名字创建Game对象;映射到一个新流中。Stream<Game> game = appendQueue.map(name -> new Game(name));// 7. 打印整个队伍的Game对象信息。game.forEach(g -> System.out.println(g.getName()));}
}

JAVA学习 API_day11(属性集, 函数式编程, stream流)相关推荐

  1. Java8函数式编程——Stream流

    函数式编程-Stream流 实例练习:https://javadaily.cn/post/2022020817/7f222b3057fb/ 1. 概述 1.1 为什么学? 能够看懂公司里的代码 大数量 ...

  2. 函数式编程-Stream流(来源三更草堂)

    函数式编程-Stream流 1. 概述 1.1 为什么学? 能够看懂公司里的代码 大数量下处理集合效率高 代码可读性高 消灭嵌套地狱 //查询未成年作家的评分在70以上的书籍 由于洋流影响所以作家和书 ...

  3. 函数式编程-Stream流/lambda表达式/Optional/函数式接口/方法引用/高级用法

    函数式编程-Stream流 不会Lambda表达式.函数式编程?你确定能看懂公司代码?-java8函数式编程(Lambda表达式,Optional,Stream流)从入门到精通-最通俗易懂 1. 概述 ...

  4. 函数式编程-Stream流

    1. 概述 1.1 为什么学? 能够看懂公司里的代码 大数量下处理集合效率高 代码可读性高 消灭嵌套地狱 //查询未成年作家的评分在70以上的书籍 由于洋流影响所以作家和书籍可能出现重复,需要进行去重 ...

  5. java学习笔记20(Lambda表达式、函数式编程、流式计算、练习)

    文章目录 11.3 学习内容 Lambda表达式 Lambda标准格式 格式说明 省略规则 使用前提 函数式接口 预定义的函数式接口 工作内容 任务1 总结&明日计划 11.4 学习内容 流式 ...

  6. Java 8 Lambda表达式的函数式编程– Monads

    什么是monad ?: monad是一种设计模式概念,用于大多数功能编程语言(如Lisp)或现代世界的Clojure或Scala中. (实际上,我会从scala复制一些内容.)现在,为什么它在Java ...

  7. Java学习笔记 六、面向对象编程中级部分

    Java学习笔记 六.面向对象编程中级部分 包 包的注意事项和使用细节 访问修饰符 访问修饰符的注意事项和使用细节 面向对象编程三大特征 封装 封装的实现步骤(三步) 继承 继承的细节问题 继承的本质 ...

  8. Lambda表达式接口更新方法引用函数式接口Stream流

    Lambda表达式&接口更新&方法引用&函数式接口&Stream流 Lambda 1.程序启动三种不同的表现形式 2.Lambda表达式的标准格式 3.练习 Lambd ...

  9. Java面试知识点:红黑树、Stream流

    问题:Java面试知识点:红黑树.Stream流 答案: 1.红黑树 红黑树   • 平衡二叉B树   • 每一个节点可以是红或者黑   • 红黑树不是高度平衡的,它的平衡是通过"自己的红黑 ...

最新文章

  1. IO异常 java.net.SocketException: Connection reset
  2. mysql判断视图是否存在_使用JDBC查询是否存在某表或视图,按月动态生成表
  3. DataWorks搬站方案:Airflow作业迁移至DataWorks
  4. for循环中pairs与ipairs的区别与联系
  5. 旧金山站线上峰会24h倒数
  6. matlab练习程序(图像放大/缩小,放大没有进行插值操作)
  7. U盘安装Linux安装报错及解决方案
  8. 12.看板方法---度量和管理报告
  9. 2. JavaScript Boolean 对象
  10. Python:学习笔记
  11. spp色散关系 matlab,表面等离极化激元(SPP)基本原理教案分析.ppt
  12. 毫米波雷达探测技术,雷达人体存在感应器,实时检测静止存在应用
  13. [RK3288][Android6.0] 调试笔记 --- RT5640播放时的Codec寄存器列表
  14. DirectoryEntry配置IIS7出现ADSI Error:未知错误(0x80005000)
  15. 详解反向传播神经网络 (Back Propagation Neural Network, BPNN)
  16. ubuntu下安装anjuta
  17. The Bequeath Protocol Adapter [ID 16653.1]
  18. android 9.0极光推送闪退,推送导致应用闪退
  19. Elasticsearch JestClient 使用
  20. DROID-SLAM: 用于单目双目RGBD相机的深度视觉SLAM

热门文章

  1. 服务器ahci模式安装系统,u盘装系统硬盘模式怎么设置|u盘装系统BIOS设置ide/ahci方法...
  2. 一篇关于编程的文章,启发你的编程知识
  3. 阿里云 mysql 命令_有mysql命令
  4. @Param注解的用法
  5. Crazy Binary String
  6. 5.Fabric v2.0 java-sdk 根据TXID查询区块并从区块解析数据
  7. 安了锐捷后电脑总是弹出交互式检测
  8. 苏大与东大计算机软件专业比较,东北大学和苏州大学哪个实力更强一些?网友:苏大强?...
  9. emwin自定义字库
  10. Python requests模块详解