Java进阶:Collection接口

Collection接口

Collection中 只要是Object的子类型,都能存储(集合中不能直接存储基本数据类型,也不能存储java对象,只是存储Java对象的内存地址)
关于java.util.Collection接口中常用的方法

  1. boolean add(Object e) 向集合中添加元素
  2. int size() 获取集合中元素的个数
  3. void clear() 清空集合
  4. boolean isEmpty() 判断该集合中的元素个数是否为0
  5. boolean contains(Object o) 判断当前集合中是否包含元素o,包含返回true,不包含返回false
  6. boolean remove(Object o) 删除集合中的某个元素
  7. Object[] toArray() 把集合转换成数组
public class CollectionTest {
    public static void main(String[] args) {
        // 创建一个集合对象
        //Collection c = new Collection(); // 接口是抽象的,无法实例化
        // 多态
        Collection c = new ArrayList();

        // 测试Collection接口中的常用方法
        // 1. boolean add(Object e) 向集合中添加元素
        c.add(123);    // 自动装箱,实际上存储的是对象的内存地址
        // 2. int size() 获取集合中元素的个数
        System.out.println("集合中的元素个数是:" + c.size());  //1
        // 3. void clear() 清空集合
        c.clear();
        System.out.println("集合中的元素个数是:" + c.size());  //0

        // 4. boolean isEmpty() 判断该集合中的元素个数是否为0
        System.out.println(c.isEmpty());    //true

        // 再添加元素
        c.add("hello");
        c.add("would");

        // 5. boolean contains(Object o) 判断当前集合中是否包含元素o,包含返回true,不包含返回false
        System.out.println(c.contains("hello"));    //true

        // 6. boolean remove(Object o) 删除集合中的某个元素
        System.out.println("集合中的元素个数是:" + c.size());    //2
        c.remove("would");
        System.out.println("集合中的元素个数是:" + c.size());    //1
    }
}

集合遍历/迭代(重点)

集合遍历/迭代方式在Map集合中不能用,在所有的Collection以及子类中使用。
迭代器对象Iterator中的方法:

  • boolean hasNext() 如果仍有元素可以迭代,则返回true
  • Object next() 返回迭代器的下一个元素
public class CollectionTest01 {
    public static void main(String[] args) {
        // 创建集合对象,不一定要HashSet
        Collection c = new HashSet();

        // 添加元素
        c.add("asd");
        c.add("qwe");
        c.add(123);
        c.add(new Object());

        // 对集合Collection进行遍历/迭代
        // 1.获取集合对象的迭代器对象Iterator
        Iterator iterator = c.iterator();
        // 2.通过以上获取的迭代器对象开始迭代/遍历集合
        while (iterator.hasNext()) {
            Object obj = iterator.next();   //取出来的都是Object类型的
            System.out.println(obj);
        }
    }
}

深入contains、remove方法

总结:存放在集合里的类型必须重写equals方法

public class CollectionTest02 {
    public static void main(String[] args) {
        // 创建集合对象
        Collection c = new ArrayList();

        // 向集合中存储元素
        String s1 = new String("asd");
        c.add(s1);

        String s2 = new String("qwe");
        c.add(s2);

        // 集合中的元素个数
        System.out.println("集合中的元素个数是:" + c.size());    //2

        // 新建的对象String
        String s = new String("asd");
        // 底层调用equals方法,比较的是内容
        System.out.println(c.contains(s));  // true
        System.out.println("remove:" + c.remove(s));    // true
        System.out.println("集合中的元素个数是:" + c.size());    //1


        System.out.println("----------------------------------------");

        User u1 = new User("zxc");
        c.add(u1);

        User u = new User("zxc");

        System.out.println("集合中的元素个数是:" + c.size());    //2
        // 没有重写equals方法
        //System.out.println(c.contains(u));  //false
        //System.out.println("remove:" + c.remove(s));    //false
        // 重写equals方法之后
        System.out.println(c.contains(u));  //true
        System.out.println("remove" + c.remove(s));   //true
        System.out.println("集合中的元素个数是:" + c.size());
    }
}


class User{
    private String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    // 重写equals
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || !(obj instanceof User)) return false;
        User user = (User) obj;
        return Objects.equals(name, user.name);
    }
}

重点:在迭代元素的过程中,一定要使用迭代器Iterator的remove方法删除元素,不要使用集合自带的remove方法,否则会出现ConcurrentModificationException异常

