java常用方法

前端

集合

1:concat();
2:join();
3:pop();
4:shift();
5:unshift();
7:reverse();
8:sort();
9:slice();
10:splice();
11:toString();
12:valueOf();
13:IndexOf();
14:lastIndexOf();
15:forEach();
16:map();
17:filter();
18:every();
19:some();
20.reduce();
image-20220427215819079

includes

1)第一个参数是要查找的元素

2)第二个参数表示搜索的起始位置,默认为 0 。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为 -4 ,但数组长度为 3 ),则会重置为从 0 开始。

只有一个参数情况

[1, 2, 3].includes(2); // true
 
[1, 2, 3].includes(4); // false
 
[1, 2, NaN].includes(NaN); // true

两个参数的情况

[1, 2, 3].includes(3, 3); // false
 
[1, 2, 3].includes(3, -1); // true
  1. concat功能:

    功能:合并数组,可以合并一个或多个数组,会返回合并数组之后的数据,不会改变原来的数组

    var str1 = [12,2,"hello"];var str2 = ["world"];
    console.log(str1.concat(str2));        //[12, 2, "hello", "world"]
    console.log(str1);                //[12,2,"hello"];
    
  2. join();

    功能:将数组转为字符串并返回转化的字符串数据,不会改变原来的数组;

    注意:()中用双引号包括自己想用的分隔符,默认为逗号,这里方便观察,我用了-

    
    var str1 = [12,2,"hello"];
    var str2 = ["world"];
    console.log(str1.join("-"));        //12-2-hello
    console.log(str1);  
    
  3. pop();

    功能:删除数组的最后一位,并且返回删除的数据,会改变原来的数组

    var str1 = [12,2,"hello"];
    console.log(str1.pop()        //hello
    console.log(str1); //[12, 2]
    
  4. shift();

    功能:删除数组的第一位数据,并且返回删除的数据,会改变原来的数组

  5. unshift();

    功能:在数组的首位新增一个或多数据,并且返回新数组的长度,会改变原来的数组

    注意:unshift()方法返回的数据是新数组的长度,它增加的数据可以是一个也可以是多个,可以理解为增加一连串的数据,

    var str1 = [12,2,"hello"];
    var str2 = [43,2,"test"];
    console.log(str1.unshift("你好"));              //4
    console.log(str2.unshift("hello","world"));        //5
    console.log(str1);                       //["你好", 12, 2, "hello"]
    console.log(str2);                       //["hello", "world", 43, 2, "test"]
    
  6. push();

    功能:在数组的最后一位新增一个或多个数据,并且返回新数组的长度,会改变原来的数组

    注意:push()方法返回的是数据是新数组的长度,它增加的数据可以是一个也可以是多个,可以理解为增加一连串的数据。

  7. reverse();

    功能:将数组的数据进行反转,并且返回反转后的数组,会改变原数组

    var str1 = [12,2,"hello"];
    console.log(str1.reverse());      //["hello", 2, 12]
    console.log(str1);   
    
    
  8. 功能:对数组内的数据进行排序(默认为升序),并且返回排过序的新数组,会改变原来的数组

    1. 注意:

      8.1:这里的排序是针对字符的排序,先使用数组的toString()方法转为字符串,再逐位比较,3是大于12的,因为首位3>1,不要与Number型的数据排序混淆
      8.2:str2数组中增加了三个字符,可以看到,比较的时候,zoom是最大的,因为首位的英文字母通过ASCII码可以转为相应的数值,再根据数值比较

      var str1 = [12,2,43,5,2,5];
      var str2 = [92,2,43,"hello",'zoom',5,2,5];
      console.log(str1.sort());//[12, 2, 2, 43, 5, 5]
      console.log(str1);//[12, 2, 2, 43, 5, 5]
      console.log(str2.sort());//[2, 2, 43, 5, 5, 92, "abc", "hello", "zoom"]
      console.log(str2);//[2, 2, 43, 5, 5, 92, "abc", "hello", "zoom"]
      

      8.3:排序问题

    参数:sort(callback) 如果需要按照数值排序,需要传参。sort(callback),callback为回调函数,该函数应该具有两个参数,比较这两个参数,然后返回一个用于说明这两个值的相对顺序的数字(a-b)。其返回值如下:

    若 a 小于 b,返回一个小于 0 的值。

    若 a 等于 b,则返回 0。

    若 a 大于 b,则返回一个大于 0 的值。

    var str3 = [92,2,43,5,2,5];     
    console.log(str3.sort(fn));//[2, 2, 5, 5, 43, 92]
    str3.sort((a,b)=>a-b);
    console.log(str3); //[2, 2, 5, 5, 43, 92]
    
    function fn (a,b){
        return a-b;
     }
    
    
    
  9. slice()

    功能:截取指定位置的数组,并且返回截取的数组,不会改变原数组

    参数:slice(startIndex, endIndex)

    注意:可从已有的数组中返回选定的元素。该方法接收两个参数slice(start,end),stsrt为必选,表示从第几位开始;end为可选,表示到第几位结束(不包含end位),省略表示到最后一位;start和end都可以为负数,负数时表示从最后一位开始算起,如-1表示最后一位。

    var arr = ["T1","J1","L1","L2","M1"];
        console.log(arr.slice(1,3));        //["J1","L1"]
        console.log(arr.slice(1));          //["J1","L1","L2","M1"]
        console.log(arr.slice(-4,-1));      //["J1","L1","L2"]
        console.log(arr.slice(-2));         //["Lily","M1"]
        console.log(arr.slice(1,-2));       //["J1","L1"]
        console.log(arr);                   //["T1","J1","L1","L2","M1"]
    
  10. splice

    删除的指定元素

    可以用于删除数组中的指定元素使用splice()会影响到原数组,会将指定元素从原数组中删除并将被删除的元素作为返回值返回参数:

    ​ 第一个,表示开始位置的索引

    第二个,表示删除的数量

    • 第三个及以后。。
    • 可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边
    • */
    var arr = ["Tom","Jack","Lucy","Lily","May"];
    console.log(arr.splice(2,0,"a","b"));//[]
    console.log(arr);//["Tom", "Jack", "a", "b", "Lucy", "Lily", "May"]---原数组改变
    
  11. toString();

    功能:将数组转换成字符串,类似于没有参数的join()。该方法会在数据发生隐式类型转换时被自动调用,如果手动调用,就是直接转为字符串。不会改变原数组

    var str = [1,2,3];
    console.log(str.toString()); //1,2,3
    console.log(str);//[1,2,3]
    
  12. 功能:返回数组的原始值(一般情况下其实就是数组自身),一般由js在后台调用,并不显式的出现在代码中

    var str = [1,2,3];
    console.log(str.valueOf()); //[1,2,3]
    console.log(str); //[1,2,3]
    //为了证明返回的是数组自身
    console.log(str.valueOf() == str);//true
    
  13. IndexOf

    功能:根据指定的数据,从左向右,查询在数组中出现的位置,如果不存在指定的数据,返回-1,找到了指定的数据返回该数据的索引

    参数:indexOf(value, start);value为要查询的数据;start为可选,表示开始查询的位置,当start为负数时,从数组的尾部向前数;如果查询不到value的存在,则方法返回-1

    var str = ["h","e","l","l","o"];
     console.log(str.indexOf("l"));        //2
     console.log(str.indexOf("l",3));      //3
     console.log(str.indexOf("l",4));      //-1
     console.log(str.indexOf("l",-1));     //-1
     console.log(str.indexOf("l",-3));     //2
    
  14. lastIndexOf();

    功能:lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,如果指定第二个参数 start,则在一个字符串中的指定位置从后向前搜索。

    参数:lastIndexOf(value, start);value为要查询的数据;start为可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的最后一个字符处开始检索。

    var str = ["h","e","l","l","o"];
    console.log(str.lastIndexOf("l"));        //3
    console.log(str.lastIndexOf("l",3));      //3
    console.log(str.lastIndexOf("l",4));      //3
    console.log(str.lastIndexOf("l",-1));     //3
    console.log(str.lastIndexOf("l",-3));     //2
    
    • 注意: 该方法将从后向前检索字符串,但返回是从起始位置 (0) 开始计算子字符串最后出现的位置。 看它是否含有字符串。 开始检索的位置在字符串的 start 处或字符串的结尾(没有指定 start 时)。 如果没有找到匹配字符串则返回 -1 。
    • 注意:lastIndexOf() 方法是区分大小写的!
  15. forEach

    功能:ES5新增的方法,用来遍历数组,没有返回值,

    参数:forEach(callback);callback默认有三个参数,分别为value(遍历到的数组的数据),index(对应的索引),self(数组自身)。

    var arr = ["Tom","Jack","Lucy","Lily","May"];
    var a = arr.forEach(function(value,index,self){
         console.log(value + "--" + index + "--" + (arr === self));
    })
    // 打印结果为:
    // Tom--0--true
    // Jack--1--true
    // Lucy--2--true
    // Lily--3--true
    // May--4--true
    console.log(a);     //undefined---forEach没有返回值
    //该方法为遍历方法,不会修改原数组
    
  16. map();

    功能:

    同forEach功能;

    map的回调函数会将执行结果返回,最后map将所有回调函数的返回值组成新数组返回。

    • 参数:map(callback);callback默认有三个参数,分别为value,index,self。跟上面的forEach()的参数一样
    //功能1:同forEach
        var arr = ["Tom","Jack","Lucy","Lily","May"];
        var a = arr.map(function(value,index,self){
            console.log(value + "--" + index + "--" + (arr === self))
        })
        // 打印结果为:
        // Tom--0--true
        // Jack--1--true
        // Lucy--2--true
        // Lily--3--true
        // May--4--true
     
        //功能2:每次回调函数的返回值被map组成新数组返回
        var arr = ["Tom","Jack","Lucy","Lily","May"];
        var a = arr.map(function(value,index,self){
            return "hi:"+value;
        })
        console.log(a);     //["hi:Tom", "hi:Jack", "hi:Lucy", "hi:Lily", "hi:May"]
        console.log(arr);   //["Tom", "Jack", "Lucy", "Lily", "May"]---原数组未改变
    
  17. filter()

    功能: 1.同forEach功能; 2.filter的回调函数需要返回布尔值,当为true时,将本次数组的数据返回给filter,最后filter将所有回调函数的返回值组成新数组返回(此功能可理解为“过滤”)。

    参数:filter(callback);callback默认有三个参数,分别为value,index,self。

    //功能1:同forEach
        var arr = ["Tom","Jack","Lucy","Lily","May"];
        var a = arr.filter(function(value,index,self){
            console.log(value + "--" + index + "--" + (arr === self))
        })
        // 打印结果为:
        // Tom--0--true
        // Jack--1--true
        // Lucy--2--true
        // Lily--3--true
        // May--4--true
     
        //功能2:当回调函数的返回值为true时,本次的数组值返回给filter,被filter组成新数组返回
        var arr = ["Tom","Jack","Lucy","Lily","May"];
        var a = arr.filter(function(value,index,self){
            return value.length > 3;
        })
        console.log(a);         //["Jack", "Lucy", "Lily"]
        console.log(arr);       //["Tom", "Jack", "Lucy", "Lily", "May"]---原数组未改变
    
  18. every();

    功能:判断数组中每一项是否都满足条件,只有所有项都满足条件,才会返回true。

    参数:every()接收一个回调函数作为参数,这个回调函数需要有返回值,every(callback);callback默认有三个参数,分别为value,index,self。

    功能1:当回调函数的返回值为true时,类似于forEach的功能,遍历所有;如果为false,那么停止执行,后面的数据不再遍历,停在第一个返回false的位置。

    //demo1:
        var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
        var a = arr.every(function(value,index,self){
            console.log(value + "--" + index + "--" + (arr == self))
        })
        // 打印结果为:
        // Tom--0--true
        //因为回调函数中没有return true,默认返回undefined,等同于返回false
     
        //demo2:
        var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
        var a = arr.every(function(value,index,self){
            console.log(value + "--" + index + "--" + (arr == self))
            return value.length < 4;
        })
        // 打印结果为:
        // Tom--0--true
        // abc--1--true
        // Jack--2--true
        //因为当遍历到Jack时,回调函数到return返回false,此时Jack已经遍历,但是后面数据就不再被遍历了
     
        //demo3:
        var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
        var a = arr.every(function(value,index,self){
            console.log(value + "--" + index + "--" + (arr == self))
            return true;
        })
        // 打印结果为:
        // Tom--0--true
        // abc--1--true
        // Jack--2--true
        // Lucy--3--true
        // Lily--4--true
        // May--5--true
        //因为每个回调函数的返回值都是true,那么会遍历数组所有数据,等同于forEach功能
    

  1. some();

功能:判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。

参数:some()接收一个回调函数作为参数,这个回调函数需要有返回值,some(callback);callback默认有三个参数,分别为value,index,self。

功能1:因为要判断数组中的每一项,只要有一个回调函数返回true,some都会返回true,所以与every正好相反,当遇到一个回调函数的返回值为true时,可以确定结果,那么停止执行,后面都数据不再遍历,停在第一个返回true的位置;当回调函数的返回值为false时,需要继续向后执行,到最后才能确定结果,所以会遍历所有数据,实现类似于forEach的功能,遍历所有。

//demo1:
    var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
    var a = arr.some(function(value,index,self){
        console.log(value + "--" + index + "--" + (arr == self))
        return value.length > 3;
    })
    // 打印结果为:
    // Tom--0--true
    // abc--1--true
    // Jack--2--true
 
    //demo2:
    var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
    var a = arr.some(function(value,index,self){
        console.log(value + "--" + index + "--" + (arr == self))
        return true;
    })
    // 打印结果为:
    // Tom--0--true
 
    //demo3:
    var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
    var a = arr.some(function(value,index,self){
        console.log(value + "--" + index + "--" + (arr == self))
        return false;
    })
    // 打印结果为:
    // Tom--0--true
    // abc--1--true
    // Jack--2--true
    // Lucy--3--true
    // Lily--4--true
    // May--5--true

功能2:与every相反,只要有一个回调函数的返回值都为true,some的返回值为true,所有回调函数的返回值为false,some的返回值才为false

//demo1:
    var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
    var a = arr.some(function(value,index,self){
        return value.length > 3;
    })
    console.log(a);             //true
 
    //demo2:
    var arr = ["Tom","abc","Jack","Lucy","Lily","May"];
    var a = arr.some(function(value,index,self){
        return value.length > 4;
    })
    console.log(a);             //false

20.reduce();

功能:从数组的第一项开始,逐个遍历到最后,迭代数组的所有项,然后构建一个最终返回的值。

参数:reduce()接收一个或两个参数:第一个是回调函数,表示在数组的每一项上调用的函数;第二个参数(可选的)作为归并的初始值,被回调函数第一次执行时的第一个参数接收。 reduce(callback,initial);callback默认有四个参数,分别为prev,now,index,self。 callback返回的任何值都会作为下一次执行的第一个参数。 如果initial参数被省略,那么第一次迭代发生在数组的第二项上,因此callback的第一个参数是数组的第一项,第二个参数就是数组的第二项。

//demo1:不省略initial参数,回调函数没有返回值
    var arr = [10,20,30,40,50];
    arr.reduce(function(prev,now,index,self){
        console.log(prev + "--" + now + "--" + index + "--" + (arr == self))
    }, 2019)
    // 打印结果为:
    // 2019--10--0--true
    // undefined--20--1--true
    // undefined--30--2--true
    // undefined--40--3--true
    // undefined--50--4--true
    // 此时回调函数没有return,所以从第二次开始,prev拿到的是undefined
 
    //demo2:省略initial参数,回调函数没有返回值
    var arr = [10,20,30,40,50];
    arr.reduce(function(prev,now,index,self){
        console.log(prev + "--" + now + "--" + index + "--" + (arr == self))
    })
    // 打印结果为:第一次,回调函数的第一个参数是数组的第一项。第二个参数就是数组的第二项
    // 10--20--1--true
    // undefined--30--2--true
    // undefined--40--3--true
    // undefined--50--4--true
    // 此时回调函数没有return,所以从第二次开始,prev拿到的是undefined
 
    //demo3:不省略initial参数,回调函数有返回值
    var arr = [10,20,30,40,50];
    arr.reduce(function(prev,now,index,self){
        console.log(prev + "--" + now + "--" + index + "--" + (arr == self));
        return "hello";
    }, 2019)
    // 打印结果为:
    // 2019--10--0--true
    // hello--20--1--true
    // hello--30--2--true
    // hello--40--3--true
    // hello--50--4--true
    // 此时回调函数有return,所以从第二次开始,prev拿到的是回调函数return的值
 
    //demo4:省略initial参数,回调函数有返回值
    var arr = [10,20,30,40,50];
    arr.reduce(function(prev,now,index,self){
        console.log(prev + "--" + now + "--" + index + "--" + (arr == self));
        return "hello";
    })
    // 打印结果为:第一次,回调函数的第一个参数是数组的第一项。第二个参数就是数组的第二项
    // 10--20--1--true
    // hello--30--2--true
    // hello--40--3--true
    // hello--50--4--true
    // 此时回调函数有return,所以从第二次开始,prev拿到的是回调函数return的值
 
    //demo5:使用reduce计算数组中所有数据的和
    var arr = [10,20,30,40,50];
    var sum = arr.reduce(function(prev,now,index,self){
        return prev + now;
    })
    console.log(sum);      //150
    // 回调函数的最后一次return的结果被返回到reduce方法的身上
 
    //demo6:使用reduce计算数组中所有数据的和
    var arr = [10,20,30,40,50];
    var sum = arr.reduce(function(prev,now,index,self){
        return prev + now;
    }, 8)
    console.log(sum);      //158
    // 回调函数的最后一次return的结果被返回到reduce方法的身上
    // 因为reduce有第二个参数initial,在第一次执行时被计算,所以最终结果被加上8

every和some

every 是所有函数的每个回调都返回 true 的时候才会返回 true,当遇到 false 的时候终止执行,返回 false。

some 函数是存在有一个函数返回 true 的时候终止执行并返回 true,否则返回 false。

// every
var arr = [1,6,8,-2,-5,7,-4]
var isPositive = arr.every(function(value){
    return value > 0;
})
console.log(isPositive) // false
 
//some
var arr = [1,6,8,-2,-5,7,-4]
var isPositive = arr.some(function(value){
    return value > 0;
})
console.log(isPositive) // true

集合排序

var arr = [
    {name:'a',age:9},
    {name:'b',age:12},
    {name:'c',age:8}
];
   
 arr.sort((a,b)=>{
    return a.age -  b.age
  });

image-20220427212813749

js2个对象数组,根据某一个字段,删除重复项

/**
 * @description:2个对象数组去重复值,根据key
 * @param {*}
 * @return {*}
 */
const arr1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }];
const arr2 = [{ id: 1 }, { id: 2 }];
 
