Java自带常用工具类

一、Objects:专为操作Java对象而生的工具类

1.对象判空

Objects 的 isNull 方法用于判断对象是否为空,而 nonNull 方法判断对象是否不为空。

示例代码如下:

import java.util.Objects;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Objects工具测试
 */
public class ObjectTest {
    public static void main(String[] args) {
        String name = null;
        // 输出true
        System.out.println(Objects.isNull(name));
        // 输出false
        System.out.println(Objects.nonNull(name));
    }
}

2.判断两个对象是否相等

我们经常需要判断两个对象是否相等,Objects 给我们提供了 equals 方法。

示例代码如下:

import java.util.Objects;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Objects工具测试
 */
public class ObjectTest {
    public static void main(String[] args) {
        String name1 = "a";
        String name2 = "A";
        // 比较两个对象是否相等 输出false
        System.out.println(Objects.equals(name1, name2));
    }
}

如果是两个对象之间的比较,还需要重写对象的equals和hashCode方法。

我们定义一个学生类 没有实现equals方法

/**
 * @author qinxun
 * @date 2023-06-02
 * @Descripion: 学生类
 */
public class Student {

    private String name;

    private String school;

    public Student() {
    }

    public Student(String name, String school) {
        this.name = name;
        this.school = school;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
    
}

在测试类比较两个对象,发现两个对象并不相等

import java.util.Objects;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Objects工具测试
 */
public class ObjectTest {
    public static void main(String[] args) {
        Student student1 = new Student("qx", "桂林");
        Student student2 = new Student("qx", "桂林");
        // 比较两个对象是否相等 输出false
        System.out.println(Objects.equals(student1, student2));
    }
}

接下来我们在实体类中实现equals方法

import java.util.Objects;

/**
 * @author qinxun
 * @date 2023-06-02
 * @Descripion: 学生类
 */
public class Student {

    private String name;

    private String school;

    public Student() {
    }

    public Student(String name, String school) {
        this.name = name;
        this.school = school;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) && Objects.equals(school, student.school);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, school);
    }
}

我们再次调用测试方法

import java.util.Objects;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Objects工具测试
 */
public class ObjectTest {
    public static void main(String[] args) {
        Student student1 = new Student("qx", "桂林");
        Student student2 = new Student("qx", "桂林");
        // 比较两个对象是否相等 输出true
        System.out.println(Objects.equals(student1, student2));
    }
}

执行程序结果返回:

true

3.对象为空时抛异常

如果我们想在对象为空时,抛出空指针异常可以使用 Objects 的 requireNonNull 方法。

示例代码如下:

import java.util.Objects;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Objects工具测试
 */
public class ObjectTest {
    public static void main(String[] args) {
        String name = null;
        System.out.println(Objects.requireNonNull(name, "名字为空"));
    }
}

执行程序,抛出了空指针异常。

Exception in thread "main" java.lang.NullPointerException: 名字为空
	at java.util.Objects.requireNonNull(Objects.java:228)
	at demo2.ObjectTest.main(ObjectTest.java:13)

4.比较两个数组

deepEquals() 用于比较两个数组的对象 

import java.util.Objects;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Objects工具测试
 */
public class ObjectTest {
    public static void main(String[] args) {
        int[] array1 = {1, 2, 3};
        int[] array2 = {1, 2, 3};
        // 输出true
        System.out.println(Objects.deepEquals(array1, array2));
    }
}

二、Arrays:专为数组而生的工具类

1.创建数组

  • copyOf:复制指定的数组,截取或用 null 填充
  • copyOfRange:复制指定范围内的数组到一个新的数组
  • fill:对数组进行填充

示例代码如下:

import java.util.Arrays;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: 数组工具类测试
 */
public class ArrayTest {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4};
        int[] revised = Arrays.copyOf(arr, 3);
        // 输出[1, 2, 3]
        System.out.println(Arrays.toString(revised));
        int[] expanded = Arrays.copyOf(arr, 5);
        // 输出[1, 2, 3, 4, 0]
        System.out.println(Arrays.toString(expanded));

        // 第二个参数包含,第三个参数不包含, 所以从第二位开始截取,截取到第三位
        int[] range = Arrays.copyOfRange(arr, 1, 3);
        // 输出[2, 3]
        System.out.println(Arrays.toString(range));

        
        int[] temp = new int[4];
        // 数组填充
        Arrays.fill(temp, 2);
        // 输出[2, 2, 2, 2]
        System.out.println(Arrays.toString(temp));
    }
}

2.比较数组

Arrays 类的 equals() 方法用来判断两个数组是否相等

import java.util.Arrays;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: 数组工具类测试
 */
public class ArrayTest {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4};
        int[] arr1 = {2, 3, 4};
        // 输出false
        System.out.println(Arrays.equals(arr, arr1));
    }
}

3.数组排序

Arrays 类的 sort() 方法用来对数组进行排序

import java.util.Arrays;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: 数组工具类测试
 */
public class ArrayTest {
    public static void main(String[] args) {
        int[] arr = {3, 4, 2, 1};
        // 排序
        Arrays.sort(arr);
        // 输出[1, 2, 3, 4]
        System.out.println(Arrays.toString(arr));

    }
}

4.数组转Stream流

Arrays 类的 stream() 方法可以将数组转换成流

import java.util.Arrays;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: 数组工具类测试
 */
public class ArrayTest {
    public static void main(String[] args) {
        int[] arr = {3, 4, 2, 1};
        // 输出3 4 2 1 
        Arrays.stream(arr).forEach(System.out::println);

    }
}

