枚举概述: 就是一个类只能存在几个固定的对象,那么这个就是枚举.我们就可以使用这些对象可以表示一些固定的值.
举例:一周只有7天,一年只有12个月等。
定义枚举类要用关键字enum
所有枚举类都是Enum的子类
枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
枚举类可以有构造器,但必须是private的,它默认的也是private的。枚举项的用法比较特殊:枚举(“”);
枚举类也可以有抽象方法,但是枚举项必须重写该方法
枚举在switch语句中的使用
int ordinal() 返回枚举项的序号
int compareTo(E o) 比较两个枚举项的 返回的是两个枚举项序号的 差值
String name() 获取枚举项的名称
String toString()获取枚举项的名称
<T> T valueOf(Class<T> type,String name) 用来获取指定的枚举项 参数1:枚举类对应的字节码对象 参数2 枚举项的名称
values() 获取所有的枚举项
此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便
1:
public static void main(String[] args) {
// 测试
Direction front = Direction.FRONT ;
Direction behind = Direction.BEHIND;
Direction left = Direction.LEFT ;
Direction right = Direction.RIGHT ;
System.out.println(front.ordinal());
System.out.println(behind.ordinal());
System.out.println(left.ordinal());
System.out.println(right.ordinal());
System.out.println("----------------------------------");
System.out.println(front.compareTo(right));
System.out.println(front.name());
System.out.println(front.toString());
System.out.println(front);
// <T> T valueOf(Class<T> type,String name): 用来获取指定的枚举项
// type: 表示的是对应的枚举的字节码文件对象
// name: 就是枚举项的名称
Direction direction = Direction.valueOf(Direction.class, "RIGHT") ;
System.out.println(direction);
Direction[] directions = Direction.values() ;
for(Direction d : directions){
System.out.println(d);
}
2
public enum Direction {
FRONT("前"), AFTER("后"), LEFT("后"),RIGHT("右"); //下面如果有代码,; 分号不要省略,每个枚举项,用逗号隔开
private Direction(String name){}
//public class Direction {
// //表示前后左右四个固定的值
// //ctrl+shift+U 转换大小写
// public static final org.westos.demo8.Direction FRONT = new org.westos.demo8.Direction("前");
// public static final org.westos.demo8.Direction AFTER = new org.westos.demo8.Direction("后");
// public static final org.westos.demo8.Direction LEFT = new org.westos.demo8.Direction("左");
// public static final org.westos.demo8.Direction RIGHT = new org.westos.demo8.Direction("右");
// public String name;
//
// private Direction(String name) {
// this.name = name;
// }
//}
public class MyTest {
Direction front = Direction.FRONT;
Direction after = Direction.AFTER;
Direction left = Direction.LEFT;
Direction right = Direction.RIGHT;
System.out.println(after);
System.out.println(left);
System.out.println(right);
为了增强对数值的阅读性,如我们经常把数据用逗号分隔一样。JDK7提供了_对数据分隔。
举例:
int x = 100_1000;
注意事项:
不能出现在进制标识和数值之间
不能出现在数值开头和结尾
不能出现在小数点旁边
LocalDate、 LocalTime、 LocalDateTime类的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间它们提供了简单的日期或时间,并不包含当前的时间信息。也不包含与时区相关的信息。
注: ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法
这些新增的日期时间API都在 java.time包下
1通过静态方法 now();
例如:LocalDateTime ldt = LocalDateTime.now();
1获取对象的方法 now()
注意默认获取出来的是当前的美国时间和我们相差八个小时
Instant ins = Instant.now();
System.out.println(ins);
我们在东八区 所以可以加8个小时 就是我们的北京时间
Instant中设置偏移量的方法:atOffset() 设置偏移量
OffsetDateTime time = ins.atOffset(ZoneOffset.ofHours(8));
System.out.println(time);
3.获取系统默认时区时间的方法atZone()
方法的参数是要一个时区的编号可以通过时区编号类获取出来
ZoneId.systemDefault()获取本地的默认时区ID
ZonedDateTime zonedDateTime = ins.atZone(ZoneId.systemDefault());
System.out.println(zonedDateTime);
4.get系列的方法
getEpochSecond() 获取从1970-01-01 00:00:00到当前时间的秒值
getNano()方法是把获取到的当前时间的秒数 换算成纳秒
long epochSecond = ins.getEpochSecond();//获取从1970-01-01 00:00:00到当前时间的秒值
getNano()方法是把获取到的当前时间的豪秒数 换算成纳秒 比如当前时间是2018-01-01 14:00:20:30
那就把30豪秒换算成纳秒 int nano = ins.getNano();
ofEpochSecond()方法 给计算机元年增加秒数
例如 Instant instant = Instant.ofEpochSecond(5);
System.out.println(instant);
单位换算
0.1 毫秒 = 10 的5次方纳秒 = 100000 纳秒
1 毫秒 = 1000 微妙 = 1000000 纳秒
Duration类中静态方法between()
Instant start = Instant.now();
for(int i=0;i<1000L;i++){
System.out.println("循环内容");
Instant end = Instant.now();
静态方法:between() 计算两个时间的间隔,默认是秒
Duration between = Durati’on.between(start, end);
Duration中的toMillis()方法:将秒转成毫秒
System.out.println(between.toMillis());
Period类 中的静态方法between()
计算两个日期之间的间隔
LocalDate s = LocalDate.of(1985, 03, 05);
LocalDate now = LocalDate.now();
Period be = Period.between(s, now);
System.out.println(be.getYears());间隔了多少年
System.out.println(be.getMonths());间隔了多少月
System.out.println(be.getDays());间隔多少天
一般我们用该接口的一个对应的工具类 TemporalAdjusters中的一些常量,来指定日期
System.out.println(now);
1 使用TemporalAdjusters自带的常量来设置日期
LocalDate with = now.with(TemporalAdjusters.lastDayOfYear());
System.out.println(with);
2 采用TemporalAdjusters中的next方法来指定日期
LocalDate date = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(date);
例如:TemporalAdjusters.next(DayOfWeek.SUNDAY) 本周的星期天
例如:TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY) 下一周的星期一
3 采用自定义的方式来指定日期 比如指定下个工作日
LocalDateTime ldt = LocalDateTime.now();
LocalDateTime workDay = ldt.with(new TemporalAdjuster() {br/>@Override
public Temporal adjustInto(Temporal temporal) {
//向下转型
LocalDateTime ld = (LocalDateTime) temporal;
//获取这周的星期几
DayOfWeek dayOfWeek = ld.getDayOfWeek();
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return ld.plusDays(3);//如果这天是星期五,那下个工做日就加3天
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return ld.plusDays(2);//如果这天是星期六,那下个工做日就加2天
} else {
//其他就加一天
return ld.plusDays(1);
});
1.获取对象的方式,通过静态方法ofPattern("yyyy-MM-dd");
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDateTime now = LocalDateTime.now();
2.format()方法把一个日期对象的默认格式 格式化成指定的格式
String format1 = dateFormat.format(now);
System.out.println(format1);
3.格式化日期 方式2使用日期类中的format方法 传入一个日期格式化类对象
4.使用自定义的日期格式格式化字符串
DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//自定义一个日期格式
String time = now1.format(timeFormat);
把一个日期字符串转成日期对象
使用日期类中的parse方法传入一个日期字符串,传入对应的日期格式化类
LocalDateTime parse = LocalDateTime.parse(time, timeFormat);
System.out.println(parse);
用法和 LocalDate、 LocalTime、 LocalDateTime 一样 只不过ZonedDate,ZonedTime、ZonedDateTime 这三个带有当前系统的默认时区
1.获取世界各个地方的时区的集合 的方法getAvailableZoneIds()
使用ZoneID中的静态方法getAvailableZoneIds();来获取
例如:Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
2.获取系统默认时区的ID
ZoneId zoneId = ZoneId.systemDefault(); //Asia/Shanghai
3.获取带有时区的日期时间对象
//创建日期对象
//获取不同国家的日期时间根据各个地区的时区ID名创建对象
ZoneId timeID = ZoneId.of("Asia/Shanghai");
//根据时区ID获取带有时区的日期时间对象
ZonedDateTime time = now.atZone(timeID);
//方式2 通过时区ID 获取日期对象
LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(now2);
Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
public interface MyInterface {
void show(int a,int b);
//JDK1.8之后提供了一种新的语法 叫做 Lambda表达式,可以简化我们对匿名内部类的写法,也可以作为参数传递
//可以使用匿名内部类来创建该接口的一个子类对象
MyInterface myInterface = new MyInterface() {br/>@Override
public void show(int a, int b) {
System.out.println(a + b);
};
myInterface.show(10, 20);
//上面匿名内部类的写法,我可以用Lambda表达式来简化
//Lambda 引入了一个箭头 -> 符号,将我们的表达式分为左右两部分
//箭头左边,就是接口中抽象方法的参数列表,箭头右边,是你对接口中的抽象方法的具体的重写逻辑
//参数列表中的数据类型 可以省略不写
MyInterface myInterface3 = (x, y) -> System.out.println(x + y);
//当然你可以写上参数的,数据类型
MyInterface myInterface2 = (int x, int y) -> System.out.println(x + y);
public class MyTest2 {
MyInterface2 myInterface2 = new MyInterface2() {br/>@Override
public int test(int a, int b) {
return a + b;
private static void myTest(MyInterface myInterface) {
myInterface.show(10,20);
通过上面的对比,发现Lambda表达式式书写起来更为简洁
那我们具体来看一下Lambda表达式的书写语法
Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “ ->” , 该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分:
左侧: 指定了 Lambda 表达式需要的所有参数
右侧: 指定了 Lambda 体,即 Lambda 表达式要执行的功能。
public interface MyInteface3 {
void test();
void show();
new MyInteface3(){br/>@Override
public void test() {
//Lambda 需要 函数式接口的支持
// 函数式接口:这个接口中,仅仅只有 一个抽象方法
// 函数式接口可以使用注解 @FunctionalInterface 来检测这个接口是不是函数式接口
public class MyTest3 {
上述 Lambda 表达式中的参数类型都是由编译器推断得出的。 Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。 Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”.
Lambda表达式就是对函数式接口的一种简写方式,所以只有是函数式接口,我们才能用Lambda表达式.再换句话说,Lambda表达式需要函数式接口的支持,那函数式接口我们可以自己定义,当然JDK1.8也给我们提供了一些现成的函数式接口.
你可以通过 Lambda 表达式来创建该接口的对象
我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.
函数式接口 参数类型 返回类型 用途
Consumer<T>
消费型接口 T void 对类型为T的对象应用操
作,包含方法:
void accept(T t)
Supplier<T>
供给型接口 无 T 返回类型为T的对象,包
含方法: T get();
Function<T, R>
函数型接口
T R 对类型为T的对象应用操
作,并返回结果。结果
是R类型的对象。包含方
法: R apply(T t);
Predicate<T> 断言型接口
T boolean 确定类型为T的对象是否
满足某约束,并返回
boolean 值。包含方法
boolean test(T t);
BiFunction<T,U,R>
T U R 对类型为 T, U 参数应用
操作, 返回 R 类型的结
果。 包含方法为
R apply(T t, U u);
UnaryOperator<T>
(Function的子接口)
T T 对类型为T的对象进行一
元运算, 并返回T类型的
结果。 包含方法为
T apply(T t);
BinaryOperator<T>
(BiFunction的子接口) T T T 对类型为T的对象进行二
T apply(T t1, T t2);
BiConsumer<T,U>
T U void 对类型为T, U 参数应用
操作。 包含方法为
void accept(T t, U u)
ToIntFunction<T>
ToLongFunction<T>
ToDoubleFunction<T>
T int
long
double 分 别 计 算 int 、 long 、
double、 值的函数
IntFunction<R>
LongFunction<R>
DoubleFunction<R>
int
double R 参数分别为int、 long、
double 类型的函数
Stream 是 Java8 中处理集合的关键抽象概念,
它可以指定你希望对集合进行的操作,
可以执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。
简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,流讲的是计算!
注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream 的操作三个步骤
1.创建 Stream
一个数据源(如:集合、数组),获取一个流
2.中间操作
一个中间操作链,对数据源的数据进行处理
3.终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果
default Stream<E> stream() : 返回一个顺序流
default Stream<E> parallelStream() : 返回一个并行流
2.Java8 中的 Arrays 的静态方法 stream() 可以获取数组流:
static <T> Stream<T> stream(T[] array): 返回一个流
重载形式,能够处理对应基本类型的数组:
public static IntStream stream(int[] array)
public static LongStream stream(long[] array)
public static DoubleStream stream(double[] array)
3.由值创建流,可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。
public static<T> Stream<T> of(T... values) : 返回一个流
4.由函数创建流:创建无限流可以使用静态方法 Stream.iterate()和Stream.generate(), 创建无限流。
public static<T> Stream<T> iterate(final T seed, finalUnaryOperator<T> f) 迭代
public static<T> Stream<T> generate(Supplier<T> s) 生成
筛选与切片
filter(Predicate p) 过滤 接收 Lambda , 从流中排除某些元素。
distinct() 去重,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize) 截断流,使其元素不超过给定数量。
skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
2.映射
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流.
mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。
mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。
3.排序
sorted() 产生一个新流,其中按自然顺序排序 元素实现Compareble接口
sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序 传入一个比较器
终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void 。
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。
Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换。
public Employee() {
//**Stream 的操作三个步骤
//1. 创建 Stream
//一个数据源(如:集合、数组),获取一个流
//2. 中间操作
//一个中间操作链,对数据源的数据进行处理
//3. 终止操作(终端操作)
//一个终止操作,执行中间操作链,并产生结果
//我们会创建流跟集合关联起来,关联起来后,我们是想要使用这个流对集合中的元素,进行一些列的中间操作
//1. 筛选与切片
//filter(Predicate p) 过滤 接收 Lambda ,从流中排除某些元素。
//distinct() 去重,通过流所生成元素的 hashCode () 和 equals () 去除重复元素
//limit( long maxSize)截断流,使其元素不超过给定数量。
//skip( long n)跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit (n) 互补
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "张三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "赵六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);
new Employee(104, "赵六", 8, 7777.771),
new Employee(104, "赵六", 8, 7777.772),
new Employee(104, "赵六", 8, 7777.773),