欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

week06_day01

程序员文章站 2022-05-09 13:50:07
...

week06_day01
其实主要分为两部分:Collection和Map

·······················································································································································································································

正式讲课之前,我们先来搞明白三个小问题:

  1. 为什么需要集合类?
    很多情况下,我们需要对一组对象进行操作。而且很可能事先并不知道到底有多少个对象。为了解决这个问题呢,Java 就提供了集合类供我们使用。

  2. 集合类的特点
    a. 只能存储引用数据类型
    b. 可以自动地调整自己的大小

  3. 数组和集合类都是容器,它们有何不同?
    a. 数组可以存储基本数据类型的数据,集合不可以。
    b. 数组的长度是固定的,集合可以自动调整自己的大小。
    c. 数组的效率高,相对来说集合效率比较低。
    d. 数组没有API,集合有丰富的API。

在实际开发中,更经常用的是集合,能用集合做不要用数组。因为不用自己去写API,而且这样你写的代码别人能看懂。

Collection就是一个容器,里面放你的元素。
Collection不存在次序的概念,也就不存在index,也就不存在头删尾删

正确的创建Project、Moudle的方式:

  1. File-----New-----Project,写入project创建路径,此时一个Project就创建好了,创建好后删除Project下的src目录。
  2. 在Project中点击:File-----New-----Moudle

·······················································································································································································································

Collection概念
Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

Collection 的含义大家应该清楚了,那么它应该包含哪些 API 呢?
week06_day01

Collection中的equals方法和hashCode方法都应当被重写,因为我们应当比较的是一个Collection中的元素个数以及元素值是否相等甚至元素次序(如LinkedList)是否相等,而不应该比较这两个集合是否是同一个集合(不应比较这两个集合指向的内存地址是否相同)。既然equals方法重写了,hashCode方法也应当被重写。

特点:
a. 可以自动地调整自己的大小
b. 只能存储引用数据类型

API:

  • 增:
    boolean add(E e)
    boolean addAll(Collection c)
  • 删:
    void clear()
    boolean remove(Object o)
    boolean removeAll(Collection c)
    boolean retainAll(Collection c) //retain 保留
  • 查:
    boolean contains(Object o)
    boolean containsAll(Collection c)
  • 获取集合的属性:
    boolean isEmpty()
    int size()
  • 遍历:
    Object[] toArray()
    Iterator iterator()
public class Demo01 {

    public static void main(String[] args) {

        Collection c = new ArrayList(10);
        for (int i = 0; i < 30; i++) {
            c.add(i);
        }

        //Collection重写了toString方法,打印出来的是数组的值,而不是地址
        System.out.println(c);
        System.out.println(c.size());
    }
}

思考一下,我们说集合没法装基本数据类型的数据,那为什么我们把int类型的数据装进去了呢?

因为自动装箱拆箱。
提供基本数据类型是为了提高性能的,因为数据很简单。但在java中奉行一种原理:一切数据皆对象。所以提供了基本数据类型对应的引用数据类型。

自动装箱:基本数据类型转换成对应的引用数据类型
自动拆箱:引用数据类型转换成对应的基本数据类型

public class Demo02 {

    public static void main(String[] args) {
        /*int intValue = 10;
        Integer integer = Integer.valueOf(intValue);
        int i = integer.intValue();*/

		//我们只需按照下面这样写就行了
		//下面写的这三行代码会在编译时自动编译成上面三行代码
        int intValue = 10;
        // 自动装箱
        Integer integer = intValue;
        // 自动拆性
        int i = integer;
    }
}

·······················································································································································································································

()中的类型和Collection无关的API:

  • boolean add(E e)
    会发现ArrayList允许重复元素,HashSet不允许重复元素。这就是多态。增加成功返回true,失败返回false。
  • boolean remove(Object o)
    ArrayList只会删除第一个值为o的元素。删除成功返回true,失败返回false。
  • void clear()
  • boolean contains(Object o)
    包含值为0的元素成功返回true,失败返回false。
  • boolean isEmpty()
    为空成功返回true,失败返回false。
  • int size()
    返回Collection对象容纳的元素个数。
public class Demo03 {

    public static void main(String[] args) {

        // boolean add(E e)
        Collection c = new ArrayList();
        c.add("hello");
        c.add("world");
        c.add("java");

        System.out.println(c);
        System.out.println(c.add("java")); // ?
        System.out.println(c);

        Collection c2 = new HashSet();
        System.out.println(c2.add("hello"));
        System.out.println(c2.add("world"));
        System.out.println(c2.add("java"));
        System.out.println(c2);
        System.out.println(c2.add("java"));
        System.out.println(c2);

        // boolean remove(Object o)
        System.out.println(c.remove("java")); // true
        System.out.println(c);
        System.out.println(c.remove("database")); // false
        System.out.println(c);

        c.add("javase");
        c.add("java");
        System.out.println(c.remove("java"));
        System.out.println(c);

        // int size() , void clear()
        System.out.println(c.size());
        c.clear();
        System.out.println(c.size());

       // boolean empty() 判空:判断集合中是否有元素
        //在null上看它的属性,调用它的方法,都会报空指针异常
        //如何判断一个对象是否为null?  if(c == null)  即可
        c = null;
        System.out.println(c.isEmpty()); // ?
        c.clear();
        System.out.println(c.isEmpty());

        // boolean contains(Object o)
        System.out.println(c.contains("java"));
        System.out.println(c.contains("database"));
    }
}

