一、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));
    }
}

但是这个Objects.equals方法的比较需要两个对象实现各自的eqauls方法。

我们先自定义一个实体类,没有实现其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方法的话会使用Object类中的equals方法,而Object类中的equals方法比较的是两个对象的内存地址是否相等,而现在我们创建的是两个对象,内存地址肯定是不一样的,所以它们的比较是不相等的,所以我们需要在比较的类中实现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));
    }
}

这样就实现了我们想要的结果。

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.比较两个数组

Objects.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()方法可以实现数组转List

示例代码如下:

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));
    }
}