Stream流
1. 单列集合的Stream流获取
Java中的Stream流操作可以分为中间操作和终止操作两种。
中间操作包括:
filter
:对流中的元素进行筛选。map
:对流中的元素进行转换。flatMap
:对流中的元素进行扁平化映射。distinct
:去除流中重复的元素。sorted
:对流中的元素进行排序。peek
:对流中的每个元素执行操作,并返回新的Stream。limit
:截取Stream中前n个元素。skip
:跳过Stream中前n个元素。
终止操作包括:
count
:统计流中元素的数量。collect
:将流中的元素收集为集合或其他数据结构。forEach
:对流中的每个元素执行操作。reduce
:将流中的元素进行规约操作,返回一个结果。anyMatch
:判断流中是否有任意一个元素满足条件。allMatch
:判断流中是否所有元素都满足条件。noneMatch
:判断流中是否所有元素都不满足条件。findFirst
:返回流中的第一个元素。findAny
:返回流中的任意一个元素。
package com.wz.stream01;import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;public class streamDemo {public static void main(String[] args) {//源List<Integer> numbers = Arrays.asList(1,2,3,4,5);//通过源获取Stream流Stream<Integer> stream = numbers.stream();//对源中的数据进行过滤
// stream.filter(new Predicate<Integer>() {
// @Override
// public boolean test(Integer integer) {
// return integer>3;
// }
// });Stream<Integer> integerStream = stream.filter(integer -> integer > 3);//遍历剩下的元素
// integerStream.forEach(new Consumer<Integer>() {
// @Override
// public void accept(Integer integer) {
// System.out.println(integer);
// }
// });integerStream.forEach(System.out::println);System.out.println("------------------");HashSet<Character> set = new HashSet<>();set.add('a');set.add('b');set.add('c');set.add('d');set.add('e');set.add('f');set.stream().filter(character -> character>'c').forEach(System.out::println);}
}
在代码中,首先创建了一个包含整数的列表
numbers
,然后通过numbers.stream()
获取了一个Stream<Integer>
流。接着,使用
filter
方法对流中的元素进行过滤。使用了 lambda 表达式来简化过滤条件的定义,只保留大于 3 的元素。然后,使用
forEach
方法遍历过滤后的元素并打印出来。使用了方法引用System.out::println
使用 Stream 流对字符集合进行过滤和遍历。首先创建了一个包含字符的 HashSet 集合
set
,然后使用set.stream()
获取了一个流。接着,使用filter
方法过滤出大于字符 ‘c’ 的元素,并使用forEach
方法遍历并打印出来。
2. 双列集合及数组的Stream流获取
双列集合无法直接获取Stream流对象,只有先拿到单列集合,然后再获取Stream流对象
Stream<Map.Entry<String, Integer>> stream =map.entrySet().stream();Stream<String> stream = map.keySet().stream()
数组获取Stream流对象通过Arrays工具类获取
String[] names = {"ZhangSan","LiSi","WangWu"}; Stream<String> stream1 = Arrays.stream(names);
数组还可以通过Stream流自身提供的of方法来获取
Stream<String> stream2 = Stream.of("ZhangSan", "LiSi", "WangWu");
package com.wz.stream01;import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;public class streamDemo02 {public static void main(String[] args) {HashMap<String, Integer> map = new HashMap<>();map.put("ZhangSan", 20);map.put("LiSi", 21);map.put("WangWu", 22);//双列集合无法直接获取Stream流对象,只有先拿到单列集合,然后再获取Stream流对象
// Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();Stream<String> stream = map.keySet().stream()c//数组获取Stream流对象通过Arrays工具类获取String[] names = {"ZhangSan","LiSi","WangWu"};Stream<String> stream1 = Arrays.stream(names);//数组还可以通过Stream流自身提供的of方法来获取Stream<String> stream2 = Stream.of("ZhangSan", "LiSi", "WangWu");//将多个Stream流中的元素拼接到一起,形成一个新的Stream流Stream<String> concat = Stream.concat(stream1, stream2);}}
3. 使用 Stream 流对一个用户数组进行操作。
package com.wz.stream02;public class User {String username;String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
package com.wz.stream02;import java.util.Arrays;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;public class UserDemo {private static final char[] CHARACTERS = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};public static void main(String[] args) {//初始化数组User[] users = new User[10];for (int i = 0; i < 10; i++) {User user = new User();user.setUsername(randomStr(5));user.setPassword(randomStr(10));users[i]=user;}
// Stream<String> stream = Arrays.stream(users).map(new Function<User, String>() {
// @Override
// public String apply(User user) {
// return user.getUsername();
// }
// });
// stream.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// });Arrays.stream(users).map(User::getUsername).forEach(System.out::println);}//自定义随机字符private static String randomStr(int length){StringBuilder builder = new StringBuilder();Random r = new Random();for (int i = 0 ; i<length;i++){int index = r.nextInt(CHARACTERS.length);builder.append(CHARACTERS[index]);}return builder.toString();}
}
使用 Stream 流对一个用户数组进行操作。
首先,代码定义了一个包含小写字母的字符数组
CHARACTERS
。接下来,代码创建了一个用户数组
users
,并使用循环为每个用户对象设置用户名和密码。然后,代码展示了如何使用 Stream 流从用户数组中提取用户名并打印出来:
使用
Arrays.stream(users)
将用户数组转换为流。使用
map
方法将流中的每个用户对象映射为其用户名。通过Arrays.stream(users).map(User::getUsername)
将用户数组中的每个用户对象转换为其用户名。使用
forEach
方法遍历流中的每个用户名,并使用System.out.println
打印出来。通过Arrays.stream(users).map(User::getUsername).forEach(System.out::println)
对流中的每个用户名执行打印操作。最后,代码使用自定义的
randomStr
方法生成随机字符串,用于设置用户的用户名和密码。
4. Stream流中间聚合操作
Stream<T> filter(Predicate<? super T> predicate);//根据给定的条件过滤流中的元素
<R> Stream<R> map(Function<? super T, ? extends R> mapper);//将流中元素进行类型转换
Stream<T> distinct();//去重
Stream<T> sorted();//排序,如果存储元素没有实现Comparable或者相关集合没有提供Comparator将抛出异常
Stream<T> limit(long maxSize);//根据给定的上限,获取流中的元素
Stream<T> skip(long n);//跳过给定数量的元素IntStream mapToInt(ToIntFunction<? super T> mapper);//将流中元素全部转为整数
LongStream mapToLong(ToLongFunction<? super T> mapper);//将流中元素全部转为长整数
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);//将流中元素全部转为双精度浮点数
package com.wz.stream03;import java.util.Comparator;
import java.util.stream.Stream;public class StreamOperation {public static void main(String[] args) {Stream<Integer> s = Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50);//distinct()可以对管道中的元素进行去重s.distinct().forEach(System.out::println);System.out.println("-------------------------");Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50)//排序,默认是升序排序,如果需要进行降序排列,需要给定一个//排序器进行降序排列.sorted().forEach(System.out::println);System.out.println("-------------------------");Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50).sorted((o1, o2) -> o2-o1).forEach(System.out::println);System.out.println("-------------------------");Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50)//limit()限制管道中的元素个数.limit(5).forEach(System.out::println);System.out.println("-------------------------");Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50).skip(6).forEach(System.out::println);}
}
使用
distinct
方法对流中的元素进行去重。通过s.distinct().forEach(System.out::println)
去重并打印每个元素。使用
sorted
方法对流中的元素进行排序。默认情况下,排序是升序的。通过Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50).sorted().forEach(System.out::println)
进行升序排序并打印每个元素。如果需要进行降序排列,可以给定一个自定义的排序器。通过
Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50).sorted((o1, o2) -> o2-o1).forEach(System.out::println)
进行降序排序并打印每个元素。使用
limit
方法限制流中元素的个数。通过Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50).limit(5).forEach(System.out::println)
限制流中只有前 5 个元素,并打印每个元素。使用
skip
方法跳过流中的前几个元素。通过Stream.of(10, 50, 64, 12, 46, 23, 41, 36,10,50).skip(6).forEach(System.out::println)
跳过前 6 个元素,并打印剩余的元素。
package com.wz.stream03;import java.util.Arrays;
import java.util.function.ToIntFunction;
import java.util.stream.IntStream;public class StreamOperation02 {public static void main(String[] args) {//使用Stream流进行数据类型转换Integer[] numbers = {1,2,3,4};
// IntStream intStream = Arrays.stream(numbers).mapToInt(new ToIntFunction<Integer>() {
// @Override
// public int applyAsInt(Integer value) {
// return value.intValue();
// }
// });
// IntStream intStream = Arrays.stream(numbers).mapToInt(Integer::intValue);
// int[] array = intStream.toArray();int[] array = Arrays.stream(numbers).mapToInt(Integer::intValue).toArray();System.out.println(Arrays.toString(array));}
}
如何使用 Stream 流进行数据类型转换:
首先,代码创建了一个整数数组
numbers
。
使用
Arrays.stream(numbers)
将整数数组转换为流。使用
mapToInt
方法将流中的元素映射为int
类型。通过Arrays.stream(numbers).mapToInt(Integer::intValue)
将整数数组中的每个元素转换为对应的int
值。使用
toArray
方法将流中的元素转换为int
数组。通过Arrays.stream(numbers).mapToInt(Integer::intValue).toArray()
将流中的元素转换为int
数组。最后,代码使用
Arrays.toString(array)
将转换后的int
数组转换为字符串,并输出结果。
package com.wz.stream03;import java.util.Arrays;
import java.util.function.IntFunction;
import java.util.stream.Stream;public class StreamOperation03 {public static void main(String[] args) {Integer[] numbers = {1, 2, 3, 4};int[] array = Arrays.stream(numbers).mapToInt(Integer::intValue).toArray();System.out.println(Arrays.toString(array));Stream<Integer> boxed = Arrays.stream(array).boxed();
// boxed.toArray(new IntFunction<Integer[]>() {
// @Override
// public Integer[] apply(int value) {
// return new Integer[value];
// }
// });// boxed.toArray(value -> new Integer[value]);Integer[] array1 = boxed.toArray(Integer[]::new);}
}
利用Stream 流将整数数组转换为基本类型
int
数组:
- 使用
Arrays.stream(numbers)
将整数数组转换为流。- 使用
mapToInt
方法将流中的元素映射为int
类型。通过Arrays.stream(numbers).mapToInt(Integer::intValue)
将整数数组中的每个元素转换为对应的int
值。- 使用
toArray
方法将流中的元素转换为int
数组。通过Arrays.stream(numbers).mapToInt(Integer::intValue).toArray()
将流中的元素转换为int
数组。
使用 Stream 流将基本类型
int
数组转换为包装类型Integer
数组:
使用
Arrays.stream(array)
将基本类型int
数组转换为流。使用
boxed
方法将流中的元素包装为对应的包装类型Integer
。通过Arrays.stream(array).boxed()
将基本类型int
数组中的每个元素转换为对应的包装类型Integer
。使用
toArray
方法将流中的元素转换为Integer
数组。通过boxed.toArray(Integer[]::new)
将流中的元素转换为Integer
数组。
5. Stream流终结操作
void forEach(Consumer<? super T> action);//遍历操作流中元素
<A> A[] toArray(IntFunction<A[]> generator);//将流中元素按照给定的转换方式转换为数组
<R, A> R collect(Collector<? super T, A, R> collector);//将流中的元素按照给定的方式搜集起来Optional<T> min(Comparator<? super T> comparator);//根据给定的排序方式获取流中最小元素
Optional<T> max(Comparator<? super T> comparator);//根据给定的排序方式获取流中最大元素
Optional<T> findFirst(); //获取流中第一个元素long count();//获取流中元素数量
boolean anyMatch(Predicate<? super T> predicate);//检测流中是否存在给定条件的元素
boolean allMatch(Predicate<? super T> predicate);//检测流中元素是否全部满足给定条件
boolean noneMatch(Predicate<? super T> predicate);//检测流中元素是否全部不满足给定条件
package com.wz.stream04;import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class StreamTerminal {private static final char[] CHARACTERS = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};public static void main(String[] args) {//初始化数组List<User> users = new ArrayList<>();for (int i = 0; i < 10; i++) {User user = new User();user.setUsername(randomStr(5));user.setPassword(randomStr(10));System.out.println(user);}User user = new User();user.setUsername("admin");user.setPassword("123456");String username = "admin";users.add(user);System.out.println(username);
// users.stream().map(User::getUsername).forEach(System.out::println);//过滤Stream<User> stream = users.stream().filter(u -> u.getUsername().equals(username));//将流中的元素按照给定的方式搜集起来,我们指定的收集方式是收集为一个List集合。List<User> userList = stream.collect(Collectors.toList());//set集合
// Set<User> uesrSet = stream.collect(Collectors.toSet());//数组
// User[] array = stream.toArray(User[]::new);if (userList.size() > 0) {System.out.println(username + "已经被注册了");}//检测流中是否存在给定条件的元素
// users.stream().anyMatch(new Predicate<User>() {
// @Override
// public boolean test(User user) {
// return user.getUsername().equals(username);
// }
// });if (users.stream().anyMatch(user1 -> user1.getUsername().equals(username))) {System.out.println(username + "已经被注册了");}//检测流中元素是否全部不满足给定条件
// users.stream().noneMatch(new Predicate<User>() {
// @Override
// public boolean test(User user) {
// return user.getUsername().equals(username);
// }
// });if (users.stream().noneMatch(user2 -> user2.getUsername().equals(username))) {System.out.println(username + "可以注册");}//检测流中元素是否全部满足给定条件
// users.stream().allMatch(new Predicate<User>() {
// @Override
// public boolean test(User user) {
// return user.getUsername().length() >=5;
// }
// });if (users.stream().allMatch(user12 -> user12.getUsername().length() >= 5)) {System.out.println("所有用户的用户名长度均>=5");}Integer[] numbers = {1, 2, 3, 4, 5,};//count()一般在filter之后才会调用long count = Arrays.stream(numbers).filter(num -> num > 3).count();System.out.println(count);//求最值的时候必须要给定一个比较器,因为Stream流支持的是泛型,具体是//什么类型需要根据使用的情况来确定,而这个类型不一定是可比较的,因此,//需要我们提供比较的方式。最值得到的结果存储在一个容器中,这个容器是//是一个比较特殊的容器,这个容器至多存储一个值(可能一个值都没有)//根据给定的排序方式获取流中最小元素
// Optional<User> opt = users.stream().min(new Comparator<User>() {
// @Override
// public int compare(User o1, User o2) {
// return o1.getUsername().compareTo(o2.getUsername());
// }
// });Optional<User> opt = users.stream().min((o1, o2) -> o1.getUsername().compareTo(o2.getUsername()));//users.stream().min(Comparator.comparing(User::getUsername));User u = opt.orElse(null);System.out.println(u);}private static String randomStr(int length) {StringBuilder builder = new StringBuilder();Random r = new Random();for (int i = 0; i < length; i++) {int index = r.nextInt(CHARACTERS.length);builder.append(CHARACTERS[index]);}return builder.toString();}
}
使用
collect
方法将流中的元素收集到一个List<User>
集合中。通过users.stream().filter(u -> u.getUsername().equals(username))
过滤出用户名与指定值相等的用户流,然后使用collect(Collectors.toList())
将流中的元素收集为一个列表。使用
anyMatch
方法检测流中是否存在满足给定条件的元素。通过users.stream().anyMatch(user1 -> user1.getUsername().equals(username))
判断是否有用户名与指定值相等的用户。使用
noneMatch
方法检测流中是否所有元素都不满足给定条件。通过users.stream().noneMatch(user2 -> user2.getUsername().equals(username))
判断是否所有用户名都与指定值不相等。使用
allMatch
方法检测流中是否所有元素都满足给定条件。通过users.stream().allMatch(user12 -> user12.getUsername().length() >= 5)
判断是否所有用户名长度都大于等于 5。使用
count
方法统计流中满足给定条件的元素个数。通过Arrays.stream(numbers).filter(num -> num > 3).count()
统计数组中大于 3 的元素个数。使用
min
方法获取流中的最小元素。通过users.stream().min((o1, o2) -> o1.getUsername().compareTo(o2.getUsername()))
获取用户名最小的用户对象。注意,这里使用了 lambda 表达式作为比较器。
日期时间类
1. 日期时间类使用
//获取系统的当前时间Date date = new Date();System.out.println(date);
//日历,获取一个日期的实例,这个实例一产生就是当前系统的时间Calendar c = Calendar.getInstance();
//获取日历的当前日期Date time = c.getTime();System.out.println(time);
//获取日历的年份int year = c.get(Calendar.YEAR);System.out.println(year);
//获取日历的月份和当前天数
//注意,月份从0开始,11结束int month = c.get(Calendar.MONTH);int day = c.get(Calendar.DATE);System.out.println(year + "-" +(month+1) + "-" + day);
//获取时间
//注意:HOUR表示12小时制 HOUR_OF_DAY表示24小时制int hour = c.get(Calendar.HOUR_OF_DAY);int minute = c.get(Calendar.MINUTE);int second = c.get(Calendar.SECOND);System.out.println(hour+":"+minute+":"+second);
//滚动日历,第一个参数表示滚动单位,第二个参数表示滚动数量c.roll(Calendar.DATE,-5);System.out.println(c.getTime());
//获取当前月的最大天数 int maxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);System.out.println(maxDay);
//设置日期目前处于的天数c.set(Calendar.DAY_OF_MONTH,2);
//获取当前日历表示一周的星期几int week = c.get(Calendar.DAY_OF_WEEK);System.out.println(week);
2. 日历
package com.wz.date01;import java.util.ArrayList;
import java.util.Calendar;public class DateDemo {public static void main(String[] args) {showCalender(2023,7);}public static void showCalender(int year , int month){System.out.println("一\t二\t三\t四\t五\t六\t日");//获取当前时间和日期的实例Calendar c = Calendar.getInstance();//传入年份和月份c.set(Calendar.YEAR,year);c.set(Calendar.MONTH,month-1);//得到这个月最大天数int maxDays = c.getActualMaximum(Calendar.DAY_OF_MONTH);//将日历设置到当月的第一天c.set(Calendar.DAY_OF_MONTH,1);//得到这个月的第一天是星期几//注意:一周的第一天是星期日 -- 1 ,最后一天是星期六 -- 7int week = c.get(Calendar.DAY_OF_WEEK);//一页日历是42天int total = 42;//计算上个月要展示多少天int lastMonthDays = (week == 1) ? 6: ( week - 2 );//计算上个月的最大天数//将日历向前滚动一个月c.roll(Calendar.MONTH,-1);// c.set(Calendar.DAY_OF_MONTH,1);int lastMonthMaxDays = c.getActualMaximum(Calendar.DAY_OF_MONTH);//上个月开始的天数int start = lastMonthMaxDays - lastMonthDays + 1;ArrayList<Integer> days= new ArrayList<>();//向days中添加上个月要展示的天数for (int i = start; i <= lastMonthMaxDays; i++) {days.add(i);}//向days中添加当月的天数for (int i = 1; i <= maxDays; i++) {days.add(i);}//向days中添加下个月需要展示的天数int nextMonthDays = total - maxDays - lastMonthDays;for (int i = 1; i <=nextMonthDays ; i++) {days.add(i);}//展示日历for (int i = 0; i < days.size(); i++) {System.out.print(days.get(i)+"\t");if (i%7==6){System.out.println();}}}
}
- 创建一个Calendar实例,获取当前时间和日期。
- 设置Calendar实例的年份和月份为传入的参数。
- 使用
getActualMaximum(Calendar.DAY_OF_MONTH)
方法获取该月份的最大天数。- 使用
set(Calendar.DAY_OF_MONTH, 1)
将日历设置到该月份的第一天。- 使用
get(Calendar.DAY_OF_WEEK)
获取该月份的第一天是星期几。- 计算上个月需要展示的天数,以及上个月的最大天数。
- 向一个ArrayList中添加上个月需要展示的天数。
- 向ArrayList中添加该月份的天数。
- 向ArrayList中添加下个月需要展示的天数。
- 使用循环遍历ArrayList,按照每行7个元素的格式打印日历。
包装类
Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的。基本类型的数据不具备"对象"的特性(没有成员变量和成员方法可以调用),因此,java为每种数据类型分别设计了对应的类,即包装类。
基本数据类型 | 对应的包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
- 所有包装类都是final类型,因此不能创建他们的子类。
- 包装类是不可变类,一个包装类的对象自创建后,他所包含的基本类型数据就不能被改变。
1. 装箱和拆箱
装箱:将基本数据类型变为包装类对象。
拆箱:将包装类中包装的基本数据类型取出。
int --> Integer(装箱) | Integer --> int(拆箱) |
---|---|
使用Integer类的构造方法 | xxx.intValue() |
Integer.valueOf() | 自动拆箱 |
自动装箱 |
Integer a = 100; //Integer.valueOf()int b = 100;//如果有字面的基本数据类型参数比较运算,只需要//看值是否相同即可System.out.println(a == b);
Integer c = 200, d = 200;Integer e = 110, f = 110;System.out.println(c == d);System.out.println(e == f);//这一步发生了自动拆箱,自动拆箱调用的是xxxValue方法//a.intValue()
package com.wz.packagGroup;public class Test01 {public static void main(String[] args) {Integer c = 200, d = 200;Integer e = 110, f = 110;System.out.println(c == d);//falseSystem.out.println(e == f);//trueInteger i1 = new Integer(127);Integer i2 = new Integer(127);System.out.println(i1 == i2);//falseSystem.out.println(i1.equals(i2));//trueInteger i3 = new Integer(128);Integer i4 = new Integer(128);System.out.println(i3 == i4);//falseSystem.out.println(i3.equals(i4));//trueInteger i5 = 128;Integer i6 = 128;System.out.println(i5 == i6);//falseSystem.out.println(i5.equals(i6));//trueInteger i7 = 127;Integer i8 = 127;System.out.println(i7 == i8);//trueSystem.out.println(i7.equals(i8));//true}
}