I/O流
intern()方法:
首先会去常量池中查看是否存在这样的对象,如果不存在,则创建,创建好之后再将这个常量池中创建的内存地址赋值给相应的引用。
String s4 = s3.intern();
String s5 = "管理员很水";//由于s4已经在常量池中创建了字符串"管理员很水",此时只需要将这个字符串的内存地址赋给s5即可
System.out.println(s4 == s5);//true
File类的常用操作
1. File类的作用
java.io.File
类是对存储在磁盘上的文件信息的一个抽象表示。主要用于文件的创建、查找和删除
2.File的构造方法
/**
* File 的构造方法
*/
public class FileTest {
public static void main(String[] args) {
File f1 = new File("D:\\io\\io.txt");
File f2 = new File("D:\\io","io.txt");
File f3 = new File("D:\\io");//先创建父文件
File f4 = new File(f3 , "io.txt");//后子文件
System.out.println(f3);
}
}
3.常用方法
//绝对路径:带有盘符的路径称之为绝对路径
//相对路径:不带盘符的路径称之为相对路径,相对路径相对于当前工程来定位的。
public String getAbsolutePath(); //获取文件的绝对路径
public String getName();//获取文件的名字
public String getPath();//获取文件的路径
public File getParentFile();//获取文件的父文件
public String getParent();//获取文件的父文件路径
public long length();//获取文件的大小
public long lastModified();//获取文件最后修改时间
public boolean canRead();//是否可读
public boolean canWrite();//是否可写
public boolean exists();//是否存在
public boolean isDirectory();//是否是目录
public boolean isFile();//是否是一个正常的文件
public boolean isHidden();//是否隐藏
public boolean canExecute();//是否可执行
public boolean createNewFile() throws IOException;//创建新的文件
public boolean delete();//删除文件
public boolean mkdir();//创建目录,一级
public boolean mkdirs();//创建目录,多级
public boolean renameTo(File dest);//文件重命名,重命名后,原来的文件就不存在了
public File[] listFiles();//列出文件夹下所有文件
注意:删除文件夹时必须保证文件夹为空,否则将删除失败
4.递归
在方法内部再调用自身就是递归。递归分为直接递归和间接递归。
直接递归就是方法自己调用自己。
间接递归就是多个方法之间相互调用,形成一个闭环,从而构成递归。
使用递归时必须要有出口,也就是使递归停下来。否则,将导致栈内存溢出。
I/O流
概念:
I/O流就是磁盘与内存是实现交互的通道
read --- 就是向内存写数据----- "Input"通常指的是输入流,用于从外部源(如文件、网络或其他设备)读取数据。
write ---- 就是将内存中的数据取出来存储到磁盘()----- "Output"通常指的是输出流,用于将数据写入到外部目标(如文件、网络或其他设备)。
字节流
文件输出流 FileOutputStream 构造方法
就是将内容写入文件中
文件输入流 FileInputStream 构造方法
就是将文件中的内容读入内存中
如果通道中数据长度过长,那么根据通道中数据的长度来构建字节数组,则可能导致内存不够,比如使用流读取一个大小为10G的文件,那么通道中就应该存在10G长的数据,此时应该怎么办?
利用字节数组来存,初始化一个字节数组长度,一般是1024,2048等
练习
使用字节流实现磁盘文件拷贝功能
public static void main(String[] args) {
copyFile(new File("D:\\io\\io.txt"),new File("D:\\ios\\io.txt"));
}
public static void copyFile(File source, File dest){
//先判断接收内容的文件夹是否存在,不存在就创建
File parentFile = dest.getParentFile();
if (!parentFile.exists()){
parentFile.mkdirs();
}
try {
InputStream in = Files.newInputStream(source.toPath());
OutputStream out = Files.newOutputStream(dest.toPath());
byte[] bytes = new byte[1024];//利用字节数组
int len;
while((len = in.read()) != -1){
out.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
字符流
FileReader:将文件读入内存
FileWriter:将内容写入文件
示例
public static void main(String[] args) {
String sourceFile = "F:\\AA\\io.txt";
String destFile = "F:\\file\\a.txt";
copyFile(sourceFile, destFile);
}
public static void copyFile(String sourceFile, String destFile){
File file = new File(destFile);
File parent = file.getParentFile();
if(!parent.exists()) parent.mkdirs();
try (Reader reader = new FileReader(sourceFile);
Writer writer = new FileWriter(file)){
char[] buffer = new char[4096];
while (true){
int len = reader.read(buffer);
if(len == -1) break;
writer.write(buffer, 0, len);
}
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
缓冲流Buffered
BufferedWriter 构造方法
public BufferedWriter(Writer out);//根据给定的字符输出流创建一个缓冲字符输出流,缓冲区大小使用默认大小
public BufferedWriter(Writer out, int sz);//根据给定的字符输出流创建一个缓冲字符输出流,并指定缓冲区大小
BufferedReader 构造方法
public BufferedReader(Reader in); //根据给定的字符输入流创建一个缓冲字符输入流,缓冲区大小使用默认大小
public BufferedReader(Reader in, int sz);//根据给定的字符输入流创建一个缓冲字符输入流,并指定缓冲区大小
示例
使用缓冲字符流实现磁盘文件拷贝功能
public static void main(String[] args) {
copyFile(new File("D:\\io\\hello.txt"),new File("D:\\ios\\h.txt"));
}
public static void copyFile(File source, File dest){
//先判断接收内容的文件夹是否存在,不存在就创建
File parentFile = dest.getParentFile();
if (!parentFile.exists()){
parentFile.mkdirs();
}
try {
BufferedReader reader = new BufferedReader(new FileReader("D:\\io\\hello.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("D:\\ios\\h.txt"));
char[] buffer = new char[4096];
int len;
while((len = reader.read()) != -1){
writer.write(buffer,0,len);
writer.flush();
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
对象流
正如二进制数据流支持原始数据类型的I / O一样,对象流也支持对象的I / O。大多数(但不是全部)标准类支持其对象的序列化。那些类实现了序列化标记接口Serializable才能够序列化。
将一个对象从内存中写入磁盘文件中的过程称之为序列化。序列化必须要求该对象所有类型实现序列化的接口Serializable
MyDay10->Test05
将磁盘中存储的对象信息读入内存中的过程称之为反序列化,需要注意的是,反序列化必须保证与序列化时使用的JDK版本一致
MyDay10->Test06
函数式接口
1.什么是函数式接口
函数式接口是仅包含一种抽象方法的任何接口。有且仅有一种。(一个函数式接口可能包含一个或多个默认方法或静态方法。)由于一个函数式接口仅包含一个抽象方法,因此在实现该方法时可以省略该方法的名称。
package com.qf.functional;
public interface Hello {
void sayHello(String name);
static void show(){} //JDK8
default void print(){} //JDK8
private void test(){} // JDK9
}
@FunctionalInterface >> 可以用来判断是否只有一个函数式接口,超过一个就报错。
2.函数式编程
就是在实现类里面用一个变量来代替一个函数式接口。这就相当于办一个函数赋值给另一个变量,只能使用lamada表达式类实现。
3.Lambda
表达式延迟执行
String...infos >> 表示可以有0->多个String类型的参数。
// Printable p = new Printable() {
// @Override
// public void print(String msg) {
// System.out.println(msg);
// }
// };
//lambda表达式的书写规则:
//1、保留接口方法的参数列表以及后面的方法体
//2、在参数列表与方法体之间加一个 ->
// Printable p = (String msg) -> {System.out.println(msg);};
// p.print("输出");
//lambda表达式在编写的时候可以进行省略,省略规则如下:
//1、因为函数式接口中的参数列表是定死的,因此,参数列表的类型是可以推导,参数列表的类型可以省略
// Printable p = (msg)->{
// System.out.println(msg);
// };
// p.print("输出");
//2、如果参数列表只有一个参数,那么()是可以省略的
// Printable p = msg -> {
// System.out.println(msg);
// };
// p.print("输出");
//3、如果方法体的实现只有一行代码,那么{}是可以省略的,这行代码的分号也是可以省略的
Printable p = msg -> System.out.println(msg);
p.print("输出");
4.Consumer
接口
Consumer是一个消费者,消费一个数据。
void accept(T t);//接收一个被消费的数据
5.BiConsumer
接口
BiConsumer
也是一个消费者,只是这个消费者可以一次性消费两个数据(一般是键值对)。至于如何消费,就需要看这个接口被如何实现。
void accept(T t, U u);//接收两个被消费的数据
6.Predicate
接口
Predicate
是条件的意思,可以检测给定数据是否满足条件,也可以与其他条件进行衔接。至于如何检测,就需要看这个接口被如何实现。
boolean test(T t);//检测是否满足条件
default Predicate<T> and(Predicate<? super T> other);//条件之间的逻辑与衔接
default Predicate<T> negate();//条件取反
default Predicate<T> or(Predicate<? super T> other);//条件之间的逻辑或衔接
主要是用来作比较的时候去使用。
练习
学生有姓名、性别和年龄。现有一个集合内存储有10名学生信息,请找出其中性别为男,年龄在20岁以上的学生,并在控制台进行输出
public class Student {
private String name;
private String sex;
private int age;
public Student() {
}
public Student(String name, String sex,int age) {
this.name = name;
this.sex=sex;
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class Work01 {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();//定义一个数组来存
Random r = new Random();
for(int i =0;i<20;i++){
Student stu = new Student();
stu.setName("user" + i);
int num = r.nextInt(10);
stu.setSex(num % 3 == 0 ? "男": num%3==1 ? "女" : "其他");
stu.setAge(r.nextInt(20) + 10);
list.add(stu);
System.out.println(stu);
}
System.out.println("---------------------------------");
// Predicate<Student> s1 = new Predicate<Student>() {
// @Override
// public boolean test(Student student) {
// return "男".equals(student.getSex());
// }
// };
// Predicate<Student> s2 = new Predicate<Student>() {
// @Override
// public boolean test(Student student) {
// return student.getAge()>20;
// }
// };
Predicate<Student> s1 = student->
"男".equals(student.getSex());
Predicate<Student> s2 = student->
student.getAge()>20;
Predicate<Student> s3 = s1.and(s2);
list.forEach(new Consumer<Student>() {
@Override
public void accept(Student student) {
if (s3.test(student)){
System.out.println(student);
}
}
});
}
}
输出:
![](C:\Users\17866\Desktop\文件夹\笔记\博客截图\屏幕截图 2023-07-15 153931.png)
7.Function
接口
Function
是功能的意思,可以将一种数据类型的对象转换为另一种数据类型的对象,至于如何转换,就需要看这个接口被如何实现
R apply(T t); //将一个对象转换为另一种数据类型的对象
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after);//复合转换
示例
先将一个String类型的“10”装换成Integer类型,再将Integer类型转换int类型
public static void main(String[] args) {
// Function f = new Function<String, Integer>() {
// @Override
// public Integer apply(String s) {
// return Integer.parseInt(s);
// }
// };
//将String类型转换为Integer类型
Function<String,Integer> f = s ->Integer.parseInt(s);
Integer in = f.apply("10");
System.out.println(in);
//将Student类型装换为Integer类型
// Function<Student, Integer> f2 = new Function<Student, Integer>() {
// @Override
// public Integer apply(Student student) {
// return student.getAge();
// }
// };
Function<Student,Integer> stu = student-> student.getAge();
//先创建一个对象,在加一组数据。进行实验
Student s = new Student();
s.setName("李白");
s.setSex("男");
s.setAge(99);
Integer apply = stu.apply(s);
System.out.println(apply);
//赋值的数组在赋值过程中发生了装箱,使用了Integer.valueOf()方法
//拆箱使用的xxxValue(), 这里的xxx要看是什么数据类型。比如整数如果
//发生拆箱,那么就需要使用intValue();
stream流
1、管道
管道就是一系列的聚合操作。
源:可以是集合,数组,生成器函数或I / O通道。
2、流
流是一系列元素。 与集合不同,它不是存储元素的数据结构。 取而代之的是,流通过管道携带来自源的值。
3、如何获取Stream
流
Collection
接口
default Stream<E> stream();
Stream
接口
//获取流
public static<T> Stream<T> of(T... values);
//将两个流拼接形成一个新的流
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);
示例
List<Integer> numbers1 = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> s1 = numbers1.stream();
s1.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer%2 ==0;
}
}).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
输出
2
4
Stream<Integer> s2 = Stream.of(6, 7, 8, 9, 10);
s2.forEach(System.out::println);//打印出来
Stream.concat
可以将两个stream流拼接起来
示例
List<Integer> numbers1 = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> s1 = numbers1.stream();
Stream<Integer> s2 = Stream.of(6, 7, 8, 9, 10);
Stream<Integer> s3 = Stream.concat(s1, s2);
s3.forEach(System.out::println);
输出
1
2
3
4
5
6
7
8
9
10
对于集合也是一样的
示例
Map<String,Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
Stream<Map.Entry<String,Integer>> s4 = map.entrySet().stream();
s4.forEach(System.out::println);
输出
a=1
b=2
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);//将流中元素全部转为双精度浮点数
示例
Stream<Integer> s= Stream.of(1, 2, 2, 7, 4, 6, 3);
//去重
//s.distinct().forEach(System.out::println);
//去重过后就不能再对s进行操作,应为s已经被操作过了,被放入另外一条管道里面去了
//排序
//s.sorted().forEach(System.out::println);
// s.sorted((o1, o2)-> o1 - o2).forEach(System.out::println);//升
//s.sorted(Comparator.comparingInt(o -> o)).forEach(System.out::println);
//s.sorted((o1, o2)-> o2 - o1).forEach(System.out::println);//降
//从指定位置打印
//s.skip(2).forEach(System.out::println);
//limit方法可以用来限制管道中元素的个数
// s.limit(5).forEach(System.out::println);
示例
Integer[] numbers = {1,2,3,4};
// IntStream intStream= Arrays.stream(numbers).mapToInt(new ToIntFunction<Integer>() {
// @Override
// public int applyAsInt(Integer value) {
// return value.intValue();
// }
// });
//mapToInt是将包装类型的整数转换为原始类型的整数
// 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));
//将int类型转换为Integer类型
Stream<Integer> boxed = Arrays.stream(array).boxed();
//IntFunction是一个转换接口,泛型就是决定转换的目标类型(第一步)
// Integer[] array1 = boxed.toArray(new IntFunction< Integer[]>() {
// @Override
// public Integer[] apply(int value) {
// return new Integer[value];
// }
// });
// Integer[] array1 = boxed.toArray((int value) -> new Integer[value]);//(第二步)
Integer[] array1 = boxed.toArray(Integer[]::new);
System.out.println(array1.getClass());
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);//检测流中元素是否全部不满足给定条件
示例
public static final char[] CHARACTERS ={
'a','b','c','d','e','f','g','h','i','l','m','n'
};
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);
users.add(user);
}
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
users.add(user);
String username = "admin1";
System.out.println(username);
// users.stream().filter(new Predicate<User>() {//第一步
// @Override
// public boolean test(User u) {
// return u.getUsername().equals(u.getUsername());
// }
// });
Stream<User> stream = users.stream().filter(u -> u.getUsername().equals(username));//第二步
//针对过滤后还存在元素进行收集, 收集的时候需要指定收集的方式
//这里我们指定的收集方式是收集为一个List集合
List<User> userList = stream.collect(Collectors.toList());
// Set<User> collect = 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);
}
});
//在Stream流的管道中存在的元素,只要任意一个元素满足给定的条件,结果就为真
// if (users.stream().anyMatch(new Predicate<User>() {//第一步
// @Override
// public boolean test(User u) {
// return u.getUsername().equals(username);
// }
// })) {}
if (users.stream().anyMatch((User u)-> u.getUsername().equals(username)
)) {
System.out.println(username + "已经被注册");
}
//在Stream流的管道中存在的元素,不存在任何元素满足给定的条件,结果就是真
if (users.stream().noneMatch(u->u.getUsername().equals(username))) {
System.out.println(username + "可以注册");
}
//在Stream流的管道中存在所有元素都必须满足给定的条件,结果就为真
if (users.stream().allMatch(u->u.getUsername().length()>=5)) {
System.out.println("所有的用户的用户名长度均 >= 5");
}
Integer[] numbers = {1,2,3,4,5};
//long count = Arrays.stream(numbers).count();
System.out.println();
}
private static String randomStr(int length){
StringBuilder builder = new StringBuilder();
Random random = new Random();
for (int i = 0; i <length ; i++) {
int index = random.nextInt(CHARACTERS.length);
builder.append(CHARACTERS[index]);
}
return builder.toString();
}
面试题
使用Stream流将一个基本数据类型的数组转换为包装类型的数组,再将包装类型的数组转换基本数据类型数组。
int[] intArr1 = {1, 2, 3, 4, 5};
// Integer[] intArr2 = Arrays.stream(intArr1).mapToObj(new IntFunction<Integer>() {
// @Override
// public Integer apply(int value) {
// return value;
// }
// }).toArray(new IntFunction<Integer[]>() {
// @Override
// public Integer[] apply(int value) {
// return new Integer[value];
// }
// });
// Integer[] intArr2 = Arrays.stream(intArr1).mapToObj(value -> value).toArray(Integer[]::new);
Integer[] intArr2 = Arrays.stream(intArr1).boxed().toArray(Integer[]::new);
Integer[] intArr3 = {1,2,3,4,5};
int[] intArr4 = Arrays.stream(intArr3).mapToInt(Integer::intValue).toArray();
6、包装类
基本数据类型 | 包装类 | 基本数据类型 | 包装类 |
int | Integer | char | Character |
byte | Byte | boolean | Boolean |
short | Short | float | Float |
long | Long | double | Double |
自动装箱和拆箱
自动装箱方法
包装类名.valueOf(原始数据类型的值);
示例
//变量num期望获取一个整数对象,但赋值时给定的是一个基本数据类型int值,此时编译器将会将int值5进行包装
//调用的是Integer.valueOf(5)
Integer num = 5;
自动拆箱
Similarly, if you use a number object when a primitive is expected, the compiler unboxes the object for you.
类似地,如果在期望使用基本数据类型的情况下使用包装类型,则编译器会为你解包该对象。
自动拆箱方法
包装类对象.xxxValue();
示例
Integer num = new Integer(10);
//变量a期望获取一个基本数据类型的值,但赋值时给定的是一个引用数据类型的对象,此时编译器会将这个引用数据类型
//的对象中存储的数值取出来,然后赋值给变量a。调用的是num.intValue();
int a = num;
8.Date类和SimpleDateFormat类
方法:
public Date(); //无参构造,表示计算机系统当前时间,精确到毫秒
public Date(long date);//带参构造,表示根据给定的时间数字来构建一个日期对象,精确到毫秒
public long getTime();//获取日期对象中的时间数字,精确到毫秒
public boolean before(Date when);//判断当前对象表示的日期是否在给定日期之前
public boolean after(Date when);//判断当前对象表示的日期是否在给定日期之后
public SimpleDateFormat(String pattern); //根据给定的日期格式构建一个日期格式化对象
public final String format(Date date);//将给定日期对象进行格式化
常用日期格式
字母 | 含义 | 说明 |
y | 年year | 不区分大小写,一般用小写 |
M | 月month | 区分大小写,只能使用大写 |
d | 日day | 区分大小写,只能使用小写 |
H | 时hour | 不区分大小写,一般用大写 |
m | 分minute | 区分大小写,只能使用小写 |
s | 秒second | 区分大小写,只能使用小写 |
应用
public static void main(String[] args) {
Date date = new Date();
System.out.println(date);
long l = System.currentTimeMillis();
System.out.println(l);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(format.format(l));
System.out.println(date.getTime());
Date date1 = new Date();
boolean b = date.before(date1);//true
boolean a = date.after(date1);//false
System.out.println(b);
System.out.println(a);
}
9.Calendar
类
常用静态字段
字段值 | 含义 |
YEAR | 年 |
MONTH | 月,从0开始 |
DAY_OF_MONTH | 月中第几天 |
HOUR | 时(12小时制) |
HOUR_OF_DAY | 时(24小时制) |
MINUTE | 分 |
SECOND | 秒 |
DAY_OF_WEEK | 周中第几天,一周的第一天是周日,因此周日是1 |
常用方法
public static Calendar getInstance();//获取日历对象
public final Date getTime();//获取日历表示日期对象
public final void setTime(Date date);//设置日历表示的日期对象
public int get(int field);//获取给定的字段的值
public void set(int field, int value);//设置给定字段的值
public void roll(int field, int amount);//根据给定的字段和更改数量滚动日历
public int getActualMaximum(int field);//获取给定字段的实际最大数量
案例:做一个日历
public static void main(String[] args) {
showCalendar(2023, 6);
// yyyy-MM-dd HH:mm:ss
// yyyy/MM/dd HH:mm:ss
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
System.out.println(format.format(new Date()));
}
//日历的制作需要给两个参数:年份和月份
public static void showCalendar(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);
//这一步一定要做,防止日历当前的天数是31,如果滚动到上个月就会出问题
// c.set(Calendar.DAY_OF_MONTH, 1);
int lastMonthMaxDays = c.getActualMaximum(Calendar.DAY_OF_MONTH);
//上个月开始的天数
int start = lastMonthMaxDays - lastMonthDays + 1;
List<Integer> days = new ArrayList<>();
for(int i=start; i<=lastMonthMaxDays; i++){
days.add(i);
}
//当前月要展示的天数
for(int i=1; i<=maxDays; i++){
days.add(i);
}
//计算下一个月要展示多少天
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();
}
}
private static void demo(){
//获取系统当前时间
Date date = new Date();
System.out.println(date);
//日历, 获取一个日历的实例,这个实例一产生就是当前系统的时间
Calendar c = Calendar.getInstance();
//获取日历的当前日期
Date time = c.getTime();
//获取日历的年份
int year = c.get(Calendar.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.MONTH, -5);
int maxDays = c.getActualMaximum(Calendar.DAY_OF_MONTH);
System.out.println(maxDays);
//设置日期目前处于的天数
c.set(Calendar.DAY_OF_MONTH, 2);
//获取当前日历表示的一周的星期几
int week = c.get(Calendar.DAY_OF_WEEK);
System.out.println(week);
}
标签:函数,stream,int,接口,String,Integer,new,public,out
From: https://blog.51cto.com/u_16154651/7146652