·······················································································································································································································

()中的类型和Collection有关的API:

  • boolean addAll(Collection c)
    如果集合发生了改变返回true, 否则返回false
  • boolean removeAll(Collection c)
    如果集合发生了改变返回true, 否则返回false
  • boolean retainAll(Collection c)
    如果集合发生了改变返回true, 否则返回false
  • boolean containsAll(Collection c)
    如果包含集合c中所有的元素返回true, 否则返回false

例子:假如ArrayList C的值为:bejing、beijing、beijing、wuhan、shenzhen。ArrayList C2的值为:beijing、wuhan、shenzhen。
C2.containsAll(C )依然会返回true
迷惑的时候想一想如果是你实现底层的操作,你会怎么做:从C中取出一个一个的元素,看在C2中是否有和它相同的元素。

·······················································································································································································································

  • Object[] toArray()
    将集合转换成数组

小结:
数组长度:arr.length 属性
字符串长度:s.length() 方法
集合大小:c.size() 方法

public class Demo05 {

    public static void main(String[] args) {

        Collection list = new ArrayList();
        list.add("hello");
        list.add("world");
        list.add("java");

        Object[] array = list.toArray();
        for (int i = 0; i < array.length; i++) {
            String s = (String) array[i];
            if (s.equals("java")) {
                array[i] = "javaSE";
            }
        }

        //会发现改变了array的数据,但并没有改变list的数据
        System.out.println(Arrays.toString(array));
        System.out.println(list);
    }
}

week06_day01
但实际开发中,我们更希望你对array进行操作,让这个操作影响到原本的集合
如何做呢?用Iterator iterator()

·······················································································································································································································

  • Iterator iterator()
    迭代器,集合的专用遍历方式
  • Iterable接口
    Iterator iterator()
  • Iterator接口
    它是对集合进行迭代的迭代器
    依赖于集合对象存在
    boolean hasNext()
    E next()
    void remove()
public class Demo06 {

    public static void main(String[] args) {

        Collection list = new ArrayList();
        list.add("hello");
        list.add("java");
        list.add("world");
        list.add("java");
        list.add("java");


        //Iterator iterator()方法会实实在在的改变集合list中的元素
        Iterator it = list.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.println(s);
        }

        //  void remove() 删除最近返回的元素
        Iterator it2 = list.iterator();
        while (it2.hasNext()) {
            String s = (String) it2.next();
            if ("java".equals(s)) {
                it2.remove();
            }
        }
        System.out.println(list);

        //但其实刚刚讲过的collection中的方法 boolean remove(Object o)也能删除
        //但是只会删除第一个值为o的元素。删除成功返回true,失败返回false。
        list.remove("java");
        System.out.println(list);

		//迭代器+list.remove(s); 可以删除"java"吗?  不可以
		//用集合的API修改集合的结构,所有的迭代器会失效
        Iterator it3 = list.iterator();
        while (it3.hasNext()) {
            String s = (String) it3.next(); //ConcurrentModificationException并发修改异常
            if ("java".equals(s)) {
                list.remove(s);
            }
        }

        System.out.println(list); 
    }
}

week06_day01
·······················································································································································································································

注意事项:
a. 用集合的API修改集合的结构,所有的迭代器会失效
用迭代器的API修改集合的结构,其它迭代器会失效
b. 用迭代器遍历集合的时候,不要使用while循环,可以使用for循环,最好使用foreach循环

public class Demo07 {

    public static void main(String[] args) {

        Collection c = new ArrayList();
        c.add("hello");
        c.add("java");
        c.add("world");
        c.add("java");
        c.add("java");

        Iterator it1 = c.iterator();
        while (it1.hasNext()) {
            String s = (String) it1.next();
            if ("java".equals(s)) it1.remove();
        }
        System.out.println(c);


        // ... 茫茫多代码

        Iterator it2 = c.iterator();
        while (it2.hasNext()) {
            String s = (String) it2.next();
            if ("hello".equals(s)) it2.remove();
        }

        System.out.println(c);
    }
}

上面这段代码,两个迭代器it1和it2对c遍历,这样写没有问题。
但是假如在用it2遍历时,不小心把it2.remove();写成了it1.remove();,那么就会报错:ConcurrentModificationException 并发修改异常。也就是说,你在用一个迭代器遍历时,只能访问这个迭代器的变量。
这就是对用迭代器的API修改集合的结构,其它迭代器会失效这句话的解释。

所以说:用迭代器遍历集合的时候,不要使用while循环,可以使用for循环,最好使用foreach循环。因为for循环中的变量只在本循环体内起作用。

如果我改成了for循环,后面就不可能用到it1了。

public class Demo07 {

    public static void main(String[] args) {

        Collection c = new ArrayList();
        c.add("hello");
        c.add("java");
        c.add("world");
        c.add("java");
        c.add("java");

        for(Iterator it1 = c.iterator();it3.hasNext();){
            String s = (String) it3.next();
            System.out.println(s);
        }
        System.out.println(c);

        // ... 茫茫多代码

        for (Iterator it4 = c.iterator();it4.hasNext();) {
            String s = (String) it4.next();
            if(s.equals("java")) it4.remove();
        }
        System.out.println(c);
    }
}

·······················································································································································································································

下面来看一看Iterator的实现原理:

推荐阅读