Java中集合

Java中集合类 Collection

集合类 Collection是集合层次结构中的根接口。集合表示一组对象,称为其元素。有些集合允许重复元素,而有些则不允许。有些是有序的,有些是无序的。JDK不提供此接口的任何直接实现:它提供更具体的子接口(如Set和List)的实现。此接口通常用于传递集合,并在需要最大通用性的地方对其进行操作。


一、集合


/*
* Collection:使程序能够存储和操纵元素不固定的一组数据,集合类属于java.util包中
*   数组:长度固定,可以存放任意类型数据
*   集合:长度不固定,只能存放引用类型(使用自动装箱存放基本数据类型)
*
* 根据继承体系,集合中分为两大类,List和Set 且两个都继承了Collection
*   Collection中有的方法List和Set都有
*
* Collection集合只能存储单个元素,且只能保存引用数据类型,不能保存基本数据类型
*   底层为Object[]数组,可以保存任何元素,Object是祖类,所有类型都会发生向上转型(多态)
*   基本类型和Object没有关系,可以把基本数据类型转换为对应的包装类类型保存在Collection
*   包装类类型是Object的子类
*
* 常用方法:
*   Boolean add(): 添加
*   void clear(): 清空集合
*   boolean remove(): 删除
*   boolean isEmpty(): 是否为空
*   boolean contains(): 是否包含某个元素
*   int size(): 返回集合中 元素个数
* */

public class _01_CollectionSummary {

    public static void main(String[] args) {
        // 接口不能创建对象,以ArrayList为例,发生多态,会丢失ArrayList的特有方法
        // 现在调用方法都是Collection中的方法
        Collection<Object> c1 = new ArrayList<>();


        // 判断是否为空 true
        System.out.println(c1.isEmpty());

        // 添加
        c1.add("abed");
        c1.add(111); // 自动装箱为Integer在向上转型为Object
        Object o1 = new Object();
        _01_CollectionSummary o2 = new _01_CollectionSummary();
        c1.add(o1);
        c1.add(o2);
        System.out.println(c1.isEmpty()); // false
        // size不是数组长度,是数组中已经添加的元素个数
        System.out.println(c1.size());

        // 转数组
        Object[] arr = c1.toArray();
        for (Object o : arr) {
            System.out.println(o);
        }
        System.out.println();
        System.out.println("--------------");

        // 删除
        c1.remove(111);
        // 从新获取数组
        arr = c1.toArray();
        for (Object o : arr) {
            System.out.print(o);
        }
        System.out.println();
        System.out.println("--------------");

        c1.clear();
        System.out.println(c1.size());
    }
}

二、迭代器


/*
* 迭代器是一种从程序设计模式,可在迭代对象上遍历,而无需关心容器对象的内存分配细节
*   Collection接口的iterator()和toArray()方法都用于获取集合中所有元素,前者返回迭代对象,后者返回数组
*   Iterator接口隐藏集合底层数据结构,提供各种类型集合的统一接口
*   可以使序列类型的数据结构的遍历行为和被遍历的对象分离
*
* 创建迭代器对象
*   Iterator it = 集合对象.iterator();
*   调用集合对象自身的iterator方法就可以创建数据当前对象的迭代器
*
* Iterator方法
*   1 boolean hasNext(); 判断光标下一位,是否还有元素,有返回true,否返回false
*       生成迭代器的时候,光标不是指向第一个元素,而是在最顶端,没有指向如何元素
*       光标会自动复位,使用完之后,必须从新生成
*   2 E next(); 光标向下移动一位,并返回该位置上的数据
*   3 删除当前光标指向的元素
*       三个方法使用顺序:1->2->3
*
* 迭代器创建后,如果集合在添加或删除元素,那迭代器必须从新生成,否则调用next方法报错
*   但更改数据不需从新创建
*
* 增强for循环 forEach 属于iterator的简单形式,功能不如iterator全,也是迭代器
*   forEach和iterator基本一致,不能删除和添加集合数据,可以更改
* 普通 for while 循环,是和数据结构存储有关系的,如遍历数组时,需要使用arr[index]访问
*   且可以进行删除和添加操作
*
* 使用迭代器进行遍历操作时,如果需要删除元素,只能使用迭代器的remove方法,不能使用集合的remove方法
* */

public class _01_Collection_Iterator {

