集合

Collection

集合概述

集合体系共分为两大类,分别是List和Set,并且都继承了Collection。

Collection集合由于底层是Object[]数组,所以只能存储单个元素,并且只能保存引用数据类型,不能保存基本数据类型。存储基本数据类型可以使用基本数据类型对应的包装类,完成自动装箱操作

常用方法:

  • boolean add() : 添加元素
  • void clear() : 清空集合
  • boolean remove() 删除某个元素
  • boolean isEmpty() 判断集合中是否为空
  • boolean contains() : 是否包含某个元素
  • int size() 返回集合中 元素个数

如:

public class Collection_01 {
    public static void main(String[] args) {
        //Collection是一个接口,不能创建对象,所以使用ArrayList创建集合对象
        //因为发生多态,所以丢失了ArrayList中特有的方法
        //所以现在调用的方法都是Collection的方法
        Collection c1 = new ArrayList();
        //判断是否为空
        System.out.println(c1.isEmpty());
        //添加数据
        c1.add("asd");
        //123为int值,对自动装箱为Integer,再向上转型为Object
        c1.add(123);

        Object o1 = new Object();
        c1.add(o1);
        //判断是否为空
        System.out.println(c1.isEmpty());
        //输出集合中的个数
        System.out.println(c1.size());

        //遍历
        //将集合转换为数组
        Object[] arr = c1.toArray();
        for (Object object : arr) {
            System.out.println(object);
            System.out.println(object.getClass());
        }
        System.out.println("---------------------------");
        // 删除
        c1.remove(123);
        // 重新获取数组
        arr = c1.toArray();
        for (Object object : arr) {
            System.out.println(object);
        }
        // 清空数组中元素
        c1.clear();
        System.out.println(c1.size());

    }
}

继承体系

  • Collection ——> List ——> ArrayList类
  • Collection ——> List ——> LinkedList类
  • Collection ——> Set ——> HashSet类
  • Collection ——> Set ——> SortedSet接口 ——> TreeSet类
  • Map ——> HashMap类
  • Map ——> SortedMap ——> TreeMap类

collection注意事项

使用集合中

  • boolean contains(Object o):判断集合中是否包含某个元素
  • boolean remove(Object o):在集合中删除指定元素

这两个方法时,都会调用equals方法,所以在集合中存储类对象时,需要在类中重写toString方法
如:

public class Collection_03 {
    public static void main(String[] args) {
        Manager m1 = new Manager(2, "张三");
        Manager m2 = new Manager(2, "张三");
        c.add(m1);
        //true
        System.out.println(c.contains(m1));
        //如果Manager没有重写equals,结果为false,因为调用的是Object的equals,比较的是内存地址
        //如果Manager重写equals,结果为true
        System.out.println(c.contains(m2));

    }
}

class Manager {
    private int id;
    private String name;

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

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

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

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

迭代器

迭代器是一种模式,它可以使序列类型的数据结构的遍历行为和被遍历的对象分离。

也就是说我们无需关心序列的底层数据结构是什么样子的,只要拿到这个对象,使用迭代器就可以遍历这个对象的内部数据。

语法格式:
Iterator it = 集合对象.iterator();

通过调用集合对象自己的iterator方法就可以创建属于自己的迭代器。

常用方法:

  • boolean hasNext() : 判断光标下一位是否还有元素,有就返回true,没有就返回false,生成迭代器的时候,光标不是指向第一个元素,而是在最顶端,没有指向任何元素,并且 光标不会自动复位,使用完之后,必须重新生成。
  • E next() : 把光标向下移动一位,并返回该位上的数据(E表示返回的数据类型)
  • remove() : 删除当前光标指向的元素

上述三个方法的使用顺序是从上到下使用,迭代器一旦创建,如果集合中添加或者删除元素,那么迭代器必须重新生成。否则调用next()方法会报错。更改数据不需要重新生成迭代器。

foreach循环就是迭代器的简单实现形式。
如:

public class Collection_02_Iterator {
    public static void main(String[] args) {

        //创建集合
        Collection c = new ArrayList();
        //添加元素
        c.add(123);
        c.add("asd");
        c.add(2.3);
        c.add(false);
        c.add(null);

        //创建迭代器
        Iterator it = c.iterator();
        //判断还有没有元素,没有就终止
        while (it.hasNext()){
            //能进循环说明还有下一个
            Object o = it.next();
            System.out.println(o);
        }
        System.out.println("=======================");

        //false
        System.out.println(it.hasNext());

        //使用for完成
        //不能进入for,因为光标已经到最后了
        //如果想再次使用,只能重新创建迭代器
        for (;it.hasNext();){
            //能进循环说明还有下一个
            Object o = it.next();
            System.out.println(o);
        }

        c.add(1);

        //只要迭代器生成,添加或删除元素,迭代器就会报错
        //如果要使用,需要重新生成
        //java.util.ConcurrentModificationException
        it = c.iterator();
        while (it.hasNext()){
            Object o = it.next();
            //一旦生成迭代器 不能使用 集合的remove,除非重新生成,否则报错
            //c.remove(1);
            //但是可以使用迭代器的remove进行删除操作
            it.remove();
            System.out.println(o);
        }
        System.out.println(c.size());

    }
}

List

List集合的特点:有序可重复。并且 存入顺序和取出顺序是一致的,并且有指定的下标,可以表示数据的唯一性,所以可以存在重复数据。
ArrayList和LinkedList继承了List

  • ArrayList : 底层是数组,查询效率较高,添加和删除效率较低
  • LinkedList : 底层是双向链表,查询效率较低,添加和删除效率较高

ArrayList

ArrayList:底层是索引数组,下标从0开始,初始容量为10,扩大容量为原始容量的1.5倍。非线程安全,效率较高。

常用方法:

