这里写目录标题
属性集
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));
}