public class CollectionTest03 {
    public static void main(String[] args) {
        // 创建集合对象,不一定要HashSet
        Collection c = new ArrayList();

        // 添加元素
        c.add("asd");
        c.add("qwe");
        c.add("zxc");

        // 对集合Collection进行遍历/迭代
        // 注意:集合结构只要发生改变,迭代器必须重新获取
        Iterator iterator = c.iterator();

        while (iterator.hasNext()) {
            Object obj = iterator.next();
            // 删除元素之后,集合的结构发生了变化,会出现java.util.ConcurrentModificationException异常
            //c.remove(obj);    // 直接通过集合去删除元素,没有通知迭代器。(导致迭代器的快照与原集合不同)
            // 可以使用迭代器的remove()方法
            iterator.remove();  // 删除的一定是迭代器指向的当前元素(迭代器与原集合同时删除)
            System.out.println(obj);
        }
        System.out.println("集合中的元素个数是:" + c.size());    //0
    }
}

List接口

1.List集合存储元素特点:有序可重复
2.List是Collection接口的子接口,
以下是List接口特有的常用方法:

  1. void add(int index, Object element) 在列表指定位置插入指定元素(第一个参数是下标) 使用不多,效率较低
  2. Object set(int index, Object element) 修改指定位置的元素
  3. Object get(int index) 根据下标获取元素
  4. int indexOf(Object o) 获取指定对象第一次出现处的索引
  5. int lastIndexOf(Object o) 获取指定对象最后一次出现处的索引
  6. Object remove(int index) 删除指定下标位置的元素
public class ListTest {
    public static void main(String[] args) {
        // 创建List类型的集合
        List myList = new ArrayList();

        // 添加元素
        myList.add("asd");  // 默认都是向集合末尾添加元素
        myList.add("qwe");
        myList.add("zxc");
        myList.add("zxc");
        // 1. void add(int index, Object element) 在列表指定位置插入指定元素(第一个参数是下标)
        // 使用不多,效率较低
        myList.add(1,"asd1");

        Iterator iterator = myList.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }

        System.out.println("----------------------------");

        // 2. Object set(int index, Object element) 修改指定位置的元素
        myList.set(1,"asd2");
        for (int i = 0; i < myList.size(); i++) {
            Object obj = myList.get(i);
            System.out.println(obj);
        }

        System.out.println("----------------------------");

        // 3. Object get(int index) 根据下标获取元素
        Object firstObj = myList.get(0);
        System.out.println(firstObj);

        // 通过下标遍历(List集合特有的方式,Set没有)
        for (int i = 0; i < myList.size(); i++) {
            Object obj = myList.get(i);
            System.out.println(obj);
        }

        System.out.println("----------------------------");

        // 4. int indexOf(Object o) 获取指定对象第一次出现处的索引
        System.out.println(myList.indexOf("zxc"));  //3
        // 5. int lastIndexOf(Object o) 获取指定对象最后一次出现处的索引
        System.out.println(myList.lastIndexOf("zxc"));  //4

        //6. Object remove(int index) 删除指定下标位置的元素
        System.out.println(myList.size());  //5
        myList.remove(1);
        System.out.println(myList.size());  //4
    }
}

ArrayList集合

  • 默认初始化容量是10(底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量为10)
  • 集合底层是一个Object[]数组
  • 构造方法:
    new ArrayList();
    new ArrayList(20);
  • ArrayList集合的扩容:
    原容量的1.5倍
    ArrayList集合底层是数组,怎么优化?
    • 尽可能少的扩容。因为数组扩容效率比较低(因为很难找到一块连续的比较大的内存空间),建议在使用ArrayList集合的时候预估计元素的个数,给定一个初始化容量。
  • 数组优点:
    • 检索效率比较(每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,然后知道下标,通过数学表达式计算出元素的内存地址,所以检索效率最高)
  • 数组缺点:
    • 随机增删元素效率比较
  • 向数组末尾添加元素,效率很高,不受影响
  • ArrayList集合的使用最多,因为往数组末尾添加元素,效率很高,且检索/查找某个元素的操作比较多。
public class ArrayListTest {
    public static void main(String[] args) {
        // 默认初始化容量 10
        List list = new ArrayList();
        // 集合的size()方法是获取当前集合中元素的个数,不是获取集合的容量。
        System.out.println(list.size());    //0

        // 指定初始化容量 20
        List list1 = new ArrayList(20);
        System.out.println(list1.size());   //0

        // 创建一个HashSet集合
        Collection c = new HashSet();
        c.add(1);
        c.add(2);
        c.add(3);

        // 通过这个构造方法就可以将HashSet集合转换成List集合
        List list2 = new ArrayList(c);
        for (int i = 0; i < list2.size(); i++) {
            System.out.println(list2.get(i));
        }
    }
}

补充:位运算符 >> <<

