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() {
// @Override
// public boolean test(Integer integer) {
// return integer>3;
// }
// });
Stream<Integer> integerStream = stream.filter(integer -> integer > 3);
//遍历剩下的元素
// integerStream.forEach(new Consumer() {
// @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
流。接着,使用
filter
方法对流中的元素进行过滤。使用了 lambda 表达式来简化过滤条件的定义,只保留大于 3 的元素。然后,使用
forEach
方法遍历过滤后的元素并打印出来。使用了方法引用System.out::println
使用 Stream 流对字符集合进行过滤和遍历。首先创建了一个包含字符的 HashSet 集合
set
,然后使用set.stream()
获取了一个流。接着,使用filter
方法过滤出大于字符 ‘c’ 的元素,并使用forEach
方法遍历并打印出来。
双列集合无法直接获取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> 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);
}
}
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;
}
@Override
public 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 stream = Arrays.stream(users).map(new Function() {
// @Override
// public String apply(User user) {
// return user.getUsername();
// }
// });
// stream.forEach(new Consumer() {
// @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
方法生成随机字符串,用于设置用户的用户名和密码。
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() {
// @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() {
// @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
数组。
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 uesrSet = stream.collect(Collectors.toSet());
//数组
// User[] array = stream.toArray(User[]::new);
if (userList.size() > 0) {
System.out.println(username + "已经被注册了");
}
//检测流中是否存在给定条件的元素
// users.stream().anyMatch(new Predicate() {
// @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() {
// @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() {
// @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 opt = users.stream().min(new Comparator() {
// @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
集合中。通过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 表达式作为比较器。
//获取系统的当前时间
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);
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 ,最后一天是星期六 -- 7
int 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类型,因此不能创建他们的子类。
- 包装类是不可变类,一个包装类的对象自创建后,他所包含的基本类型数据就不能被改变。
装箱:将基本数据类型变为包装类对象。
拆箱:将包装类中包装的基本数据类型取出。
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);//false
System.out.println(e == f);//true
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);//false
System.out.println(i1.equals(i2));//true
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4);//false
System.out.println(i3.equals(i4));//true
Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5 == i6);//false
System.out.println(i5.equals(i6));//true
Integer i7 = 127;
Integer i8 = 127;
System.out.println(i7 == i8);//true
System.out.println(i7.equals(i8));//true
}
}