Java教程 第47页 Java流 – Java流过滤器 过滤操作产生过滤流,即输入流的子集,其元素对于指定的谓词计算为true。 predicate是一个接受元素并返回布尔值的函数。 过滤的流具有与输入流相同的类型。 如果predicate对所有元素求值为false,它将生成一个空流。 以下代码仅在女性中使用员工流和过滤器。 它将女性映射到他们的名字,并将它们打印在标准输出上。 import java.time.LocalDate; import java.time.Month; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { Employee.persons() .stream() .filter(Employee::isFemale) .map(Employee::getName) .forEach(System.out::println); } } class Employee { public static enum Gender { MALE, FEMALE } private long id; private String name; private Gender gender; private LocalDate dob; private double income; public Employee(long id, String name, Gender gender, LocalDate dob, double income) { this.id = id; this.name = name; this.gender = gender; this.dob = dob; this.income = income; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }...
2024-04-01
Java流 – Java流操作 常用的流操作如下列出。 Distinct中间操作通过检查equals()方法返回由不同元素组成的流。 filter中间操作返回与指定谓词匹配的流。 flatMap中间操作生成流扁平化。 limit中间操作按数字截断流。 map中间操作对流执行一对一映射 peek中间操作应用调试的操作。 skip中间操作丢弃前n个元素并返回剩余流。如果此流包含少于请求的流,则返回空流。 sorted中间操作根据自然顺序或指定的比较器对流进行排序。对于有序流,排序是稳定的。 allMatch终端操作如果流中的所有元素都匹配指定的谓词,则返回true,否则返回false。如果流为空,则返回true。 anyMatch终端操作如果流中的任何元素与指定的谓词匹配,则返回true,否则返回false。如果流为空,则返回false。 findAny终端操作返回流中的任何元素。返回空流的一个空的Optional对象。 findFirst终端操作返回流的第一个元素。对于有序流,它返回第一个元素;对于无序流,它返回任何元素。 noneMatch终端操作如果流中没有元素匹配指定的谓词,则返回true,否则返回false。如果流为空,则返回true。 forEach终端操作对流中的每个元素应用操作。 reduce终端操作应用缩减操作以从流计算单个值。 流 Peek 我们可以使用Stream <T>接口的窥探(Consumer<?super T>action)方法调试流。 IntStream,LongStream和DoubleStream还包含一个peek()方法,它接受IntConsumer,LongConsumer和DoubleConsumer作为参数。 我们可以使用带有peek()方法的lambda表达式来记录元素。 以下代码使用peek()方法打印通过流管道的元素: import java.util.stream.Stream; public class Main { public static void main(String[] args) { int sum = Stream.of(1, 2, 3, 4, 5) .peek(e -> System.out.println("Taking integer: " + e)) .filter(n -> n % 2 == 1) .peek(e -> System.out.println("Filtered integer: " + e)) .map(n -> n * n).peek(e -> System.out.println("Mapped integer: " + e)) .reduce(0, Integer::sum); System.out.println("Sum = " + sum); } } 上面的代码生成以下结果。 流 ForEach forEach操作对流的每个元素执行操作。 Stream<T> 接口包含两种方法来执行forEach操作: void forEach(Consumer<? super T> action) void forEachOrdered(Consumer<? super T> action) IntStream,LongStream和DoubleStream包含相同的方法。 forEach()方法不保证操作的顺序应用流中的每个元素。 forEachOrdered()方法按元素的顺序执行操作由流定义。 forEachOrdered()方法可能会减慢并行流中的处理速度。 以下代码打印员工列表中的女性详细信息: import java.time.LocalDate; import java.time.Month; import java.util.Arrays; import java.util.List; public class Main...
2024-04-01
Java流 – Java文件流 来自Java 8的java.io和java.nio.file包添加了许多方法来支持使用流的I/O操作。 我们可以从文件中读取文本作为字符串流。流中的每个元素表示一行文本。 我们还可以使用流从JarFile读取JarEntry,我们可以读取目录中的条目作为Path流。 自动关闭 调用stream上的close()方法将关闭底层文件。 或者,我们可以在try-with-resources语句中创建流,以便自动关闭底层文件。 例子 以下代码显示如何使用流读取文件的内容。 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Path path = Paths.get("./Main.java"); try (Stream<String> lines = Files.lines(path)) { lines.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } } 上面的代码生成以下结果。 例2 以下代码显示如何使用流读取路径。 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Path dir = Paths.get("."); System.out.printf("%nThe file tree for %s%n", dir.toAbsolutePath()); try (Stream<Path> fileTree = Files.walk(dir)) { fileTree.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } } 上面的代码生成以下结果。
2024-04-01
Java流 – Java字符串流 Char序列流 CharSequence接口的chars()返回一个IntStream,它的元素是表示字符的int值。 我们可以在String,StringBuilder和StringBuffer上使用chars()方法。 以下代码从字符串创建字符流,过滤掉所有数字和空格,然后打印剩余的字符: public class Main { public static void main(String[] args) { String str = "5 123,123,qwe,1,123, 25"; str.chars() .filter(n -> !Character.isDigit((char)n) && !Character.isWhitespace((char)n)) .forEach(n -> System.out.print((char)n)); } } 上面的代码生成以下结果。 Regex流 java.util.regex.Pattern类中的splitAsStream(CharSequence input)方法返回其元素与模式匹配的String流。 以下代码通过使用正则表达式(“,”)拆分字符串来获取字符串流。 匹配的字符串打印在标准输出上。 import java.util.regex.Pattern; public class Main { public static void main(String[] args) { String str = "XML,CSS,HTML"; Pattern.compile(",") .splitAsStream(str) .forEach(System.out::println); } } 上面的代码生成以下结果。
2024-04-01
Java流 – Java集合流 来自数组的流 java.util.Arrays类包含用于从数组创建顺序流的stream()方法。 我们可以使用它来创建一个IntStream,一个LongStream,一个DoubleStream和一个Stream <T>。 下面的代码创建一个IntStream。 IntStream numbers = Arrays.stream(new int[]{1, 2, 3}); 以下代码从int数组和String数组创建Stream <String>。 Stream<String> names = Arrays.stream(new String[] {"XML", "Java"}); 集合流 Collection接口包含stream()和parallelStream()方法,它们分别从Collection创建顺序流和并行流。 以下代码从一组字符串创建流: import java.util.HashSet; import java.util.Set; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Set<String> names = new HashSet<>(); names.add("XML"); names.add("Java"); Stream<String> sequentialStream = names.stream(); sequentialStream.forEach(System.out::println); Stream<String> parallelStream = names.parallelStream(); parallelStream.forEach(System.out::println); } } 上面的代码生成以下结果。
2024-04-01
Java流 – Java函数流 我们可以有一个可以根据需要生成值的函数。 以下两种静态方法从Stream接口从函数生成无限流。 <T> Stream<T> iterate(T seed, UnaryOperator<T> f) <T> Stream<T> generate(Supplier<T> s) iterate()方法创建顺序有序流。 generate()方法创建一个顺序无序流。 IntStream,LongStream和DoubleStream包含iterate()和generate()方法,它们采用特定于其原始类型的参数生成值。 例如,在IntStream接口中定义了以下两种方法: IntStream iterate(int seed, IntUnaryOperator f) IntStream generate(IntSupplier s) Stream.iterate() iterate()方法有两个参数:种子和函数。 种子是流的第一个元素。通过将函数应用于第一元素来生成第二元素。通过对第二元素应用函数来生成第三元素。 因此,元素是:seed,f(seed),f(f(seed)),f(f(f(seed)))…. 以下代码创建了一个自然数流: Stream<Long> naturalNumbers = Stream.iterate(1L, n -> n + 1); limit(long maxSize)操作是产生另一个流的中间操作。 以下代码创建前10个自然数的流: import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<Long> tenNaturalNumbers = Stream.iterate(1L, n -> n + 1) .limit(10); tenNaturalNumbers.forEach(System.out::println); } } 上面的代码生成以下结果。 例2 以下代码过滤从iterate函数生成的值。 import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream.iterate(2L, n -> n + 1) .filter(Main::isOdd) .limit(5) .forEach(System.out::println); } public static boolean isOdd(long number) { if (number % 2 == 0) { return false; } return true; } } 上面的代码生成以下结果。 例3 要从流中丢弃某些元素,请使用跳过操作。 skip(long n)是一个中间操作,跳过流的前n个元素。 以下代码使用skip跳过前100个奇数:...
2024-04-01
Java流 – Java可选 Java 8引入了一个java.util.Optional类来优雅地处理NullPointerException。 Optional是可以包含或不包含非空值的非空值的包装器。 可能返回null的方法应返回Optional,而不是null。 如果其包含非空值,则来自可选<T>的isPresent()返回true,否则返回false。 如果get()方法包含非空值,则返回非空值,否则抛出NoSuchElementException。 当一个方法返回一个可选,你必须检查它是否包含一个非空值,然后再询问它的值。 如果在确保它包含非空值之前调用了get()方法,则会抛出NoSuchElementException,而不是抛出NullPointerException。 创建可选对象 Optional <T>类提供了三个静态工厂方法来创建Optional对象。 <T>可选<T> empty()返回一个空的Optional。从此方法返回的可选<T>不包含非空值。 <T>(T值)的可选<T>返回一个包含指定值作为非空值的Optional。如果指定的值为null,它会抛出NullPointerException。 <T>可选的T值(T值)如果值为非空,则返回包含指定值的Optional。如果指定的值为null,则返回一个空的Optional。 以下代码显示如何创建Optional对象: import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> empty = Optional.empty(); System.out.println(empty); Optional<String> str = Optional.of("www.w3cschool.cn"); System.out.println(str); String nullableString = ""; Optional<String> str2 = Optional.of(nullableString); System.out.println(str2); } } 上面的代码生成以下结果。 例2 如果包含非空值,以下代码将在可选中打印值: import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> str = Optional.of("www.w3cschool.cn"); if (str.isPresent()) { String value = str.get(); System.out.println("Optional contains " + value); } else { System.out.println("Optional is empty."); } } } 上面的代码生成以下结果。 可选ifPresent if Present(Consumer<? super T> action)方法对Optional中包含的值执行操作。 如果Optional是空的,这个方法不做任何事情。 以下代码打印出来自Optional的内容。 import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> str = Optional.of("www.w3cschool.cn"); str.ifPresent(value -> System.out.println("Optional...
2024-04-01
Java日期时间传统互操作性 在Java 8之前,Java日期和时间由 java.util.Date , java.util.Calendar 和 java.util.TimeZone 类以及它们的子类(如java.util.GregorianCalendar)定义。 旧的日期时间API在java.util包中定义,而新的Java 8日期时间API在java.time包中定义。 java.util.Date java.util.Calendar java.util.GregorianCalendar java.util.TimeZone java.sql.Date java.sql.Time java.sql.Timestamp java.nio.file.attribute.FileTime JDK 8日期时间API定义了几种方法在 java.util 和 java.time 对象之间进行转换。 Calendar.toInstant() 将Calendar对象转换为Instant。 java.util.Date toInstant() 将Date对象转换为Instant。 java.util.Date from() 方法从Instant中创建一个Date对象。 GregorianCalendar.toZonedDateTime() 将GregorianCalendar实例转换为ZonedDateTime。 GregorianCalendar.from(ZonedDateTime) 使用ZonedDateTime实例中的默认语言环境创建一个GregorianCalendar对象。 TimeZone.toZoneId() 将TimeZone对象转换为ZoneId。 java.sql.Date toLocalDate() 转换为LocalDate。 java.sql.Date valueOf() 从LocalDate创建java.sql.Date java.sql.Time toLocalTime() 转换为LocalTime。 java.sql.Time valueOf() 从LocalTime创建java.sql.Time。 java.sql.Timestamp toInstant() 转换为Instant。 java.sql.Timestamp valueOf() 从LocalDateTime进行转换。 java.nio.file.attribute.FileTime toInstant() 转换为Instant。 java.nio.file.attribute.FileTime from() 转换为Instant。 例子 以下代码显示如何将日期转换为即时。 import java.time.Instant; import java.util.Date; public class Main { public static void main(String[] args) { Date dt = new Date(); System.out.println("Date: " + dt); Instant in = dt.toInstant(); System.out.println("Instant: " + in); Date dt2 = Date.from(in); System.out.println("Date: " + dt2); } } 上面的代码生成以下结果。 例2 我们可以将GregorianCalendar转换为ZonedDateTime,它可以转换为新的Date-Time API中的任何其他类。 我们可以将Instant转换为ZonedDateTime,然后将ZonedDateTime转换为GregorianCalendar与from()方法从GregorianCalendar。 以下代码显示了如何将GregorianCalendar转换为ZonedDateTime,反之亦然。 import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetDateTime;...
2024-04-01
Java日期时间 – Java遗留日期日历 Date类的一个对象存储自1970年1月1日午夜时代起经过的毫秒数。 并表示时间的瞬间。 Date类默认构造函数使用当前系统日期时间创建一个Date对象。 例子 下面的代码显示了如何使用Date类。 import java.util.Date; public class Main { public static void main(String[] args) { Date currentDate = new Date(); System.out.println("Current date: " + currentDate); long millis = currentDate.getTime(); System.out.println("Current datetime in millis: " + millis); } } 上面的代码生成以下结果。 遗留日历 日历是一个抽象类。 GregorianCalendar类扩展了Calendar类。 构造函数 GregorianCalendar类有一个默认的构造函数,它创建一个对象来表示当前的datetime。 GregorianCalendar类还定义了我们可以用来创建特定日期的构造函数。 我们还可以在特定时区创建日期。 import java.util.Calendar; import java.util.GregorianCalendar; import java.util.TimeZone; public class Main { public static void main(String[] args) { // Get the current date in the system default time zone GregorianCalendar currentDate = new GregorianCalendar(); System.out.println(currentDate.getTime()); // Get GregorianCalendar object representing March 21, 2014 07:30:45 AM GregorianCalendar someDate = new GregorianCalendar(2014, Calendar.MARCH, 21, 7, 30, 45); System.out.println(someDate.getTime()); // Get Indian time zone, which is GMT+05:30 TimeZone indianTZ = TimeZone.getTimeZone("GMT+05:30"); GregorianCalendar indianDate =...
2024-04-01
Java日期时间 – Java日期和时间解析 由 DateTimeFormatter 处理的解析是从字符串创建日期时间对象。 用于格式化的相同符号用作解析字符串值。 如果无法解析文本,则会抛出 DateTimeParseException 。它有两种方法来提供错误的详细信息。 getErrorIndex()返回文本中的错误偏移量。 getParsedString()返回正在解析的文本。 日期时间相关的类和DateTimeFormatter定义了将字符串解析为datetime对象的方法。 parse()方法从datetime类 每个datetime类有两个重载版本的 parse()。 parse()方法的返回类型与定义datetime类相同。 下面的代码显示了如何使用 parse()方法从 LocalDate 对象: import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class Main { public static void main(String[] args) { LocalDate ld1 = LocalDate.parse("2014-06-10"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); LocalDate ld2 = LocalDate.parse("06/10/2014", formatter); System.out.println("ld1: " + ld1); System.out.println("ld2: " + ld2); } } 上面的代码生成以下结果。 parse()从DateTimeFormatter类 DateTimeFormatter 包含几个将字符串解析为datetime对象的parse()方法。 它们中的大多数返回一个TemporalAccessor对象,您可以查询它以获取datetime组件。 您可以将TemporalAccessor对象传递给datetime类的from()方法,以获取特定的datetime对象。 以下代码显示如何使用DateTimeFormatter对象解析MM/dd /yyyy格式的字符串,以构造LocalDate: import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; public class Main { public static void main(String[] args) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); TemporalAccessor ta = formatter.parse("06/10/2014"); LocalDate ld = LocalDate.from(ta); System.out.println(ld); } } 上面的代码生成以下结果。 例子 parse()方法可以通过TemporalQuery将字符串直接解析为特定的datetime对象。 import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class Main { public static void main(String[] args) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); LocalDate ld...
2024-04-01