  • add(E e) : 将指定元素添加到尾部
  • add(int index,E e) : 将指定元素添加到指定位置,原位置内容统一向后移动
  • set(int index,E e) : 更改指定位置上的元素值
  • get(int index) : 获取指定索引上的元素
  • remove(int index) : 删除指定索引上的元素
  • remove(Object o) : 删除指定元素

如:

public class Collection_05_ArrayList {
    public static void main(String[] args) {
        List<> li = new ArrayList<>();
        //集合底层是Object[]数组,所以集合可以保存任意数据类型
        //基本数据类型会进行自动装箱操作
        li.add(1);
        //把元素添加在指定位置,该位置上的元素统一向后移动
        li.add(0,2);
        System.out.println(li);
        //更改指定位置上的元素
        li.set(0,3);
        System.out.println(li);
        //获取指定位置的元素
        Object o = li.get(1);
        System.out.println(o+","+o.getClass());

        //remove(),删除方法重载,如果是int,说明是要删除元素的下标是什么,Object才是被删除的对象
        //li.remove(3);
        //删除值为3的元素
        li.remove(new Integer(3));
        System.out.println(li);

        li.add("aa");
        li.add("aa2");
        li.add("aa3");
        for (Object object : li) {
            System.out.println(object);
        }
        System.out.println("==================================");
        for (int i = 0; i < li.size(); i++) {
            System.out.println(li.get(i));
        }
    }

LinkedList

LinkedList:底层是双向链表,链表中保存的是节点信息,每个节点包括三个元素,分别是自身元素对象,上一个节点的地址和下一个节点的地址。
链表是没有下标的,内存空间不连续,所以查询较慢,删除增加快。

常用方法:

  • add(E e) : 添加到尾部
  • push(E e) : 添加到头部
  • ddFirst(E e) : 添加到头部
  • addLast(E e) : 添加到尾部
  • offerFirst(E e) 添加到头部,成功返回true
  • offerLast(E e) : 添加到尾部,成功返回true
  • get(int index) : 返回指定下标对应的数据(链表没有下标,只是模拟下标,方便我们查询使用)

添加的本质其实就调用了linkLast()和linkFirst()两个方法。
如:

public class Collection_06_LinkedList {
    public static void main(String[] args) {
        LinkedList<Integer> linkedList = new LinkedList<>();
        linkedList.add(1);
        linkedList.addFirst(2);
        linkedList.addLast(3);
        linkedList.push(4);
        linkedList.offerFirst(5);
        linkedList.offerLast(6);

        //使用foreach和for遍历
        for (Object object : linkedList) {
            System.out.println(object);
        }
        System.out.println("----");
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }
        System.out.println("==========================");

        LinkedList<String> list = new LinkedList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.remove(1);
        System.out.println(list.size());
        System.out.println(list.get(1));
    }
}

Set

Set特点:无序和不可重复
Set的子类:TreeSet和HashSet
TreeSet:底层红黑树
HashSet:底层散列表

ThreeSet

TreeSet:元素必须有序,添加的元素会按照某种规则自动排序。想要使用TreeSet,元素必须有序。

  • 数字:默认从小到大
  • 字符串:默认比较每位的ASCII码
    如果有多个字符,先比较第一位,如果第一位不同,则第一位小的在上面; 如果第一位相同,再比较第二位,以此类推
  • 日期:默认比较自然日期:昨天,今天,明天

如:

public class Collection_08_TreeSet {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>();
        ts.add(1);
        ts.add(7);
        ts.add(3);
        ts.add(5);
        //上面添加的是Integer类型
        //因为要实现自动排序
        //所以不能添加其他类型的元素
        //ts.add("aa");
        for (Object object : ts) {
            System.out.println(object);
        }

        System.out.println("=======================");
        TreeSet<String> ts2 = new TreeSet<>();
        ts2.add("a");
        ts2.add("1");
        // 如果有多个字符,先比较第一位,如果第一位不同,则第一位小的在上面
        // 如果第一位相同,再比较第二位,以此类推
        ts2.add("11");
        ts2.add("101");
        ts2.add("b");
        ts2.add("n");
        for (Object object : ts2) {
            System.out.println(object);
        }
    }
}

比较器的实现

比较器有两种:元素自身比较器和比较器类

使用TreeSet在进行数据添加的时候,会自动调用该对象的compareTo()方法和集合内元素进行比较。

必须通过实现Comparable接口对存储自定义类型进行比较,实现compareTo()方法。

如果不实现Comparable接口,在向TreeSet集合中添加元素时报错。

如:

public class Collection_09_TreeSet {
    public static void main(String[] args) {
        TreeSet<User> treeSet = new TreeSet<User>();
        User user1 = new User(11);
        User user2 = new User(13);
        User user3 = new User(6);
        treeSet.add(user1);
        treeSet.add(user2);
        treeSet.add(user3);
        System.out.println(treeSet.size());

        for (Object object : treeSet) {
            System.out.println(object);
        }
    }
}

class User implements Comparable {
    private int age;

    public User(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        //this 是当前对象
        //o 是集合内对象
        //并且返回值值为0表示相等,则不添加
        //返回大于0的表示要添加的元素大,则放到后面
        //返回小于0的表示要添加的元素小,则放到前面
        User user = (User) o;
        //升序
        //return this.age - user.age;
        //降序
        return user.age - this.age;
    }
}
/*
输出结果为:
3
User{age=13}
User{age=11}
User{age=6}

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值