5.打印数组

使用 Arrays.toString()

import java.util.Arrays;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: 数组工具类测试
 */
public class ArrayTest {
    public static void main(String[] args) {
        int[] arr = {3, 4, 2, 1};
        // 输出[3, 4, 2, 1]
        System.out.println(Arrays.toString(arr));

    }
}

6.数组转 List

使用Arrays.asList方法

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: 数组工具类测试
 */
public class ArrayTest {
    public static void main(String[] args) {
        Integer[] arr = {3, 4, 2, 1};
        // 数组转list
        List<Integer> list = new ArrayList<>(Arrays.asList(arr));
        // 输出[3, 4, 2, 1]
        System.out.println(list);
    }
}

三、Collections:专为集合框架而生的工具类

1.排序操作

  • reverse(List list):反转顺序
  • shuffle(List list):洗牌,将顺序打乱
  • sort(List list):自然升序
  • sort(List list, Comparator c):按照自定义的比较器排序
  • swap(List list, int i, int j):将 i 和 j 位置的元素交换位置
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Collections工具类测试
 */
public class CollectionTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("d");
        list.add("c");
        list.add("e");

        System.out.println("原始顺序:" + list);

        // 反转
        Collections.reverse(list);
        System.out.println("反转后:" + list);

        // 洗牌
        Collections.shuffle(list);
        System.out.println("洗牌后:" + list);

        // 自然升序
        Collections.sort(list);
        System.out.println("自然升序后:" + list);

        // 交换
        Collections.swap(list, 2, 4);
        System.out.println("交换后:" + list);

    }
}
原始顺序:[a, b, d, c, e]
反转后:[e, c, d, b, a]
洗牌后:[a, e, c, b, d]
自然升序后:[a, b, c, d, e]
交换后:[a, b, e, d, c]

2.查找操作

  • binarySearch(List list, Object key):二分查找法,前提是 List 已经排序过了
  • max(Collection coll):返回最大元素
  • max(Collection coll, Comparator comp):根据自定义比较器,返回最大元素
  • min(Collection coll):返回最小元素
  • min(Collection coll, Comparator comp):根据自定义比较器,返回最小元素
  • fill(List list, Object obj):使用指定对象填充
  • frequency(Collection c, Object o):返回指定对象出现的次数
/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Collections工具类测试
 */
public class CollectionTest {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        // 输出1
        System.out.println(Collections.binarySearch(list, 2));

        // 输出3
        System.out.println(Collections.max(list));

        // 输出1
        System.out.println(Collections.min(list));

        // 输出1
        System.out.println(Collections.frequency(list, 2));
    }
}

3.同步控制

ArrayList 是线程不安全的,没法在多线程环境下使用,那 Collections 工具类中提供了多个 synchronizedXxx 方法,这些方法会返回一个同步的对象,从而解决多线程中访问集合时的安全问题。

我们先使用普通的ArrayList来实现多线程的数据添加

import java.util.ArrayList;
import java.util.List;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Collections工具类测试
 */
public class CollectionTest {
    public static void main(String[] args) throws InterruptedException {
        List<Integer> synchronizedList = new ArrayList<>();

        // 使用线程的方式添加两个数据到集合
        Thread thread = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                synchronizedList.add(i);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();

        Thread thread1 = new Thread(() -> {
            for (int i = 11; i <= 20; i++) {
                synchronizedList.add(i);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread1.start();
        Thread.sleep(1000);
        // 输出[1, 11, 12, 2, 13, 3, 4, 14, 5, 15, null, 16, 7, 17, 8, 18, 9, 19, 10, 20]
        System.out.println(synchronizedList);

    }
}

我们发现不是我们需要的结果。

接下来我们使用Collections.synchronizedList方式创建可以处理多线程的集合。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Collections工具类测试
 */
public class CollectionTest {
    public static void main(String[] args) throws InterruptedException {
        List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        // 使用线程的方式添加两个数据到集合
        Thread thread = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                synchronizedList.add(i);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();

        Thread thread1 = new Thread(() -> {
            for (int i = 11; i <= 20; i++) {
                synchronizedList.add(i);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread1.start();
        Thread.sleep(1000);
        // 输出[1, 11, 2, 12, 3, 13, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10]
        System.out.println(synchronizedList);
    }
}

实现了我们需要的结果。

4.不可变集合

  • emptyXxx():制造一个空的不可变集合
  • singletonXxx():制造一个只有一个元素的不可变集合
  • unmodifiableXxx():为指定集合制作一个不可变集合
import java.util.Collections;
import java.util.List;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Collections工具类测试
 */
public class CollectionTest {
    public static void main(String[] args) throws InterruptedException {
        List<Object> emptyList = Collections.emptyList();
        emptyList.add(3);
        System.out.println(emptyList);
    }
}

运行程序报错

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at demo2.CollectionTest.main(CollectionTest.java:16)

5.其他

  • addAll(Collection<? super T> c, T... elements),往集合中添加元素
  • disjoint(Collection<?> c1, Collection<?> c2),判断两个集合是否没有交集
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author qinxun
 * @date 2023-06-08
 * @Descripion: Collections工具类测试
 */
public class CollectionTest {
    public static void main(String[] args) throws InterruptedException {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "hello", "world");
        // 输出[hello, world]
        System.out.println(list);

        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);

        List<Integer> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        
        System.out.println("是否有交集:" + Collections.disjoint(list1, list2));
    }
}