集合视图与Collections类的使用

 首先明白一个集合的特性:

public class Test {
    int age;
    String name;

    public Test(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public static void main(String[] args) {
        ArrayList<Test> testArrayList = new ArrayList<>();
        Test test=new Test(12,"mike");
        testArrayList.add(test);
        System.out.println(testArrayList);
        test.setAge(22);
        System.out.println(testArrayList);
        testArrayList.get(0).setName("jack");
        System.out.println(test.toString());
    }

    @Override
    public String toString() {
        return "Test{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

结果:

由上面的代码,不难看出,所谓集合,就是一群相同相同或不同类型数据的集合,如果将某个对象添加到集合中,那么意味着这个元素开始服从这个集合的”管理“了

简谈动态安全类型:

Java数组在声明时就定义了元素的数据类型,在初始化时定义了数组长度,在此只后,不管该数组要被如何引用(做返回值,做参数等),只要对数组插入了与声明不符的元素,都会在编译阶段报错,如下

 如此,我们可以说Java数组就是动态安全类型

再来看看集合,当集合声明时未声明泛型,那么理论上它可以存储任何引用类型的数据,因为它的内部是使用了Object【】来存储元素,

一旦我们在声明时定义了泛型,再向里面插入非泛型数据时,那么它程序将在编译时提醒错误,如下:

但问题是泛型对元素的检查仅仅在程序编译时,如果我们将上面的代码换做如下写法:

public class Test {
    public static void main(String[] args) {
        ArrayList<Rabbit> rabbitArrayList=new ArrayList<>();
        addAAnimal(rabbitArrayList);
        System.out.println(rabbitArrayList);
    }
    public static void addAAnimal(List list){
        list.add(new Monkey());
    }
}
interface Animal{};
class Rabbit implements Animal{};
class Monkey implements Animal{};

便会发现,这段代码成功通过了泛型在编译时的检查(集合泛型是对集合调用的方法进行检查,并且最终将Monkey插入泛型为Rabbit的集合中,由此看来,泛型并没有让集合真正成为一个动态安全类型,

让集合真正实现动态安全

使用 java.util.Collections.checkedXXX()(本文以checkedList()来举例)方法来生成一个动态类型安全的集合视图

public static void main(String[] args) {
        ArrayList<Rabbit> rabbitArrayList=new ArrayList<>();
        List<Rabbit> rabbitList=Collections.checkedList(rabbitArrayList,Rabbit.class);
        System.out.println(rabbitArrayList.hashCode()==rabbitList.hashCode());
    }

由这段代码可以看出来,通过checkedList()生成的集合视图与原集合在内存上的地址相同,因此是同一个集合的不同的引用,checkedList()第二个参数表示此视图允许插入的元素,任何错误元素的插入都会产生ClassCastException异常,此检查链接运行时同样有效,因此可以很好的让集合实现动态安全。

示例:

public static void main(String[] args) {
        ArrayList<Rabbit> rabbitArrayList = new ArrayList<>();
        try {
            List<Rabbit> list = Collections.checkedList(new ArrayList<>(), Rabbit.class);//可通新建一个集合,也可使用已有的集合
            addAAnimal(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void addAAnimal(List list) {
        list.add(new Monkey());
    }

结果:

注意:

如果使用一个已经包含错误元素的集合新建一个视图,那么checked将不会对已插入的元素做任何事情:

例:

public class Test {
    public static void main(String[] args) {
        ArrayList<Rabbit> rabbitArrayList = new ArrayList<>();
        addAAnimal(rabbitArrayList);
        addAAnimal(rabbitArrayList);
        addAAnimal(rabbitArrayList);
        try {
            List<Rabbit> list = Collections.checkedList(rabbitArrayList, Rabbit.class);//使用已有的集合视图
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void addAAnimal(List list) {
        list.add(new Monkey());
    }
};
class Rabbit implements Animal {
};

class Monkey implements Animal {
    @Override
    public String toString() {
        return "i am monkey";
    }
};

结果:

所以一般建议使用第一种方式直接建立一个集合视图,增加集合的安全性

Collections类的其他常用方法:

collections是用来操作集合的工具类,常用方法如下:(部分方法以List为例说明)

static <T> boolean addAll(Collection<? super T> c, T... elements)

将所有指定的元素添加到指定的集合。

static <E> List<E> checkedList(List<E> list, <E> type)

返回指定列表的动态类型安全视图。

static <T> void copy(List<? super T> dest, List<? extends T> src)

将所有元素从一个列表复制到另一个列表中。(

static boolean disjoint(Collection<?> c1, Collection<?> c2)

如果两个指定的集合没有共同的元素,则返回 true

static <T> List<T> emptyList()

返回空列表(immutable)。

static <T> void fill(List<? super T> list, T obj)

用指定的元素代替指定列表的所有元素。

static int frequency(Collection<?> c, Object o)

返回指定集合中与指定对象相等的元素数。

static int lastIndexOfSubList(List<?> source, List<?> target)

返回指定源列表中指定目标列表的最后一次出现的起始位置,如果没有此类事件则返回-1。

static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)

根据指定的比较器引发的顺序返回给定集合的最大元素。

static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)

将列表中一个指定值的所有出现替换为另一个。

static <T> void sort(List<T> list, Comparator<? super T> c)

根据指定的比较器引起的顺序对指定的列表进行排序。

static void swap(List<?> list, int i, int j)

交换指定列表中指定位置的元素。

static <T> List<T> synchronizedList(List<T> list)

返回由指定列表支持的同步(线程安全)列表。

static <T> List<T> unmodifiableList(List<? extends T> list)

返回指定列表的不可修改视图。

方法较多,就几个常用的加以实践:

public class Test {
    public static void main(String[] args) {
        String s1 = "who";
        String s2 = "are";
        String s3 = "you";
        String s4 = "OK";
        List<String> stringList = new ArrayList<>();
        List<String> stringList2 = new ArrayList<>();
        Collections.addAll(stringList2, s2, s3);
        List<String> listView = Collections.checkedList(stringList, String.class);//生成动态类型安全的集合
        Collections.addAll(listView, s1, s1, s2, s2, s3,s4);
        System.out.println("collection is:" + listView);
        System.out.println("there were " + Collections.frequency(listView, s2) + " s2 in collection");//元素出现的次数
        System.out.println("\"are you\" first appearance was on the :" + Collections.lastIndexOfSubList(listView, stringList2));
        /*Collections.sort(listView);//默认为自然顺序排序
        System.out.println("sort with natural order:" + listView);*/
        Collections.sort(listView, Comparator.comparing(String::length));//自定义长度排序
        System.out.println("sort whit length:"+listView);
    }
}

结果:

特别说明:

如果对于个集合已经初始好的集合,我们只对它查询,不进行修改,那么,最好使用unmodifiableList返回一个不可修改的集合视图,增加集合的安全性:

public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        Collections.addAll(stringList,"who","are","you");
        List<String> unmodifiableList=Collections.unmodifiableList(stringList);//不可修改集合
        System.out.println(unmodifiableList.get(1));
        unmodifiableList.add("hello");
    }

发布了58 篇原创文章 · 获赞 75 · 访问量 6667

猜你喜欢

转载自blog.csdn.net/qq_42013035/article/details/103452711