    public static void main(String[] args) {
        // 创建集合
        Collection<Object> c = new ArrayList<>();
        //添加元素
        c.add(111);
        c.add("abcd");
        c.add(false);
        c.add(null);

        // 通过集合创建迭代器对象
        Iterator<Object> it = c.iterator();

        // 判断是否还有元素,否终止
        while (it.hasNext()){
            Object next = it.next();
            System.out.println(next);
        }
        System.out.println("-------");
        System.out.println(it.hasNext()); // false

        // 不会执行,因为while循环中执行完后 光标就移动到最后
        // 这时在判断hasNext(),则为false
        if (it.hasNext()){
            // 能进来说明集合还存在元素
            Object next = it.next();
            System.out.println(next);
        }

        // 迭代器使用后添加或删除操作
        c.add(123);

        // 只要迭代器生成,只要集合添加或删除操作后继续使用这个迭代器,就会报错
        // java.util.ConcurrentModificationException
        // 如果使用,需要重新生成
        it = c.iterator();
        if (it.hasNext()){
            // 能进来说明集合还存在元素
            Object next = it.next();
            // 生成迭代器后后,不能使用集合的remove方法,除非使用后从新生成,否则报错
            // c.remove(123);
            // 可以使用迭代器的remove方法
            it.remove();
            System.out.println(next);
        }

        // if 循环中 it.remove(); 操作全部删除完了。输出0
        System.out.println(c.size());
    }
}

三、常用的两个方法


/*
* contains()与remove()
*   boolean contains(); 判断集合中是否包含某个元素
*   boolean remove(); 集合中删除指定元素
*
* 这两个方法底层都会调用equals方法进行比较
*   c.contains("abc"), 会用 abc 调用String的equals方法 依次和集合中元素进行比较
*   判断或删除某个对象,就用某个对象调用equals方法,依次比较
* */

public class _01_Collection_Imp {

    public static void main(String[] args) {
        // 创建集合对象
        Collection<Object> c = new ArrayList<>();
        Integer i1 = 1; // 自动装箱
        Integer i2 = 2;
        Integer i3 = 3;
        c.add(i1);
        c.add(i2);
        c.add(i3);

        String s1 = "abc";
        boolean b1 = false;
        c.add(s1);
        c.add(b1);

        Integer i4 = new Integer(2);
        String s2 = new String("abc");
        boolean b2 = false;

        System.out.println(i4==i2); // false,i4中new,在堆内存中
        System.out.println(i4.equals(i2)); // true, Integer重写了equals方法,比较的是值

        // contains(i4)方法会自动调用i4的equals方法和集合中元素进行比较
        System.out.println(c.contains(i4)); // true
        System.out.println(c.contains(s2)); // true
        System.out.println(c.contains(b2)); // true
        c.remove(b1);
        System.out.println(c.contains(b2));
        System.out.println("----------");

        // 自定义类型
        Manager m1 = new Manager(11, "张三");
        Manager m2 = new Manager(11, "张三");
        c.add(m1);
        // 如果Manager类中没有覆写equals方法,在contains(m2)方法执行时自动调用的是Manager父类中的equals方法
        // Manager默认继承Object类,则会调用Object类中的equals方法,Object类中的equals方法默认比较内存地址
        // 所以尽管两个实例化对象数据相同,但使用contains()方法时依旧不存在
        // 按指定需求覆写equals方法后在比较久为true
        System.out.println(c.contains(m2));
        System.out.println(c.contains(m1));
    }
}

class Manager{
    private int num;
    private String name;

    public Manager() {
    }

    public Manager(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Manager [num=" + num + ", name=" + name + "]";
    }

    @Override
    // 自定义对象中通过覆写equals方法定制条件判断对象是否相等
    // 需求:如果编号num与姓名name一样。认同为同一个对象
    public boolean equals(Object obj) {
        System.out.println("=====");
        if (obj == null) return false;
        if (obj == this){
            return true;
        }
        if (obj instanceof Manager){
            Manager m2 = (Manager) obj; // 强制类型转换,是的传入对象一致才有可比性
            return m2.name.equals(this.name) && m2.num == this.num;
        }
        return false;
    }
}

/*
    ArrayList中contains源码
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
        // Returns: true if this list contains the specified element
    }
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i])) // 调用equals方法比较集合中元素
                    return i;
        }
        return -1;
    }

    ArrayList中remove源码
    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) { // 调用equals方法比较集合中元素
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
*/

总结

这里简单的介绍了Collection接口,在Java中,集合采用的是 接口与实现分离,在具体应用中,应根据自己的需求选择合适的接口并实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值