public class BinaryTest {
    public static void main(String[] args) {
        // >> 1 二进制右移1位
        // 10的二进制:00001010
        // 右移1位后:00000101
        System.out.println(10 >> 1);    //5

        // << 1 二进制左移一位
        // 10的二进制:00001010
        // 左移1位后:00010100
        System.out.println(10 << 1);    //20
    }
}

LinkedList集合

链表的优点:

  • 由于链表上的元素在空间存储上内存地址不连续。
  • 所以随机增删元素的时候不会有大量元素位移,因此随机增删效率较高
  • 遇到随机增删集合中元素的业务比较多时,建议使用LinkedList

链表的缺点:

  • 不能通过数学表达式计算被查找元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止。
  • 所以LinkedList集合检索/查找效率较低

ArrayList:把检索发挥到极致。
LinkedList:把随机增删发挥到极致。
添加元素一般都是往末尾加,所以ArrayList用的比LinkedList多。

public class LinkedListTest {
    public static void main(String[] args) {
        // LinkedList集合没有初始化容量
        // LinkedList集合底层也是有下标的
        // 注意:ArrayList之所以检索效率比较高,不是单纯因为下标的原因,主要是底层数组发挥的作用。
        // LinkedList集合照样有下标,但是检索/查找某个元素的时候效率比较第,因为每一次查找都是从头节点开始一个一个遍历
        List list = new LinkedList();   // 底层是链表
        //List list = new ArrayList();  // 底层是数组
        
        // 面向接口编程
        list.add("a");
        list.add("b");
        list.add("c");

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

Vector集合

  • 底层也是一个数组

  • 初始化容量:10

  • Vector集合扩容方式:扩容之后是原容量的2倍

  • ArrayList集合扩容特点:扩容之后是原容量的1.5倍

  • Vector中所有的方法都是线程同步的,都带有synchronized关键字,是线程安全的。效率比较低,使用较少了。

  • 将一个线程不安全ArrayList集合转换成线程安全的方法:
    使用集合工具类: java.util.Collections

      java.util.Collection 是集合接口
      java.util.Collections 是集合工具类
    
public class VectorList {
    public static void main(String[] args) {
        List vector = new Vector();

        // 初始容量10
        vector.add(1);
        vector.add(2);
        vector.add(3);
        vector.add(4);
        vector.add(5);
        vector.add(6);
        vector.add(7);
        vector.add(8);
        vector.add(9);
        vector.add(10);

        // 满了之后扩容(扩容之后是20)
        vector.add(11);

        Iterator iterator = vector.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }


        List myList = new ArrayList();  // 非线程安全的

        // 将ArrayList集合转换成线程安全的
        Collections.synchronizedList(myList);

        myList.add("123");

    }
}

Set接口

HsahSet集合

/*
    HashSet集合存储元素特点:无序不可重复
 */
public class HashSetTest {
    public static void main(String[] args) {
        // 创建集合对象
        Set<String> set = new HashSet<>();

        // 添加元素
        set.add("hello1");
        set.add("hello3");
        set.add("hello2");
        set.add("hello1");

        // 遍历
        for (String s : set) {
            System.out.println(s);  // hello1 hello2 hello3
        }

    }
}

TreeSet集合

/*
    TreeSet集合存储元素特点:
        1.无序不可重复,但是存储的元素可以按照大小顺序排序(称为可排序集合)
        2.无序:这里的无序指的是存进去的顺序和取出来的顺序不同,并且没有下标
 */
public class TreeSetTest {
    public static void main(String[] args) {
        // 创建集合对象
        Set<String> set = new TreeSet<>();

        // 添加元素
        set.add("hello1");
        set.add("hello3");
        set.add("hello2");
        set.add("hello1");

        // 遍历
        for (String s : set) {
            System.out.println(s);  // hello1 hello2 hello3
        }
    }
}

Collection和Collections

java.util.Collection 集合接口
java.util.Collections 集合工具类,方便集合的操作

public class CollectionsTest {
    public static void main(String[] args) {
        // ArrayList集合不是线程安全的
        List<String> list = new ArrayList<>();
        // 变成线程安全的
        Collections.synchronizedList(list);
        list.add("asd");
        list.add("asf");
        list.add("asc");
        // 对元素进行排序
        Collections.sort(list);
        for (String s : list) {
            System.out.println(s);
        }

        // 对Set集合排序
        HashSet<String> set = new HashSet<>();
        set.add("asd");
        set.add("asf");
        set.add("abc");
        // 将Set集合转换成List集合
        ArrayList<String> myList = new ArrayList<>(set);
        Collections.sort(myList);
        for (String s : myList) {
            System.out.println(s);
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值