首页 > 其他分享 >I/O流、stream流、函数式接口

I/O流、stream流、函数式接口

时间:2023-08-19 10:37:56浏览次数:29  
标签:函数 stream int 接口 String Integer new public out

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

相关文章

  • 使用接口管理微信收藏夹
    获取收藏信息小提示:获取收藏相关信息注意:该接口作用不大请求URL:http://域名地址/api/favor/getinfo请求方式:POST请求头:Content-Type:application/jsonX-GEWE-TOKEN:后台获取参数:参数名称数据类型必填说明appid是string设备idsync_key是string返回数据:参数名数据类型说明retnumber0:......
  • 无涯教程-Perl - wait函数
    描述该函数等待子进程终止,返回已故进程的进程ID。进程的退出状态包含在$?中。语法以下是此函数的简单语法-wait返回值如果没有子进程,则此函数返回-1,否则将显示已故进程的进程ID参考链接https://www.learnfk.com/perl/perl-wait.html......
  • Python提取函数参数 inspect​​​模块
    1解析为字典https://blog.csdn.net/tutan123321/article/details/131319113defprint_params(**params):forkey,valueinparams.items():print(key+":"+str(value))2 __code__https://blog.csdn.net/weixin_44224529/article/details/1212588953i......
  • fastjson对接口参数的某个字段不打印输出,如文件的base64字符串
    fastjson对接口参数的某个字段不打印输出,如文件的base64字符串packagecom.example.core.mydemo.json5;importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.annotation.JSONField;/**需要提供getset方法,如果使用@Datalombok不生效(关键)**publicclassIte......
  • base64图片文件上传OSS,下载OSS图片转换为InputStream,文件转base64,base64转文件工具类
    base64图片文件上传OSS,下载OSS图片转换为InputStream,文件转base64,base64转文件工具类OSSUtils.javapublicclassOSSUtils{privatestaticLoggerlogger=LoggerFactory.getLogger(OSSUtils.class);privatestaticfinalStringACCESS_ID="阿里云oss参数acce......
  • 容器内部使用的比较函数书写方式
    例如:priority_queue为例子。#include<queue>std::priority_queue<Type,Container,Compare>pq;type:优先队列中存储的元素的数据类型。Container:存储元素的底层容器类型,默认为std::vector<Type>Compare:比较函数或函数对象,用于定义元素的比较原则,可以是一个函数指针、函数对象......
  • 容器内部使用的比较函数书写方式
    例如:priority_queue为例子。#include<queue>std::priority_queue<Type,Container,Compare>pq;type:优先队列中存储的元素的数据类型。Container:存储元素的底层容器类型,默认为std::vector<Type>Compare:比较函数或函数对象,用于定义元素的比较原则,可以是一个函数指针、函数对象......
  • 容器内部使用的比较函数书写方式
    例如:priority_queue为例子。#include<queue>std::priority_queue<Type,Container,Compare>pq;type:优先队列中存储的元素的数据类型。Container:存储元素的底层容器类型,默认为std::vector<Type>Compare:比较函数或函数对象,用于定义元素的比较原则,可以是一个函数指针、函数对象......
  • 容器内部使用的比较函数书写方式
    例如:priority_queue为例子。#include<queue>std::priority_queue<Type,Container,Compare>pq;type:优先队列中存储的元素的数据类型。Container:存储元素的底层容器类型,默认为std::vector<Type>Compare:比较函数或函数对象,用于定义元素的比较原则,可以是一个函数指针、函数对象......
  • 容器内部使用的比较函数书写方式
    例如:priority_queue为例子。#include<queue>std::priority_queue<Type,Container,Compare>pq;type:优先队列中存储的元素的数据类型。Container:存储元素的底层容器类型,默认为std::vector<Type>Compare:比较函数或函数对象,用于定义元素的比较原则,可以是一个函数指针、函数对象......