const uniq = (arr1, arr2,key) => {
 let ids = arr2.map((item) => item[key]);
 return arr1.filter(el=>{
     return !ids.includes(el[key]);
 })
};
 
console.log(uniq(arr1, arr2,'id'));
 
// reulut  =[ { id: 3 }, { id: 4 }, { id: 5 } ]

后端

递归

//递归方法
    public List<SubjectNestedVo> nestedList() {
        LambdaQueryWrapper<EduSubject> queryWrapper = new LambdaQueryWrapper<>();
        List<EduSubject> eduSubjects = baseMapper.selectList(null);
        List<SubjectNestedVo> collect = eduSubjects.stream().filter(eduSubject -> eduSubject.getParentId().equals("0"))
                .map(eduSubject -> {
                    SubjectNestedVo subjectNestedVo = new SubjectNestedVo();
                    BeanUtils.copyProperties(eduSubject, subjectNestedVo);
                    subjectNestedVo.setChildren(getChildren2(eduSubjects, subjectNestedVo));
                    return subjectNestedVo;
                })
                .collect(Collectors.toList());
        return collect;
    }
    private List<SubjectNestedVo> getChildren2(List<EduSubject> eduSubjects, SubjectNestedVo subjectNestedVo) {
        List<SubjectNestedVo> collect = eduSubjects.stream().filter(eduSubject -> eduSubject.getParentId().equals(subjectNestedVo.getId()))
                .map(eduSubject -> {
                    SubjectNestedVo subjectVo = new SubjectNestedVo();
                    BeanUtils.copyProperties(eduSubject, subjectVo);
                    subjectVo.setChildren(getChildren2(eduSubjects, subjectVo));
                    return subjectVo;
                }).collect(Collectors.toList());
        return collect;
    }
//递归删除
    public void deleteSubject(String id) {
        //创建list集合存放删除的id
        List<String> list = new ArrayList<>();
        list.add(id);
        this.selcetPerentChionId(id, list);
        baseMapper.deleteBatchIds(list);
    }

    private void selcetPerentChionId(String id, List<String> list) {
        //查询菜单的子菜单
        LambdaQueryWrapper<EduSubject> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EduSubject::getParentId, id);
        queryWrapper.select(EduSubject::getId);
        List<EduSubject> eduSubjects = baseMapper.selectList(queryWrapper);
        eduSubjects.stream().forEach(i -> {
            list.add(i.getId());
            selcetPerentChionId(i.getId(), list);
        });
    }

集合

image-20220518164553020

Collection方法接口介绍

Collection 接口有 3 种子类型集合: List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、ArrayBlockingQueue等,下面是Collection的所有方法。

方法名说明
boolean add(E e)向集合添加元素e,若指定集合元素改变了则返回true
boolean addAll(Collection<? extends E> c)把集合C中的元素全部添加到集合中,若指定集合元素改变返回true
void clear()清空所有集合元素
boolean contains(Object o)判断指定集合是否包含对象o
boolean containsAll(Collection<?> c)判断指定集合是否包含集合c的所有元素
boolean isEmpty()判断指定集合的元素size是否为0
boolean remove(Object o)删除集合中的元素对象o,若集合有多个o元素,则只会删除第一个元素
boolean removeAll(Collection<?> c)删除指定集合包含集合c的元素
boolean retainAll(Collection<?> c)从指定集合中保留包含集合c的元素,其他元素则删除
int size()集合的元素个数
T[] toArray(T[] a)将集合转换为T类型的数组

List(集合)常见方法操作

返回值方法说明
voidadd(int index, E element)将指定的元素插入此列表中的指定位置(可选操作)。
booleanaddAll(int index, Collection<? extends E> c)将指定集合中的所有元素插入到此列表中的指定位置(可选操作)。
booleanadd(E e)将指定的元素追加到此列表的末尾(可选操作)。
booleanaddAll(Collection<? extends E> c)按指定集合的迭代器(可选操作)返回的顺序将指定集合中的所有元素附加到此列表的末尾。
voidclear()从此列表中删除所有元素(可选操作)。
booleancontains(Object o)` |如果此列表包含指定的元素,则返回 true
booleancontainsAll(Collection<?> c)如果此列表包含指定集合的所有元素,则返回 true
booleanequals(Object o)将指定的对象与此列表进行比较以获得相等性。
Eget(int index)返回此列表中指定位置的元素。
inthashCode()返回此列表的哈希码值。
intindexOf(Object o)返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
booleanisEmpty()如果此列表不包含元素,则返回 true
Iteratoriterator()以正确的顺序返回该列表中的元素的迭代器。
intlastIndexOf(Object o)返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
ListIterator<E>listIterator()返回列表中的列表迭代器(按适当的顺序)。
ListIterator<E>listIterator(int index)从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
Eremove(int index)删除该列表中指定位置的元素(可选操作)。
booleanremove(Object o)从列表中删除指定元素的第一个出现(如果存在)(可选操作)。
default voidreplaceAll(UnaryOperator<E> operator)将该列表的每个元素替换为将该运算符应用于该元素的结果。
booleanretainAll(Collection<?> c)仅保留此列表中包含在指定集合中的元素(可选操作)。
Eset(int index, E element)用指定的元素(可选操作)替换此列表中指定位置的元素。
intsize()返回此列表中的元素数
default voidsort(Comparator<? super E> c)根据指定的Comparator引发的顺序排列此列表。
default Spliterator<E>spliterator()在此列表中的元素上创建一个Spliterator。
List<E>subList(int fromIndex, int toIndex)返回指定的 fromIndex (含)和 toIndex之间的列表部分的视图。
Object[]toArray()以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。

Set集合

无序不可重复

HashMap

isEmpty()测试映射是否为空
put(Object key, Object value)添加键值对
putAll(Collection c)添加指定的映射关系到目标映射关系
get(Object key)根据键来获取对应的值
getOrDefault(Object key, V defaultValue)map中存在key则使用对应的value,否则使用defaultValue
containsKey(Object key)是否有指定key的映射
containsValue(Object value)是否有指定value的映射
remove(Object key)删除该键值对
values()返回所有值,返回形式为Collection
size()返回大小

Date对象方法:

// 这个类的精华就在于入参,可以转换不同的格式
        // 注意这个类不是线程安全的,切记不可多个线程共享同一个实例
        // 真要在多线程环境下使用可以使用 ThreadLocal存对应线程的 Format
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //字符串转时间
        String myTimeStr  = "2019-11-01 08:19:03";
        try {
            Date myDate = format.parse(myTimeStr);
            System.out.println(myDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        //时间转字符串
        Date currentDate = new Date();
        String currentDateStr = format.format(currentDate);
        System.out.println(currentDateStr);



import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.junit.Test;

public class TimeUtil {
    // 用来全局控制 上一周,本周,下一周的周数变化
    private int weeks = 0;
    // 一月最大天数
    private int MaxDate;
    // 一年最大天数
    private int MaxYear;/**
     * 得到指定月后(前)的日期 参数传负数即可
     * 
     */
    public static String getAfterMonth(int month) {
        Calendar c = Calendar.getInstance();// 获得一个日历的实例
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse("2009-11-04");// 初始日期
        } catch (Exception e) {

        }
        c.setTime(date);// 设置日历时间
        c.add(Calendar.MONTH, month);// 在日历的月份上增加6个月
        String strDate = sdf.format(c.getTime());// 的到你想要得6个月后的日期
        return strDate;

    }

    /**
     * 得到二个日期间的间隔天数
     */
    public static String getTwoDay(String sj1, String sj2) {
        SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
        long day = 0;
        try {
            java.util.Date date = myFormatter.parse(sj1);
            java.util.Date mydate = myFormatter.parse(sj2);
            day = (date.getTime() - mydate.getTime()) / (24 * 60 * 60 * 1000);
        } catch (Exception e) {
            return "";
        }
        return day + "";
    }

    /**
     * 根据一个日期,返回是星期几的字符串
     */
    public static String getWeek(String sdate) {
        // 再转换为时间
        Date date = TimeUtil.strToDate(sdate);
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        // int hour=c.get(Calendar.DAY_OF_WEEK);
        // hour 中存的就是星期几了,其范围 1~7
        // 1=星期日 7=星期六,其他类推
        return new SimpleDateFormat("EEEE").format(c.getTime());
    }

    /**
     * 将短时间格式字符串转换为时间 yyyy-MM-dd
     */
    public static Date strToDate(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(strDate, pos);
        return strtodate;
    }

    /**
     * 两个时间之间的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long getDays(String date1, String date2) {
        if (date1 == null || date1.equals(""))
            return 0;
        if (date2 == null || date2.equals(""))
            return 0;
        // 转换为标准时间
        SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
        java.util.Date date = null;
        java.util.Date mydate = null;
        try {
            date = myFormatter.parse(date1);
            mydate = myFormatter.parse(date2);
        } catch (Exception e) {
        }
        long day = (date.getTime() - mydate.getTime()) / (24 * 60 * 60 * 1000);
        return day;
    }

    /**
     * 计算当月最后一天,返回字符串
     */
    public String getDefaultDay() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.set(Calendar.DATE, 1);// 设为当前月的1 号
        lastDate.add(Calendar.MONTH, 1);// 加一个月,变为下月的1 号
        lastDate.add(Calendar.DATE, -1);// 减去一天,变为当月最后一天
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 上月第一天
     */
    public String getPreviousMonthFirst() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.set(Calendar.DATE, 1);// 设为当前月的1 号
        lastDate.add(Calendar.MONTH, -1);// 减一个月,变为下月的1 号
        // lastDate.add(Calendar.DATE,-1);//减去一天,变为当月最后一天
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 获取当月第一天
     */
    public String getFirstDayOfMonth() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.set(Calendar.DATE, 1);// 设为当前月的1 号
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 获得本周星期日的日期
     */
    public String getCurrentWeekday() {
        weeks = 0;
        int mondayPlus = this.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus + 6);
        Date monday = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preMonday = df.format(monday);
        return preMonday;
    }

    /**
     * 获取当天时间
     */
    public String getNowTime(String dateformat) {
        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat(dateformat);// 可以方便地修改日期格式
        String hehe = dateFormat.format(now);
        return hehe;
    }

    /**
     * 获得当前日期与本周日相差的天数
     */
    private int getMondayPlus() {
        Calendar cd = Calendar.getInstance();
        // 获得今天是一周的第几天,星期日是第一天,星期二是第二天......
        int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK) - 1; // 因为按中国礼拜一作为第一天所以这里减1
        if (dayOfWeek == 1) {
            return 0;
        } else {
            return 1 - dayOfWeek;
        }
    }

    /**
     * 获得本周一的日期
     */
    public String getMondayOFWeek() {
        weeks = 0;
        int mondayPlus = this.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus);
        Date monday = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preMonday = df.format(monday);
        return preMonday;
    }

    /**
     * 获得相应周的周六的日期
     */
    public String getSaturday() {
        int mondayPlus = this.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus + 7 * weeks + 6);
        Date monday = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preMonday = df.format(monday);
        return preMonday;
    }

    /**
     * 获得上周星期日的日期
     */
    public String getPreviousWeekSunday() {
        weeks = 0;
        weeks--;
        int mondayPlus = this.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus + weeks);
        Date monday = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preMonday = df.format(monday);
        return preMonday;
    }

    /**
     * 获得上周星期一的日期
     */
    public String getPreviousWeekday() {
        weeks--;
        int mondayPlus = this.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus + 7 * weeks);
        Date monday = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preMonday = df.format(monday);
        return preMonday;
    }

    /**
     * 获得下周星期一的日期
     */
    public String getNextMonday() {
        weeks++;
        int mondayPlus = this.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus + 7);
        Date monday = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preMonday = df.format(monday);
        return preMonday;
    }

    /**
     * 获得下周星期日的日期
     */
    public String getNextSunday() {
        int mondayPlus = this.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus + 7 + 6);
        Date monday = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preMonday = df.format(monday);
        return preMonday;
    }

    private int getMonthPlus() {
        Calendar cd = Calendar.getInstance();
        int monthOfNumber = cd.get(Calendar.DAY_OF_MONTH);
        cd.set(Calendar.DATE, 1);// 把日期设置为当月第一天
        cd.roll(Calendar.DATE, -1);// 日期回滚一天,也就是最后一天
        MaxDate = cd.get(Calendar.DATE);
        if (monthOfNumber == 1) {
            return -MaxDate;
        } else {
            return 1 - monthOfNumber;
        }
    }

    /**
     * 获得上月最后一天的日期
     */
    public String getPreviousMonthEnd() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.add(Calendar.MONTH, -1);// 减一个月
        lastDate.set(Calendar.DATE, 1);// 把日期设置为当月第一天
        lastDate.roll(Calendar.DATE, -1);// 日期回滚一天,也就是本月最后一天
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 获得下个月第一天的日期
     */
    public String getNextMonthFirst() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.add(Calendar.MONTH, 1);// 减一个月
        lastDate.set(Calendar.DATE, 1);// 把日期设置为当月第一天
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 获得下个月最后一天的日期
     */
    public String getNextMonthEnd() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.add(Calendar.MONTH, 1);// 加一个月
        lastDate.set(Calendar.DATE, 1);// 把日期设置为当月第一天
        lastDate.roll(Calendar.DATE, -1);// 日期回滚一天,也就是本月最后一天
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 获得明年最后一天的日期
     */
    public String getNextYearEnd() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.add(Calendar.YEAR, 1);// 加一个年
        lastDate.set(Calendar.DAY_OF_YEAR, 1);
        lastDate.roll(Calendar.DAY_OF_YEAR, -1);
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 获得明年第一天的日期
     */
    public String getNextYearFirst() {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar lastDate = Calendar.getInstance();
        lastDate.add(Calendar.YEAR, 1);// 加一个年
        lastDate.set(Calendar.DAY_OF_YEAR, 1);
        str = sdf.format(lastDate.getTime());
        return str;
    }

    /**
     * 获得本年有多少天
     * 
     * @return
     */
    private int getMaxYear() {
        Calendar cd = Calendar.getInstance();
        cd.set(Calendar.DAY_OF_YEAR, 1);// 把日期设为当年第一天
        cd.roll(Calendar.DAY_OF_YEAR, -1);// 把日期回滚一天。
        int MaxYear = cd.get(Calendar.DAY_OF_YEAR);
        return MaxYear;
    }

    private int getYearPlus() {
        Calendar cd = Calendar.getInstance();
        int yearOfNumber = cd.get(Calendar.DAY_OF_YEAR);// 获得当天是一年中的第几天
        cd.set(Calendar.DAY_OF_YEAR, 1);// 把日期设为当年第一天
        cd.roll(Calendar.DAY_OF_YEAR, -1);// 把日期回滚一天。
        int MaxYear = cd.get(Calendar.DAY_OF_YEAR);
        if (yearOfNumber == 1) {
            return -MaxYear;
        } else {
            return 1 - yearOfNumber;
        }
    }

    /**
     * 获得本年第一天的日期
     * 
     * @return
     */
    public String getCurrentYearFirst() {
        int yearPlus = this.getYearPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, yearPlus);
        Date yearDay = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preYearDay = df.format(yearDay);
        return preYearDay;
    }

    /**
     * 获得本年最后一天的日期
     * 
     * @return
     */
    public String getCurrentYearEnd() {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");// 可以方便地修改日期格式
        String years = dateFormat.format(date);
        return years + "-12-31";
    }

    /**
     * 获得上年第一天的日期
     * 
     * @return
     */
    public String getPreviousYearFirst() {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");// 可以方便地修改日期格式
        String years = dateFormat.format(date);
        int years_value = Integer.parseInt(years);
        years_value--;
        return years_value + "-1-1";
    }

    /**
     * 获得上年最后一天的日期
     * 
     * @return
     */
    public String getPreviousYearEnd() {
        weeks--;
        int yearPlus = this.getYearPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, yearPlus + MaxYear * weeks + (MaxYear - 1));
        Date yearDay = currentDate.getTime();
        DateFormat df = DateFormat.getDateInstance();
        String preYearDay = df.format(yearDay);
        getThisSeasonTime(11);
        return preYearDay;
    }

    /**
     * 获得本季度
     * 
     * @param month
     * @return
     */
    public String getThisSeasonTime(int month) {
        int array[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 } };
        int season = 1;
        if (month >= 1 && month <= 3) {
            season = 1;
        }
        if (month >= 4 && month <= 6) {
            season = 2;
        }
        if (month >= 7 && month <= 9) {
            season = 3;
        }
        if (month >= 10 && month <= 12) {
            season = 4;
        }
        int start_month = array[season - 1][0];
        int end_month = array[season - 1][2];
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");// 可以方便地修改日期格式
        String years = dateFormat.format(date);
        int years_value = Integer.parseInt(years);
        int start_days = 1;// years+"-"+String.valueOf(start_month)+"-1";//getLastDayOfMonth(years_value,start_month);
        int end_days = getLastDayOfMonth(years_value, end_month);
        String seasonDate = years_value + "-" + start_month + "-" + start_days + ";" + years_value + "-" + end_month + "-" + end_days;
        return seasonDate;
    }

    /**
     * 获取某年某月的最后一天
     * 
     * @param year
     *            年
     * @param month
     *            月
     * @return 最后一天
     */
    private int getLastDayOfMonth(int year, int month) {
        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
            return 31;
        }
        if (month == 4 || month == 6 || month == 9 || month == 11) {
            return 30;
        }
        if (month == 2) {
            if (isLeapYear(year)) {
                return 29;
            } else {
                return 28;
            }
        }
        return 0;
    }

    /**
     * 是否闰年
     * 
     * @param year
     *            年
     * @return
     */
    public boolean isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }
}


get系列:

getDate()返回一个月中的某一天(1-31)
getDay()返回一周中的某一天(0-6)
getFullYear()返回四位数的年份
getMonth()返回月份(0-11 0是一月)
getHours()返回的是当前的小时(0-23)
getMinutes()返回的是当前的分钟(0-59)
getSeconds()返回的是当前的秒(0-59)
getTime()返回的是1970年1月1日至今的毫秒数
Date1.after(Date2)当Date1大于Date2时,返回TRUE,当小于等于时,返回false.即Date2比Date1小的true/false,当Date2日期比Date1小的时候为true,否则为false
Date1.before(Date2)当Date1小于Date2时,返回TRUE,当大于等于时,返回false;

Set系列:

parse()返回1970年1月1日到指定日期的毫秒数
setDate()设置一月的某一天(1-31)
setFullYear()设置年份
setMonth()设置月份(0-11)
setHours()设置小时(0-23)
setMinutes()设置分钟(0-59)
setSeconds()设置秒数(0-59)
setTime以毫秒数设置Date

JAVA8日期处理工具方法汇总

类名描述
LocalDate只包含日期,如:2000-01-01
LocalTime只包含时间,如:14:02:10
LocalDateTime包含日期和时间,如:2000-01-01 14:02:10
Instant时间戳
Period时间段
Duration时间差
ZoneOffset时区偏移量,如:+8:00
ZonedDateTime带时区的时间
Clock时钟

获取当前日期时间

  • 获取当天日期
public static LocalDate today() {
    return LocalDate.now();
}
  • 获取当前时间
public static LocalTime nowTime() {
    return LocalTime.now();
}
  • 获取当前日期 + 时间
public static LocalDateTime now() {
    return LocalDateTime.now();
}

获取指定日期时间

  • 获取指定日期
public static LocalDate ofDate(int year, int month, int day) {
    return LocalDate.of(year, month, day);
}
  • 获取指定时间
public static LocalTime ofTime(int hour, int minute, int second) {
    return LocalTime.of(hour, minute, second);
}
  • 获取指定日期 + 时间
public static LocalDateTime ofDateTime(int year, int month, int day, int hour, int minute, int second) {
    return LocalDateTime.of(year, month, day, hour, minute, second);
}

public static LocalDateTime ofDateTime(LocalDate date, LocalTime time) {
    return LocalDateTime.of(date, time);
}

日期比较

  • 是否相等

可以使用 equals 方法,也可以使用 isEqual 方法,isEqual 方法如果比较的日期为空,则会抛出异常

public static boolean equals(LocalDate date1, LocalDate date2) {
    return date1 != null && date1.equals(date2);
}

public static boolean equals(LocalDate date1, LocalDate date2) {
    return date1 != null && date2 != null && date1.isEqual(date2);
}
  • 比较大小
public static void main(String[] args) {
    LocalDateTime d1 = LocalDate.of(2021, 8, 10).atStartOfDay();
    LocalDateTime d2 = LocalDateTime.of(2021, 8, 10, 12, 0);
    System.out.println(d1.isAfter(d2));
    System.out.println(d1.isBefore(d2));
}

日期格式化

通过 DateTimeFormatter 设置格式

  • 日期转换为字符串
public static String format(LocalDate date, String pattern) {
    return date == null ? "" : date.format(DateTimeFormatter.ofPattern(pattern));
}

public static String format(LocalTime date, String pattern) {
    return date == null ? "" : date.format(DateTimeFormatter.ofPattern(pattern));
}

public static String format(LocalDateTime date, String pattern) {
    return date == null ? "" : date.format(DateTimeFormatter.ofPattern(pattern));
}
  • 字符串转换为日期
public static LocalDate parseDate(String date, String pattern) {
    return LocalDate.parse(date, DateTimeFormatter.ofPattern(pattern));
}

public static LocalTime parseTime(String date, String pattern) {
    return LocalTime.parse(date, DateTimeFormatter.ofPattern(pattern));
}

public static LocalDateTime parseDateTime(String date, String pattern) {
    return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(pattern));
}

获取当前时间戳

通过 Instant 类来处理时间戳,这个方法相当于 System.currentTimeMillis()

public static long currentTimeMillis() {
    return Instant.now().toEpochMilli();
}

日期通过转换为 Instant,就可以获取其时间戳,这里的转换默认使用了 东8区 时区

public static Instant toInstant(LocalDate date) {
    return date == null ? null : toInstant(date.atStartOfDay());
}

public static Instant toInstant(LocalDateTime date) {
    return toInstant(date, ZoneOffset.ofHours(8));
}

public static Instant toInstant(LocalDateTime date, ZoneOffset zoneOffset) {
    return date == null ? null : date.toInstant(zoneOffset);
}

public static Instant toInstant(Date date) {
    return date == null ? null : date.toInstant();
}

通过时间戳生成当前时间

public static LocalDateTime toLocalDateTime(Long timestamp) {
    if (timestamp == null) {
        return null;
    }
    return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
}

获取当天开始时间

public static LocalDateTime atStartOfDay(LocalDateTime date) {
    return date == null ? null : date.toLocalDate().atStartOfDay();
}

获取当天结束时间

public static LocalDateTime atLastOfDay(LocalDateTime date) {
    return date == null ? null : date.toLocalDate().atStartOfDay().plusDays(1).minusSeconds(1);
}

日期操作函数

Java8 提供了非常方便的日期操作方法,plus 开头的方法是日期加方法,minus 开头的方法是日期减方法。

单位日期加日期减
plusYearsminusYears
plusMonthsminusMonths
星期plusWeeksminusWeeks
plusDaysminusDays
小时plusHoursminusHours
分钟plusMinutesminusMinutes
plusSecondsminusSeconds
纳秒plusNanosminusNanos

示例:当前时间向后增加一年,再减去一天

public static void main(String[] args) {
    LocalDateTime now = LocalDateTime.now();
    now.plusYears(1).minusDays(1);
}

计算两个日期之间相差的天数

Duration 不支持 LocalDate,可以把 LocalDate 转换为 LocalDateTime 使用,计算的是两个时间点之间相差的秒数,然后根据不同的方法转换为不同的单位,Duration 提供了 toDays, toHourstoMinutes 等方法。

public static long diffDays(LocalDate d1, LocalDate d2) {
    return Math.abs(d1.toEpochDay() - d2.toEpochDay());
}

public static long diffDays(LocalDateTime d1, LocalDateTime d2) {
    Duration between = Duration.between(d1, d2);
    return Math.abs(between.toDays());
}

通过 Period 也可以计算相差的天数,但 Period 会把相差的日期使用 年-月-日 三个单位进行存储。

public static void main(String[] args) {
    Period between = Period.between(today(), today().plusYears(1).plusDays(10));
    System.out.println(between.getYears());
    System.out.println(between.getMonths());
    System.out.println(between.getDays());
}

输出结果为

1
0
10

判断是否生日这种周期性日期

public static boolean isBirthday(LocalDate date, Integer month, Integer day) {
    return date != null && month != null && day != null && MonthDay.of(month, day).equals(MonthDay.from(date));
}

获取一个月有多少天

public static Integer getMonthDay(TemporalAccessor date) {
    return date == null ? null : YearMonth.from(date).lengthOfMonth();
}

获取时钟

Clock 时钟类用于获取当前时间戳

public static void main(String[] args) {
    Clock defaultClock = Clock.systemDefaultZone();
    System.out.println(defaultClock.getZone().getId());
    Clock utcClock = Clock.systemUTC();
    System.out.println(utcClock.getZone().getId());
    Clock djClock = Clock.system(ZoneOffset.ofHours(9));
    System.out.println(djClock.getZone().getId());

    System.out.println("Clock : " + defaultClock.millis());
}

String 常用方法

length(); 返回字符串长度 intString str = “abcde”; int len = str.length();
substring(1); //返回一个新字符串,内容为指定位置开始到字符串末尾的所有字符String str = “abcde”; String s1 = str.substring(1)
substring(2, 4) //返回一个新字符串,内容为指定位置开始到指定位置结束所有字符String s2 = str.substring(2, 4)
startsWith() //判断字符串是否以指定字符串开头String str = “StringDemo.java”; boolean b1 = str.startsWith(“Demo”);
endsWith //测试此字符串是否以指定的后缀结尾str.endsWith(“java”);
contains(“bcd”);//判断是否包含指定字符串,包含返回true,不包含返回falseboolean b2 = str.contains(“bcd”)
indexOf(“bcd”); //判断是否包含指定字符串,包含则返回第一次出现该字符串的索引,不包含则返回-1int index = str.indexOf(“bcd”)
将字符串转成一个字符数组。String str = “abcde”; char[] chs = str.toCharArray();
将字符串转成一个字节数组String str = “abcde”; byte[] bytes = str.getBytes();
equals()判断两个字符串中的内容是否相同
equalsIgnoreCase()判断两个字符串中的内容是否相同,不比较大小写
toString获取该字符串对象中的内容
trim()截去字符串两端的空格,但对于中间的空格不
split(String str) 将str作为分隔符进行字符串分解,分解后的字字符串在字符串数组中返回1 String str = “asd!qwe|zxc#”; 2 String[] str1 = str.split(“!”)
toUpperCase()将字符串里面的小写字母变成大写字母
toLowerCase()将字符串里面的大写字母变成小写字母
split(String str)根据给定的正则表达式的匹配来拆分此字符串。形成一个新的String数组。
replace(char oldChar,char newChar)新字符替换旧字符
String replaceAll(String str1,Stringstr2)将某个内容全部替换成指定内容

数组常用方法

toString方法public static String toString(Array[] array)参数为数组将数组按照默认格式输出为字符串
sort方法public static String sort(Array[] array, int fromIndex, int toIndex)参数1数组,(参数2,3可以没有) 参数2,3为数组索引位置,用来对指定范围的数据进行排序将数组进行升序排序
binarySearchpublic static int binarySearch(Array[] array, int fromIndex, int toIndex, data key)参数1数组,(参数2,3可以没有) 参数2,3为数组索引位置,用来对指定范围的数据进行排序, 参数4为要查找的值使用二分法查找元素在数组中的索引位置

常用java工具类解析

Class – 01 – System类常用方法解析

一、System 类定义
  • System 类为 Java 的系统类,位于 java.lang 包中

  • System 类的构造方法由 private 进行修饰,因此无法被实例化

  • System 类提供了标准输入流、标准输出流和错误输出流;此外还提供了访问操作系统环境变量、访问虚拟机环境变量、复制数组、垃圾回收等一系列实用方法

二、System 类常用方法
  • System.currentTimeMillis()

    • 获取当前时间戳,单位为毫秒
  • System.nanoTime()

    • 获取当前时间戳,单位为纳秒
  • System.lineSeparator()

    • 行分隔符,等同于 System.getProperty(“line.separator”)
  • System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

    • 拷贝数组,共五个参数
    参数含义
    src源数组
    srcPos源数组开始截取的位置,从 0 开始
    dest目标数组
    destPos目标数组开始拷贝的位置,从 0 开始
    length截取长度

Java 中 Arrays 类的常用方法

一、Arrays 类的定义
  • Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法
二、Arrays 类的常用方法
  • Arrays.asList(T… data)

    注意:该方法返回的是 Arrays 内部静态类 ArrayList,而不是我们平常使用的 ArrayList,,该静态类 ArrayList 没有覆盖父类的 add(), remove() 等方法,所以如果直接调用,会报 UnsupportedOperationException 异常

    • 将数组转换为集合,接收一个可变参

      List<Integer> list = Arrays.asList(1, 2, 3);
      list.forEach(System.out::println); // 1 2 3
      
      Integer[] data = {1, 2, 3};
      List<Integer> list = Arrays.asList(data);
      list.forEach(System.out::println); // 1 2 3
      
    • 如果将基本数据类型的数组作为参数传入,该方法会把整个数组当作一个元素

      int[] data = {1, 2, 3};
      List<int[]> list = Arrays.asList(data);
      System.out.println(list.size()); // 1
      System.out.println(Arrays.toString(list.get(0))); // [1, 2, 3]
      
  • Arrays.fill(Object[] array, Object obj)

    • 用指定元素填充整个数组 (会替换掉数组中原来的元素)
    Integer[] data = {1, 2, 3, 4};
    Arrays.fill(data, 9);
    System.out.println(Arrays.toString(data)); // [9, 9, 9, 9]
    
  • Arrays.fill(Object[] array, int fromIndex, int toIndex, Object obj)

    • 用指定元素填充数组,从起始位置到结束位置,取头不取尾 (会替换掉数组中原来的元素)

      Integer[] data = {1, 2, 3, 4};
      Arrays.fill(data, 0, 2, 9);
      System.out.println(Arrays.toString(data)); // [9, 9, 3, 4]
      
  • Arrays.sort(Object[] array)

    • 对数组元素进行排序 (串行排序)

      String[] data = {"1", "4", "3", "2"};
      System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
      Arrays.sort(data);
      System.out.println(Arrays.toString(data)); // [1, 2, 3, 4]
      
  • Arrays.sort(T[] array, Comparator<? super T> comparator)

    使用**自定义比较器**,对数组元素进行排序 (串行排序)

    String[] data = {"1", "4", "3", "2"};
    System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
    // 实现降序排序,返回-1放左边,1放右边,0保持不变
    Arrays.sort(data, (str1, str2) -> {
        if (str1.compareTo(str2) > 0) {
    		return -1;
        } else {
            return 1;
        }
    });
    System.out.println(Arrays.toString(data)); // [4, 3, 2, 1]
    
  • Arrays.sort(Object[] array, int fromIndex, int toIndex)

    • 对指定范围内的数组元素进行排序 (串行排序)

      String[] data = {"1", "4", "3", "2"};
      System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
      // 对下标[0, 3)的元素进行排序,即对1,4,3进行排序,2保持不变
      Arrays.sort(data, 0, 3);
      System.out.println(Arrays.toString(data)); // [1, 3, 4, 2]
      
  • Arrays.sort(T[] array, int fromIndex, int toIndex, Comparator<? super T> c)

    • 使用**自定义比较器**,对指定范围内的数组元素进行排序 (串行排序)

      String[] data = {"1", "4", "3", "2"};
      System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
      // 对下标[0, 3)的元素进行降序排序,即对1,4,3进行降序排序,2保持不变
      Arrays.sort(data, 0, 3, (str1, str2) -> {
      	if (str1.compareTo(str2) > 0) {
      		return -1;
      	} else {
      		return 1;
      	}
      });
      System.out.println(Arrays.toString(data)); // [4, 3, 1, 2]
      
  • Arrays.parallelSort(T[] array)

    注意:其余重载方法与 Arrays.sort() 相同

    • 对数组元素进行排序 (并行排序),当数据规模较大时,会有更好的性能

      String[] data = {"1", "4", "3", "2"};
      Arrays.parallelSort(data);
      System.out.println(Arrays.toString(data)); // [1, 2, 3, 4]
      
  • Arrays.binarySearch(Object[] array, Object key)

    注意:在调用该方法之前,必须先调用 Arrays.sort() 方法进行排序,如果数组没有排序,那么结果是不确定的,此外如果数组中包含多个指定元素,则无法保证将找到哪个元素

    • 使用**二分法**查找数组内指定元素的索引值
    • 这里需要先看下 binarySearch() 方法的源码,对了解该方法有很大的帮助

image-20220527112313831

image-20220527112642529

  • 从源码中可以看到

    • 当搜索元素是数组元素时,返回该元素的索引值
    • 当搜索元素不是数组元素时,返回 - (索引值 + 1)
  • 具体的用法可以看下面的例子

    • 搜索元素是数组元素,返回该元素索引值

      Integer[] data = {1, 3, 5, 7};
      Arrays.sort(data);
      System.out.println(Arrays.binarySearch(data, 1)); // 0
      
    • 搜索元素不是数组元素,且小于数组中的最小值

      Integer[] data = {1, 3, 5, 7};
      Arrays.sort(data);
      // 此时程序会把数组看作 {0, 1, 3, 5, 7},此时0的索引值为0,则搜索0时返回 -(0 + 1) = -1
      System.out.println(Arrays.binarySearch(data, 0)); // -1
      
    • 搜索元素不是数组元素,且大于数组中的最大值

    Integer[] data = {1, 3, 5, 7};
    Arrays.sort(data);
    // 此时程序会把数组看作 {1, 3, 5, 7, 9},此时9的索引值为4,则搜索8时返回 -(4 + 1) = -5
    System.out.println(Arrays.binarySearch(data, 9)); // -5
    
    • 搜索元素不是数组元素,但在数组范围内

      Integer[] data = {1, 3, 5, 7};
      Arrays.sort(data);
      // 此时程序会把数组看作 {1, 2, 3, 5, 7},此时2的索引值为1,则搜索2时返回 -(1 + 1) = -2
      System.out.println(Arrays.binarySearch(data, 2)); // -2
      
  • Arrays.binarySearch(Object[] array, int fromIndex, int toIndex, Object obj)

    使用**二分法**查找数组内指定范围内的指定元素的索引值

    Integer[] data = {1, 3, 5, 7};
    Arrays.sort(data);
    // {1, 3},3的索引值为1
    System.out.println(Arrays.binarySearch(data, 0, 2, 3)); // 1
    
  • Arrays.copyOf(T[] original, int newLength)

    • 拷贝数组,其内部调用了 System.arraycopy() 方法,从下标 0 开始,如果超过原数组长度,则会用 null 进行填充

      Integer[] data1 = {1, 2, 3, 4};
      Integer[] data2 = Arrays.copyOf(data1, 2);
      System.out.println(Arrays.toString(data2)); // [1, 2]
      Integer[] data3 = Arrays.copyOf(data1, 5);
      System.out.println(Arrays.toString(data3)); // [1, 2, 3, 4, null]
      
  • Arrays.binarySearch(Object[] array, int fromIndex, int toIndex, Object obj)

    • 使用**二分法**查找数组内指定范围内的指定元素的索引值

      Integer[] data = {1, 3, 5, 7};
      Arrays.sort(data);
      // {1, 3},3的索引值为1
      System.out.println(Arrays.binarySearch(data, 0, 2, 3)); // 1
      
  • Arrays.copyOfRange(T[] original, int from, int to)

    • 拷贝数组,指定起始位置和结束位置,如果超过原数组长度,则会用 null 进行填充

      Integer[] data1 = {1, 2, 3, 4};
      Integer[] data2 = Arrays.copyOfRange(data1, 0, 2);
      System.out.println(Arrays.toString(data2)); // [1, 2]
      Integer[] data2 = Arrays.copyOfRange(data1, 0, 5);
      System.out.println(Arrays.toString(data2)); // [1, 2, 3, 4, null]
      
  • Arrays.equals(Object[] array1, Object[] array2)

    • 判断两个数组是否相等

      • 数组元素为基本数据类型时,依次比较值
      • 数组元素为引用数据类型时,依次调用元素的 equals() 方法进行比较
    • 即如果两个数组被认为是相等的,则两个数组中应包含相同顺序的相同元素

      Integer[] data1 = {1, 2, 3};
      Integer[] data2 = {1, 2, 3};
      System.out.println(Arrays.equals(data1, data2)); // true
      
  • Arrays.deepEquals(Object[] array1, Object[] array2)

    • 判断两个多维数组是否相等
      • 数组元素为基本数据类型时,依次比较值
      • 数组元素为引用数据类型时,依次调用元素的 equals() 方法进行比较
    • 即如果两个多维数组被认为是相等的,则两个多维数组中应包含相同顺序的相同元素
    Integer[][] data1 = {{1,2,3}, {1,2,3}};
    Integer[][] data2 = {{1,2,3}, {1,2,3}};
    System.out.println(Arrays.deepEquals(data1, data2)); // true
    
  • Arrays.hashCode(Object[] array)

    • 返回数组的哈希值

      Integer[] data = {1, 2, 3};
      System.out.println(Arrays.hashCode(data)); // 30817
      
  • Arrays.deepHashCode(Object[] array)

    • 返回多维数组的哈希值
    Integer[][] data = {{1, 2, 3}, {1, 2, 3}};
    System.out.println(Arrays.deepHashCode(data)); // 987105
    
  • Arrays.toString(Object[] array)

    • 返回数组元素的字符串形式

      Integer[] data = {1, 2, 3};
      System.out.println(Arrays.toString(data)); // [1, 2, 3]
      
  • Arrays.deepToString(Object[] array)

    • 返回多维数组元素的字符串形式

      Integer[][] data = {{1, 2, 3}, {1, 2, 3}};
      System.out.println(Arrays.deepToString(data)); // [[1, 2, 3], [1, 2, 3]]
      
  • Arrays.setAll(T[] array, IntFunction<? extends T> generator)

    • 让数组中的所有元素,**串行**地使用方法提供的生成器函数来计算每个元素 (一元操作)

      Integer[] data = {1, 2, 3, 4};
      // i为索引值
      Arrays.setAll(data, i -> data[i] * 2);
      System.out.println(Arrays.toString(data)); // [2, 4, 6, 8]
      
  • Arrays.parallelSetAll(T[] array, IntFunction<? extends T> generator)

    • 让数组中的所有元素,**并行**地使用方法提供的生成器函数来计算每个元素 (一元操作),当数据规模较大时,会有更好的性能

      Integer[] data = {1, 2, 3, 4};
      // i为索引值
      Arrays.parallelSetAll(data, i -> data[i] * 2);
      System.out.println(Arrays.toString(data)); // [2, 4, 6, 8]
      
  • Arrays.parallelPrefix(T[] array, BinaryOperator op)

    • 让数组中的所有元素,**并行**地使用方法提供的生成器函数来计算每个元素 (二元操作),当数据规模较大时,会有更好的性能

      Integer[] data = {2, 3, 4, 5};
      // 第一个元素2不变,将其与第二个元素3一起作为参数x, y传入,得到乘积6,作为数组新的第二个元素
      // 再将6和第三个元素4一起作为参数x, y传入,得到乘积24,作为数组新的第三个元素,以此类推
      Arrays.parallelPrefix(data, (x, y) -> x * y);
      System.out.println(Arrays.toString(data)); // [2, 6, 24, 120]
      
  • Arrays.parallelPrefix(T[] array, int fromIndex, int toIndex, BinaryOperator op

    • 让指定范围内的数组元素,**并行**地使用方法提供的生成器函数来计算每个元素 (二元操作),当数据规模较大时,会有更好的性能

      Integer[] data = {2, 3, 4, 5};
      // 第一个元素2不变,将其与第二个元素3一起作为参数x, y传入,得到乘积6,作为数组新的第二个元素
      // 再将6和第三个元素4一起作为参数x, y传入,得到乘积24,作为数组新的第三个元素,以此类推
      Arrays.parallelPrefix(data, 0, 3, (x, y) -> x * y);
      System.out.println(Arrays.toString(data)); // [2, 6, 24, 5]
      
  • Arrays.spliterator(T[] array)

    • 返回数组的**分片迭代器,用于并行**地遍历数组

      public class Students {
      
          private String name;
      
          private Integer age;
      
          public Students(String name, Integer age) {
              this.name = name;
              this.age = age;
          }
      	// 省略get、set方法
      }
      
      public static void main(String[] args) {
          Students[] data = new Students[5];
          IntStream.range(0,5).forEach(i -> data[i] = new Students("小明"+i+"号", i));
          // 返回分片迭代器
          Spliterator<Students> spliterator = Arrays.spliterator(data);
          spliterator.forEachRemaining(stu -> {
              System.out.println("学生姓名: " + stu.getName() + "  " + "学生年龄: " + stu.getAge());
              // 学生姓名: 小明0号  学生年龄: 0
      		// 学生姓名: 小明1号  学生年龄: 1
      		// 学生姓名: 小明2号  学生年龄: 2
      		// 学生姓名: 小明3号  学生年龄: 3
      		// 学生姓名: 小明4号  学生年龄: 4
          });
      }
      
  • Arrays.stream(T[] array)

    • 返回数组的流 (Stream),然后我们就可以使用 Stream 相关的许多方法了

      Integer[] data = {1, 2, 3, 4};
      List<Integer> list = Arrays.stream(data).collect(toList());
      System.out.println(list); // [1, 2, 3, 4]
      

Random类常用方法详解析

一、Random 类的定义
  • Random 类位于 java.util 包中,主要用于生成伪随机数

  • Random 类将 种子数 作为随机算法的起源数字,计算生成伪随机数,其与生成的随机数字的区间无关

  • 创建 Random 实例时,若没有指定种子数,则会以当前时间作为种子数,来计算生成伪随机数

  • 拥有相同种子的 Random 实例,在相同次数下,生成的伪随机数完全相同

    Random random1 = new Random(10);
    Random random2 = new Random(10);
    System.out.println(random1.nextInt()); // -1157793070
    System.out.println(random2.nextInt()); // -1157793070
    
二、Random 类的常用方法

random.nextBoolean()

  • 用于从该随机数生成器的序列中得到下一个伪均匀分布的 boolean 值

    Random random = new Random();
    System.out.println(random.nextBoolean()); // true
    
  • random.nextBytes()

    • 用于生成随机 byte 值并将其放入用户提供的 byte 数组中

    • 生成的随机 byte 数等于 byte 数组的长度

      Random random = new Random();
      byte[] data = new byte[5];
      random.nextBytes(data);
      System.out.println(Arrays.toString(data)); // [29, 73, -58, -60, -101]
      
  • random.nextDouble()

    • 用于从该随机数生成器的序列中得到下一个伪均匀分布在 0.0 到 1.0 之间的 double 值,[0.0, 1.0)

      Random random = new Random();
      System.out.println(random.nextDouble()); // 0.07169148591770946
      
  • random.nextFloat()

    • 用于从该随机数生成器的序列中得到下一个伪均匀分布在 0.0 到 1.0 之间的 float 值,[0.0, 1.0)

      Random random = new Random();
      System.out.println(random.nextFloat()); // 0.35473615
      
  • random.nextFloat()

    用于从该随机数生成器的序列中得到下一个伪均匀分布在 0.0 到 1.0 之间的 float 值,[0.0, 1.0)

    Random random = new Random();
    System.out.println(random.nextFloat()); // 0.35473615
    
  • random.nextInt()

    • 用于从该随机数生成器的序列中得到下一个伪均匀分布的 int 值

      Random random = new Random();
      System.out.println(random.nextInt()); // 1414623307
      
  • random.nextInt(int bound)

    用于从该随机数生成器的序列中得到下一个 0 到结束值之间伪均匀分布的 int 值,[0, 结束值)

Random random = new Random();
System.out.println(random.nextInt(10)); // 5
  • random.nextGaussian()

    • 用于从该随机数生成器的序列中得到下一个伪均匀分布的 double 值

    • 生成的 double 值符合**均值为 0,方差为 1 的正态分布 (高斯分布)**

      Random random = new Random();
      System.out.println(random.nextGaussian()); // 0.48039371890232446
      
  • random.setSeed(long seed)

    • 设置随机种子

      Random random = new Random();
      random.setSeed(10);
      
  • random.ints()

    • 用于得到一个**有效无限**的伪随机 int 值流

      Random random = new Random();
      IntStream ints = random.ints();
      ints.forEach(System.out::println);
      
  • random.ints(int randomNumberOrigin, int randomNumberBound)

    • 用于得到一个**有效无限的范围在起始值到结束值之间的伪随机 int 值流,[起始值, 结束值)**

      Random random = new Random();
      IntStream ints = random.ints(1, 5);
      ints.forEach(System.out::println);
      
  • random.ints(long streamSize, int randomNumberOrigin, int randomNumberBound)

    • 用于得到一个**有限长度的范围在起始值到结束值之间的伪随机 int 值流,[起始值, 结束值)**

      Random random = new Random();
      IntStream ints = random.ints(5, 1, 5);
      ints.forEach(value -> System.out.print(value + " ")); // 4 2 1 4 1
      
  • random.longs()

    • 用于得到一个**有效无限**的伪随机 long 值流

      Random random = new Random();
      LongStream longs = random.longs();
      longs.forEach(System.out::println);
      
  • random.longs(long streamSize)

    • 用于得到一个**有限长度**的伪随机 long 值流

      Random random = new Random();
      LongStream longs = random.longs(5);
      // -4253735830085011397 -81131290106869012 8737071083795249766 2189971428068815599 -6480079951366618766
      longs.forEach(value -> System.out.print(value + " "));
      

TimeUnit类常用方法解析

一、TimeUnit类的定义
  • TimeUnit 类位于 java.util.concurrent 包中,是一个枚举类,主要用于时间颗粒度的转换与线程的延时
  • TimeUnit 包含以下七个枚举常量
常量名含义
NANOSECONDS纳秒,等于 $1 * 10^{-9}s$
MICROSECONDS微秒,等于 $1 * 10^{-6}s$
MILLISECONDS毫秒,等于 $1 * 10^{-3}s$
SECONDS
MINUTES
HOURS
DAYS
二、TimeUnit 类常用方法
  • toDays(long duration)

    • 将指定颗粒度的时间转换为天数

      // 将1天转换为天数
      System.out.println(TimeUnit.DAYS.toDays(1)); // 1
      
  • toHours(long duration)

    • 将指定颗粒度的时间转换为小时数

      // 将1天转换为小时数
      System.out.println(TimeUnit.DAYS.toHours(1)); // 24
      
  • toMinutes(long duration)

    • 将指定颗粒度的时间转换为分数

      // 将1天转换为分数
      System.out.println(TimeUnit.DAYS.toMinutes(1)); // 1440
      
  • toSeconds(long duration)

    • 将指定颗粒度的时间转换为秒数

      // 将1天转换为秒数
      System.out.println(TimeUnit.DAYS.toSeconds(1)); // 86400
      
  • toSeconds(long duration)

    • 将指定颗粒度的时间转换为秒数

      // 将1天转换为秒数
      System.out.println(TimeUnit.DAYS.toSeconds(1)); // 86400
      
  • toMillis(long duration)

    • 将指定颗粒度的时间转换为毫秒数

      // 将1天转换为毫秒数
      System.out.println(TimeUnit.DAYS.toMillis(1)); // 86400000
      
  • toMicros(long duration)

    • 将指定颗粒度的时间转换为微秒数

      // 将1天转换为微秒数
      System.out.println(TimeUnit.DAYS.toMicros(1)); // 86400000000
      

    toNanos(long duration)

    • 将指定颗粒度的时间转换为纳秒数

      // 将1天转换为纳秒数
      System.out.println(TimeUnit.DAYS.toNanos(1)); // 86400000000000
      
  • convert(long sourceDuration, TimeUnit sourceUnit)

    • 将参数颗粒度时间转换为指定颗粒度时间

      // 将48小时转换为天数
      System.out.println(TimeUnit.DAYS.convert(48, TimeUnit.HOURS)); // 2
      
  • compareTo(E o)

    • 比较两个枚举常量的索引值大小,返回一个差值

image-20220530090817585

// [NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]
System.out.println(Arrays.toString(TimeUnit.values())); 
// DAYS的索引值为6
System.out.println(TimeUnit.DAYS.ordinal()); //6
// MINUTES的索引值为4
System.out.println(TimeUnit.MINUTES.ordinal()); // 4
System.out.println(TimeUnit.DAYS.compareTo(TimeUnit.MINUTES)); // 2
System.out.println(TimeUnit.MINUTES.compareTo(TimeUnit.DAYS)); // -2
  • sleep(long timeout)

    • 提供了可读性更好的**线程休眠**操作,使线程休眠指定时间颗粒度的时间,通常用来替换 Thread.sleep()

    • 当使用 Thread.sleep() 方法时,由于输入的参数为毫秒数,所以很难直观地看出当前线程具体休眠了多长时间

    Thread.sleep(2000);
    // 休眠2秒钟 (时间颗粒度为秒)
    TimeUnit.SECONDS.sleep(2);
    // 休眠2分钟 (时间颗粒度为分)
    TimeUnit.MINUTES.sleep(2)
    
  • timedJoin(Thread thread, long timeout)

    • 对指定线程,休眠指定时间颗粒度的时间

      // 对当前线程休眠2秒
      TimeUnit.SECONDS.timedJoin(Thread.currentThread(), 2);
      
  • timedWait(Object obj, long timeout)

    • 对指定对象,休眠指定时间颗粒度的时间

      public class Test {
      	// 此处需要使用synchronized关键字将方法锁住
          public synchronized void show() throws InterruptedException {
              TimeUnit.SECONDS.timedWait(this, 2);
              System.out.println("HelloWorld");
          }
          
      	public static void main(String[] args) throws InterruptedException {
              Test test = new Test();
              // 2秒之后执行
              test.show();
          }
      }
      

Math类常用方法解析

一、Math 类定义
  • Math 类位于 java.lang 包中,主要提供了一些常用的数学函数和计算
二、Math 类常用方法
三角函数运算
  • Math.toDegrees(double angrad)

    • 将弧度转换为角度

      System.out.println(Math.toDegrees(1.5707963267948966)); // 90.0
      
  • Math.toRadians(double angdeg)

    • 将角度转换为弧度

      System.out.println(Math.toRadians(90)); // 1.5707963267948966
      
  • Math.sins(double a)

    • 计算正弦值

      // 先将30°转换为弧度,再计算其正弦值,30°的正弦值为0.5
      System.out.println(Math.sin(Math.toRadians(30))); // 0.49999999999999994约等于0.5
      
  • Math.asin(double a)

    • 计算反正弦值

      // 先求出值为0.5的反正弦值(弧度),再将弧度转换为角度
       System.out.println(Math.toDegrees(Math.asin(0.5))); // 30.000000000000004约等于30°
      
  • Math.cos(double a)

    • 计算余弦值

      // 先将60°转换为弧度,再计算其余弦值,60°的余弦值为0.5
      System.out.println(Math.cos(Math.toRadians(60))); // 0.5000000000000001约等于0.5
      
  • Math.tan(double a)

    • 计算正切值

    • 30°的正切值: $\frac{1}{\sqrt{3}}$

      // 先将30°转换为弧度,再计算其正切值
      System.out.println(Math.tan(Math.toRadians(30))); // 0.5773502691896257
      
  • Math.sinh(double x)

    • 计算双曲正弦值

    • 双曲正弦值表达式:$\frac{e^x - e^{-x}}{2}$

  • Math.cosh(double x)

    • 计算双曲余弦值

    • 双曲余弦值表达式:$\frac{e^x + e^{-x}}{2}$

      System.out.println(Math.cosh(1)); // 1.543080634815244
      
  • Math.tanh(double x)

    • 计算双曲正切值

    • 双曲正切值表达式:$\frac{e^x - e^{-x}}{e^x + e^{-x}}$

      System.out.println(Math.tanh(1)); // 0.7615941559557649
      
  • Math.atan2(double y, double x)</font

    • 计算指定点与极坐标的弧度

    • 指定点的y轴坐标为$\sqrt{3}$,x 轴坐标为 1,其与 (0, 0) 所成的角度为 60°

      System.out.println(Math.toDegrees(Math.atan2(Math.sqrt(3), 1))) // 59.99999999999999约等于60°
      
算术运算
  • Math.addExact(int x, int y)

    • 计算两参数之和,参数类型:int 或 long

      System.out.println(Math.addExact(1, 2)); // 3
      
  • Math.subtractExact(int x, int y)

    • 计算两参数之差(第一个参数 - 第二个参数),参数类型:int 或 long

      System.out.println(Math.subtractExact(3, 2)); // 1
      
  • Math.floorMod(int x, int y)

    • 计算两参数相除的余数(第一个参数 / 第二个参数),参数类型:int 或 long

      System.out.println(Math.floorMod(2, 3)); // 2
      
  • Math.floorDiv(int x, int y)

    • 计算小于或等于商的最大整数值,参数类型:int 或 long

      System.out.println(Math.floorDiv(4, 3)); // 1
      
  • Math.pow(double a, double b)

    • 计算 a 的 b 次幂,$a^b$

      System.out.println(Math.pow(2, 3)); // 8.0
      
  • Math.sqrt(double a)

    • 计算平方根,$\sqrt{a}$

      System.out.println(Math.sqrt(16)); // 4.0
      
  • Math.cbrt(double a)

    • 计算立方根,$\sqrt[3]{a}$

      System.out.println(Math.cbrt(8)); // 2.0
      
  • Math.hypot(double x, double y)

    • 计算两个参数平方和的平方根,$\sqrt{x^2 + y^2}$

      System.out.println(Math.hypot(6, 8)); // 10.0
      
  • Math.log(double x)

    • 计算以 e 为底的对数 (自然对数),$\log{e^x}$$\ln{x}$

      System.out.println(Math.log(Math.E)); // 1.0
      
  • Math.log10(double x)

    • 计算以 10 为底的对数,$\log{10^x}$$\lg{x}$

      System.out.println(Math.log10(100)); // 2.0
      
  • Math.log1p(double x)

    • 计算以 e 为底,1 与参数之和为指数的对数,$\log{e^{1 + x}}$$\ln{(1 + x)}$

      System.out.println(Math.log1p(Math.E - 1)); // 1.0
      
  • Math.expm1(double x)

    • 计算 e 的 x 次幂 - 1, $\log{e^x-1}$$\ln{x} - 1$

      System.out.println(Math.expm1(1) + 1); // 2.718281828459045
      
  • Math.scalb(float x, int y)

    • 计算 x 乘以 2 的 y 次幂,$x*2^y$

      System.out.println(Math.scalb(2, 3)); // 16.0
      
  • Math.IEEEremainder(double x, double y)

    • 按照 IEEE 754 标准的规定,对两个参数进行余数运算,余数的算术值等于 x − y × n x - y × n xy×n

    • 其中 n 为最接近 x / y x/y x/y 的商的整数

    • 如果两个整数同样接近,则选其中的偶数

    • 如果余数为 0,那么它的符号与第一个参数的符号相同

System.out.println(Math.IEEEremainder(105, 10)); // 5.0
System.out.println(Math.IEEEremainder(106, 10)); // -4.0
取整运算
  • Math.ceil(double x)

    • 向上取整,返回大于该值的最近 double 值

      System.out.println(Math.ceil(1.23)); // 2.0
      System.out.println(Math.ceil(-1.23)); // -1.0
      
  • Math.floor(double x)

    • 向下取整,返回小于该值的最近 double 值

      System.out.println(Math.floor(1.23)); // 1.0
      System.out.println(Math.floor(-1.23)); // -2.0
      
  • Math.round(double x)

    • 四舍五入取整,参数类型:double、float

      System.out.println(Math.round(1.43)); // 1
      System.out.println(Math.round(1.53)); // 2
      System.out.println(Math.round(-1.43)); // -1
      System.out.println(Math.round(-1.53)); // -2
      
随机运算
  • Math.random()

    • 内部调用了 Random.nextDouble() 方法,生成一个伪均匀分布在 0.0 到 1.0 之间的 double 值

      System.out.println((int)(Math.random() * 10 + 1)); // 生成范围再[1, 11)之间的伪随机数
      
符号运算
  • Math.abs(int x)

    • 计算绝对值,参数类型:int、long、float、double

      System.out.println(Math.abs(-1)); // 1
      
  • Math.negateExact(int x)

    计算相反值,参数类型:int、long

    System.out.println(Math.negateExact(-1)); // 1
    
  • Math.signum(double x)

    • 如果参数为 0.0,则返回 0.0

    • 如果参数大于 0.0,则返回 1.0

    • 如果参数小于 0.0,则返回 -1.0

    • 参数类型:float、double

      System.out.println(Math.signum(0.1)); // 1.0
      System.out.println(Math.signum(0.0)); // 0.0
      System.out.println(Math.signum(-0.1)); // -1.0
      
  • Math.copySign(double magnitude, double sign)

    • 获取带有第二个浮点参数符号的第一个浮点参数,参数类型:(double, double)、(float, float)

      System.out.println(Math.copySign(1.1, -0.1)); // -1.1
      
  • 大小运算

    • Math.max(int x, int y)

      • 获取两个参数中的最大值,参数类型:int、long、float、double

        System.out.println(Math.max(1, 2)); // 2
        
  • Math.min(int x, int y)

    • 获取两个参数中的最小值,参数类型:int、long、float、double

      System.out.println(Math.min(1, 2)); // 1
      
  • Math.decrementExact(int x)

    • 获取该参数递减之后的数,参数类型:int、long

      System.out.println(Math.decrementExact(2)); // 1
      
  • Math.incrementExact(int x)

    • 获取该参数递增之后的数,参数类型:int、long

      System.out.println(Math.incrementExact(1)); // 2
      
  • Math.nextUp(double x)

    • 获取比参数略大的相邻浮点数,参数类型:float、double

      System.out.println(Math.nextUp(1.1)); // 1.1000000000000003
      
  • Math.nextDown(double x)

    • 获取比参数略小的相邻浮点数,参数类型:float、double

      System.out.println(Math.nextDown(1.1)); // 1.0999999999999999
      
  • Math.nextAfter(double start, double direction)

    • 获取第一个参数和第二个参数之间与第一个参数相邻的浮点数,参数类型:(double, double)、(float, double)

      System.out.println(Math.nextAfter(1.2, 1.3)); // 1.2000000000000002
      
  • Math.rint(double x)

    • 获取与参数最接近的double值

      System.out.println(Math.rint(1.4)); // 1.0
      System.out.println(Math.rint(1.5)); // 2.0
      System.out.println(Math.rint(-1.4)); // -1.0
      System.out.println(Math.rint(-1.5)); // -2.0
      
其他运算
  • Math.ulp(double x)

    • 获取参数的 ulp 值,ulp 值是该浮点值与下一个数值较大的浮点值之间的正距离,参数类型:float、double

      System.out.println(Math.ulp(0.1)); // 1.3877787807814457E-17
      
  • Math.getExponent(double x)

    • 获取在表示浮点数时使用的无偏指数,参数类型:float、double

      System.out.println(Math.getExponent(1024)); // 10
      

ThreadPoolExecutor类常用方法解析

一、ThreadPoolExecutor 类定义
  • ThreadPoolExecutor 类位于 java.util.concurrent 包中,主要用于创建线程池

  • ThreadPoolExecutor 类提供四个构造函数来实例化 ThreadPoolExecutor 对象

    ThreadPoolExecutor(int corePoolSize,
                       int maximumPoolSize,
                       long keepAliveTime,
                       TimeUnit unit,
                       BlockingQueue<Runnable> workQueue)
    
    
    ThreadPoolExecutor(int corePoolSize,
                       int maximumPoolSize,
                       long keepAliveTime,
                       TimeUnit unit,
                       BlockingQueue<Runnable> workQueue,
                       ThreadFactory threadFactory)
    
    
    ThreadPoolExecutor(int corePoolSize,
                       int maximumPoolSize,
                       long keepAliveTime,
                       TimeUnit unit,
                       BlockingQueue<Runnable> workQueue,
                       RejectedExecutionHandler handler)
    
    
    ThreadPoolExecutor(int corePoolSize,
                       int maximumPoolSize,
                       long keepAliveTime,
                       TimeUnit unit,
                       BlockingQueue<Runnable> workQueue,
                       ThreadFactory threadFactory,
                       RejectedExecutionHandler handler)
    
    
  • 由源码可知,前面三个构造函数内部都是调用第四个构造函数来实现的

  • 构造函数七个参数含义如下

参数名含义
corePoolSize核心线程数
maximumPoolSize最大线程数
keepAliveTime非核心线程的最大存活时间
unitkeepAliveTime 参数的时间单位
workQueue工作队列
threadFactory线程创建工厂
handler线程拒绝策略
  • ThreadPoolExecutor 类包含四个**线程拒绝策略**
拒绝策略含义
AbortPolicy直接丢弃任务,抛出异常 (默认策略)
CallerRunsPolicy将任务分配给调用线程来执行
DiscardPolicy直接丢弃任务,不抛出异常
DiscardOldestPolicy丢弃队列中最早的任务,不抛出异常
二、ThreadPoolExecutor 类常用方法

创建一个线程池,用于下面例子调用

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 10, 
    TimeUnit.SECONDS, new LinkedBlockingQueue<>(10),  
    Executors.defaultThreadFactory(),  new ThreadPoolExecutor.AbortPolicy());
  • getPoolSize()

    • 获取线程池中当前的线程数

      executor.execute(() -> System.out.println("Hello World"));
      System.out.println(executor.getPoolSize()); // 1
      executor.shutdown();
      
  • getLargestPoolSize()

    • 获取线程池中同时存在的最大线程数

    • largestPoolSize <= maximunPoolSize

      executor.execute(() -> System.out.println("Hello World"));
      System.out.println(executor.getLargestPoolSize()); // 1
      executor.shutdown();
      
  • getCorePoolSize()

    • 获取核心线程数

      System.out.println(executor.getCorePoolSize()); // 5
      
  • setCorePoolSize(int corePoolSize)

    • 设置核心线程数

      executor.setCorePoolSize(10);
      System.out.println(executor.getCorePoolSize()); // 10
      
  • setCorePoolSize(int corePoolSize)

    • 设置核心线程数

      executor.setCorePoolSize(10);
      System.out.println(executor.getCorePoolSize()); // 10
      
  • getMaximumPoolSize()

    • 获取最大线程数

      System.out.println(executor.getMaximumPoolSize()); // 10
      
  • setMaximumPoolSize(int maximumPoolSize)

    • 设置最大线程数

      executor.setMaximumPoolSize(20);
      System.out.println(executor.getMaximumPoolSize()); // 20
      
  • getKeepAliveTime(TimeUnit unit)

    • 获取线程最大存活时间 (该线程指的是非核心线程)

      System.out.println(executor.getKeepAliveTime(TimeUnit.SECONDS)); // 10
      
  • setKeepAliveTime(long time, TimeUnit unit)

    • 设置线程最大存活时间 (该线程指的是非核心线程)

      executor.setKeepAliveTime(20, TimeUnit.SECONDS);
      System.out.println(executor.getKeepAliveTime(TimeUnit.SECONDS)); // 20
      
  • getQueue()

    • 获取工作队列

    • 当线程数大于核心线程数且小于最大线程数时,提交的新任务会放入到队列中

      • 此种情况,当前线程数为 5,小于等于核心线程数,因此不会有任务放入到队列中

        IntStream.range(0, 5).forEach(i -> 
            executor.execute(() -> System.out.println("Hello World")));
        System.out.println(executor.getQueue());
        executor.shutdown();
        // Hello World
        // Hello World
        // Hello World
        // Hello World
        // Hello World
        // []
        
        • 此种情况,当前线程数为 6,大于核心线程数,因此会有任务放入到队列中

          IntStream.range(0, 6).forEach(i -> 
              executor.execute(() -> System.out.println("Hello World")));
          System.out.println(executor.getQueue());
          executor.shutdown();
          // Hello World
          // Hello World
          // Hello World
          // Hello World
          // Hello World
          // Hello World
          // [clazz.ThreadPoolExecutorTest$$Lambda$2/1023892928@4dd8dc3]
          
  • getThreadFactory()

    • 获取线程创建工厂

      System.out.println(executor.getThreadFactory()); 
      // java.util.concurrent.Executors$DefaultThreadFactory@3d075dc0
      
  • setThreadFactory(ThreadFactory threadFactory)

    • 设置线程创建工厂

      executor.setThreadFactory(Executors.defaultThreadFactory());
      System.out.println(executor.getThreadFactory()); 
      // java.util.concurrent.Executors$DefaultThreadFactory@682a0b20
      
  • getRejectedExecutionHandler()

    • 获取线程拒绝策略

      System.out.println(executor.getRejectedExecutionHandler()); 
      // java.util.concurrent.ThreadPoolExecutor$AbortPolicy@214c265e
      
  • setRejectedExecutionHandler(RejectedExecutionHandler handler)

    • 设置线程拒绝策略

      executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
      System.out.println(executor.getRejectedExecutionHandler()); 
      // java.util.concurrent.ThreadPoolExecutor$DiscardPolicy@682a0b20
      
  • getActiveCount()

    • 获取正在执行任务的**大致**线程数

      executor.execute(() -> System.out.println("Hello World"));
      System.out.println(executor.getActiveCount()); // 1
      executor.shutdown();
      
  • getTaskCount()

    • 获取已安排执行的**大致**任务总数

    • 因为任务和线程的状态可能在计算期间动态改变,所以获取到的只是近似值

      executor.execute(() -> System.out.println("Hello World"));
      System.out.println(executor.getTaskCount()); // 1
      executor.shutdown();
      
  • getCompletedTaskCount()

    • 获取已完成执行的大致任务总数

    • 因为任务和线程的状态可能在计算期间动态改变,所以获取到的只是近似值

      executor.execute(() -> System.out.println("Hello World"));
      System.out.println(executor.getCompletedTaskCount()); // 1
      executor.shutdown();
      
  • execute(Runnable command)

    • 执行给定的 Runnable 任务

      executor.execute(() -> System.out.println("Hello World")); // Hello World
      executor.shutdown();
      
  • submit(Runnable task)

    • 提交给定的 Runnable 任务进行执行,在任务执行完成后,返回相应的 Future

    • Future 的 get() 方法会在任务执行完成后**返回 null**

      Future<?> submit1 = executor.submit(() -> System.out.println("Hello World"));
      System.out.println(submit1.get()); // null
      executor.shutdown();
      
  • submit(Callable task)

    • 提交给定的 Callable 任务进行执行,在任务执行完成后,返回相应的 Future

    • Future 的 get() 方法会在任务执行完成后**返回任务结果**

      Future<Object> submit2 = executor.submit(() -> "Hello World");
      System.out.println(submit2.get()); // Hello World
      executor.shutdown();
      
  • submit(Runnable task, T result)

    • 提交给定的 Runnable 任务进行执行,在任务执行完成后,返回相应的 Future

    • Future 的 get() 方法会在任务执行完成后**返回给定的任务结果**

      Future<String> submit = executor.submit(() -> System.out.println("Hello World"), "result");
      System.out.println(submit.get()); // result
      executor.shutdown();
      
  • invokeAll(Collection<? extends Callable> tasks)

    • 执行给定的 Callable 任务列表,在所有任务执行完成后,返回相应的 Future 列表

    • Future 的 get() 方法会在任务执行完成后返回给定的任务结果

      Callable<String> task1 = () -> "Hello World1";
      Callable<String> task2 = () -> "Hello World2";
      List<Callable<String>> callableList = Arrays.asList(task1, task2);
      List<Future<String>> futureList = executor.invokeAll(callableList);
      for (Future<String> future : futureList) {
          System.out.println(future.get());
      }
      executor.shutdown();
      
      // Hello World1
      // Hello World2
      
  • invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)

    • 执行给定的 Callable 任务列表,在所有任务执行完成后,返回相应的 Future 列表

    • 针对所有任务,进行了超时时间控制,如果超时,会取消所有没有未完成的任务,并抛出 CancellationException 异常

      Callable<String> task1 = () -> "Hello World1";
      Callable<String> task2 = () -> {
          TimeUnit.SECONDS.sleep(2);
          return "Hello World2";
      };
      List<Callable<String>> callableList = Arrays.asList(task1, task2);
      List<Future<String>> futureList = executor.invokeAll(callableList, 1, TimeUnit.SECONDS);
      for (Future<String> future : futureList) {
          System.out.println(future.get());
      }
      executor.shutdown();
      
      // Hello World1
      // Exception in thread "main" java.util.concurrent.CancellationException
      // 	at java.util.concurrent.FutureTask.report(FutureTask.java:121)
      // 	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
      // 	at clazz.ThreadPoolExecutorTest.main(ThreadPoolExecutorTest.java:55)
      
  • invokeAny(Collection<? extends Callable> tasks)

    • 执行给定的任务列表,在有一个任务成功执行完成后,就会返回相应的任务结果,其余任务会被取消

      Callable<String> task1 = () -> "Hello World1";
      Callable<String> task2 = () -> "Hello World2";
      List<Callable<String>> callableList = Arrays.asList(task1, task2);
      String result = executor.invokeAny(callableList);
      System.out.println(result); // Hello World1
      executor.shutdown();
      
  • invokeAny(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)

    • 执行给定的任务列表,在有一个任务成功执行完成后,就会返回相应的任务结果

    • 针对所有任务,进行了超时时间控制,如果超时,会取消超时任务,直到有任务成功执行为止

    • 如果所有任务都超时,则会抛出 TimeoutException 异常

      Callable<String> task1 = () -> {
          TimeUnit.SECONDS.sleep(2);
          return "Hello World1";
      };
      Callable<String> task2 = () -> "Hello World2";
      List<Callable<String>> callableList = Arrays.asList(task1, task2);
      String result = executor.invokeAny(callableList, 1, TimeUnit.SECONDS);
      System.out.println(result); // Hello World2
      executor.shutdown();
      
      Callable<String> task1 = () -> {
      TimeUnit.SECONDS.sleep(2);
      return "Hello World1";
      };
      Callable<String> task2 = () -> {
      TimeUnit.SECONDS.sleep(2);
      return "Hello World2";
      };
      List<Callable<String>> callableList = Arrays.asList(task1, task2);
      String result = executor.invokeAny(callableList, 1, TimeUnit.SECONDS);
      System.out.println(result);
      executor.shutdown();
      
      // Exception in thread "main" java.util.concurrent.TimeoutException
      // 	at java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:184)
      // 	at java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:225)
      // 	at clazz.ThreadPoolExecutorTest.main(ThreadPoolExecutorTest.java:75)
      
      
  • isShutdown()

    • 如果线程池已关闭,则返回 true;否则返回 false
    executor.execute(() -> System.out.println("Hello World"));
    executor.shutdown();
    System.out.println(executor.isShutdown()); // true
    
    
  • isTerminated()

    • 如果在线程池关闭后,所有任务都已完成,则返回 true;否则返回 false

    • 此外,除非先调用 shutdown() 方法 或 shutdownDown() 方法,否则 isTerminated() 永远为 false

      • 此种情况,执行 execute() 方法的线程晚于主线程执行完毕,因此 isTerminated() 方法返回 false

        executor.execute(() -> System.out.println("Hello World"));
        executor.shutdown();
        System.out.println(executor.isTerminated()); // false
        
    • 此种情况,让主线程休眠 100 ms,使执行 execute() 方法的线程先执行完毕,因此 isTerminated() 方法返回 true

    executor.execute(() -> System.out.println("Hello World"));
    executor.shutdown();
    TimeUnit.MILLISECONDS.sleep(100);
    System.out.println(executor.isTerminated()); // true
    
  • isTerminating()

    • 如果线程池在执行了 shutdown() 方法或 shutdownNow() 方法后,尚有任务未执行完成,则返回 true;否则返回 false

    • 此种情况,执行 execute() 方法的线程晚于主线程执行完毕,因此 isTerminating() 方法返回 true

      executor.execute(() -> System.out.println("Hello World"));
      executor.shutdown();
      System.out.println(executor.isTerminating()); // true
      
  • 此种情况,让主线程休眠 100 ms,使执行 execute() 方法的线程先执行完毕,因此 isTerminating() 方法返回 false

    executor.execute(() -> System.out.println("Hello World"));
    executor.shutdown();
    TimeUnit.MILLISECONDS.sleep(100);
    System.out.println(executor.isTerminating()); // false
    
  • shutdown()

    • 关闭线程池
    • 正在执行的任务会继续执行,尚未执行的任务不再处理
  • shutdownNow()

    • 立刻关闭线程池
    • 中止所有正在执行的任务,尚未执行的任务不再处理
  • prestartCoreThread()

    • 启动一个核心线程,使其等待执行任务,返回 true

    • 此方法会覆盖在执行新任务时,启动核心线程的默认策略

    • 如果所有核心线程均已启动,则调用此方法会返回 false

      System.out.println(executor.prestartCoreThread()); // ture
      System.out.println(executor.getPoolSize()); // 1
      executor.shutdown();
      
      IntStream.range(0, 5).forEach(i -> executor.execute(() -> System.out.println("Hello World")));
      System.out.println(executor.prestartCoreThread()); // false
      System.out.println(executor.getPoolSize()); // 5
      executor.shutdown();
      
  • prestartAllCoreThreads()

    • 启动所有核心线程,使其等待执行任务

    • 此方法会覆盖在执行新任务时,启动核心线程的默认策略

      System.out.println(executor.prestartAllCoreThreads()); // 5
      System.out.println(executor.getPoolSize()); // 5
      executor.shutdown();
      
  • allowCoreThreadTimeOut(boolean value)

    • 设置是否允许核心线程超时

      executor.prestartAllCoreThreads();
      executor.allowCoreThreadTimeOut(true);
      System.out.println(executor.getPoolSize()); // 5
      TimeUnit.SECONDS.sleep(15);
      System.out.println(executor.getPoolSize()); // 0
      
  • allowsCoreThreadTimeOut()

    • 获取核心线程是否可以超时的标识

      executor.allowCoreThreadTimeOut(true);
      System.out.println(executor.allowsCoreThreadTimeOut()); // true
      
      executor.allowCoreThreadTimeOut(false);
      System.out.println(executor.allowsCoreThreadTimeOut()); // false
      
  • awaitTermination(long timeout, TimeUnit unit)

    • 设置超时时间,当线程池关闭后,阻塞主线程直到所有任务都执行完毕,或者超时

      • 此种情况,任务执行完毕时间小于超时时间,即所有线程都已执行完毕,返回 true

        executor.execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Hello World");
        });
        executor.shutdown();
        System.out.println(executor.awaitTermination(3, TimeUnit.SECONDS)); // true
        
        
      • 此种情况,任务执行完毕时间大于超时时间,即尚有线程未执行完毕,返回 false

        executor.execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Hello World");
        });
        executor.shutdown();
        System.out.println(executor.awaitTermination(3, TimeUnit.SECONDS)); // false
        
        

meUnit.MILLISECONDS.sleep(100);
System.out.println(executor.isTerminated()); // true


- isTerminating()

- 如果线程池在执行了 shutdown() 方法或 shutdownNow() 方法后,尚有任务未执行完成,则返回 true;否则返回 false

- 此种情况,执行 execute() 方法的线程晚于主线程执行完毕,因此 isTerminating() 方法返回 true

  ```java
  executor.execute(() -> System.out.println("Hello World"));
  executor.shutdown();
  System.out.println(executor.isTerminating()); // true
  ```

- 此种情况,让主线程休眠 100 ms,使执行 execute() 方法的线程先执行完毕,因此 isTerminating() 方法返回 false

```java
executor.execute(() -> System.out.println("Hello World"));
executor.shutdown();
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(executor.isTerminating()); // false
  • shutdown()

    • 关闭线程池
    • 正在执行的任务会继续执行,尚未执行的任务不再处理
  • shutdownNow()

    • 立刻关闭线程池
    • 中止所有正在执行的任务,尚未执行的任务不再处理
  • prestartCoreThread()

    • 启动一个核心线程,使其等待执行任务,返回 true

    • 此方法会覆盖在执行新任务时,启动核心线程的默认策略

    • 如果所有核心线程均已启动,则调用此方法会返回 false

      System.out.println(executor.prestartCoreThread()); // ture
      System.out.println(executor.getPoolSize()); // 1
      executor.shutdown();
      
      IntStream.range(0, 5).forEach(i -> executor.execute(() -> System.out.println("Hello World")));
      System.out.println(executor.prestartCoreThread()); // false
      System.out.println(executor.getPoolSize()); // 5
      executor.shutdown();
      
  • prestartAllCoreThreads()

    • 启动所有核心线程,使其等待执行任务

    • 此方法会覆盖在执行新任务时,启动核心线程的默认策略

      System.out.println(executor.prestartAllCoreThreads()); // 5
      System.out.println(executor.getPoolSize()); // 5
      executor.shutdown();
      
  • allowCoreThreadTimeOut(boolean value)

    • 设置是否允许核心线程超时

      executor.prestartAllCoreThreads();
      executor.allowCoreThreadTimeOut(true);
      System.out.println(executor.getPoolSize()); // 5
      TimeUnit.SECONDS.sleep(15);
      System.out.println(executor.getPoolSize()); // 0
      
  • allowsCoreThreadTimeOut()

    • 获取核心线程是否可以超时的标识

      executor.allowCoreThreadTimeOut(true);
      System.out.println(executor.allowsCoreThreadTimeOut()); // true
      
      executor.allowCoreThreadTimeOut(false);
      System.out.println(executor.allowsCoreThreadTimeOut()); // false
      
  • awaitTermination(long timeout, TimeUnit unit)

    • 设置超时时间,当线程池关闭后,阻塞主线程直到所有任务都执行完毕,或者超时

      • 此种情况,任务执行完毕时间小于超时时间,即所有线程都已执行完毕,返回 true

        executor.execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Hello World");
        });
        executor.shutdown();
        System.out.println(executor.awaitTermination(3, TimeUnit.SECONDS)); // true
        
        
      • 此种情况,任务执行完毕时间大于超时时间,即尚有线程未执行完毕,返回 false

        executor.execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Hello World");
        });
        executor.shutdown();
        System.out.println(executor.awaitTermination(3, TimeUnit.SECONDS)); // false
        
        
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值