java集合----collection接口

java集合----collection接口


引入

面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。 而Java 集合就像一种容器,可以动态地 把多个对象的引用放入容器中。另外一方面,使用 Array 存储对象方面具有 一些弊端 。
比如:

  • 数组初始化以后,长度就不可变了,不便于扩展;

  • 数组中提供的属性和方法少,不便于进行添加、删除、插入等操作, 且效率 不 高。
    同时无法直接获取存储元素的个数;

  • 数组存储的数据是有序的、可以重复的。 存储数据的特点单一;

在java中集合框架主要分为Collection和Map两种体系.
在这里插入图片描述
这里主要讲解有关于Collection的一些操作。

Collection接口

Collection 接口是 List 、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
这里可以看看在Java8中关于Collection接口的介绍:
在这里插入图片描述
翻译为:集合层次结构中的根接口。集合表示一组对象,称为其元素。有些集合允许复制元素,有些则不允许。有些是有序的,有些是无序的。JDK没有提供该接口的任何直接实现:它提供了更具体的子接口(如SetList)的实现。此接口通常用于在需要最大通用性的地方传递和操作集合。

Collection接口的方法

  • add(T e): 添加一个元素(这里T表示泛型的意思)
    例子:
    这里代码只给出了测试单元,可以看见Colletion接口add方法既可以添加int型,String型,还可以是个对象(这里Person是我创建的一个对象)
public void test1() {
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        obj.add(new Person("LC",20));
        Iterator iterator = obj.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

结果:
在这里插入图片描述

  • addAll(Collection c ): 将指定的对象的集合加到当前集合中
    例如:
	@Test
    public void test1() {
        Collection obj = new ArrayList();
        //将数组元素转化为list列表
        Collection obj2 = Arrays.asList("123",132);
        obj.add(123);
        obj.add("AA");
        obj.add(new Person("LC",20));
        obj.addAll(obj2);
        Iterator iterator = obj.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

结果:
在这里插入图片描述

  • int size() : 获取有效元素的个数

例如:这里使用size方法去返回obj中的元素个数

@Test
public void test2(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        System.out.println(obj.size());
    }

结果:在这里插入图片描述
-void clear():清空集合

例如:使用clear方法后,我们再看看obj的size是多少

@Test
public void test2(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        obj.clear();
        System.out.println(obj.size());
    }

结果,毋庸置疑的是0:
在这里插入图片描述

  • boolean isEmpty(): 判断是否是空集合
    例如:
 	@Test
    public void test2(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        boolean empty = obj.isEmpty();
        System.out.println(empty);
    }

结果:
在这里插入图片描述

  • boolean contains(Object obj): 是通过元素的 equals 方法来判断是否是同一个对象
    例如:
	@Test
    public void test2(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        boolean contains = obj.contains(123);
        System.out.println(contains);
    }

结果:
在这里插入图片描述

  • boolean containsAll(Collection c) 也是调用元素的 equals 方法来比较的 。拿两个集合的元素挨个比较 。
    例如:
	@Test
    public void test2(){
        Collection obj = new ArrayList();
        Collection obj2 =  Arrays.asList(123);
        obj.add(123);
        obj.add("AA");
        boolean containsAll = obj.containsAll(obj2);
        System.out.println(containsAll);
    }

结果:
在这里插入图片描述

  • boolean remove(Object obj) 通过 元素的 equals 方法判断是否是要删除的那个元素 。 只会删除找到的第一个元素。
    例如:
	@Test
    public void test3(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add(123);
        obj.add("AA");
        obj.add("BB");
        obj.remove(123);
        Iterator iterator = obj.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

结果:
可见并没有把相同的元素全部删去,只删除第一个相同的元素。
在这里插入图片描述

  • boolean removeAll(Collection coll 取当前集合的差集

例如:

@Test
    public void test3(){
        Collection obj = new ArrayList();
        Collection obj2 = Arrays.asList(123,"AA");
        obj.add(123);
        obj.add(123);
        obj.add("AA");
        obj.add("BB");
        obj.removeAll(obj2);
        Iterator iterator = obj.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

结果:
在这里插入图片描述

  • boolean equals(Object obj) :集合是否相等
  • 这里我们来看一个例子,我用一个Person类的一个对象,加到obj中,obj2用Arrays的方法把数组转化为List,其中元素也是Person类的一个对象。

person类如下所示:

package com.Collection;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

//   @Override
//    public boolean equals(Object o) {
//        System.out.println("Person equals()....");
//        if (this == o) return true;
//        if (o == null || getClass() != o.getClass()) return false;
//
//        Person person = (Person) o;
//
//        if (age != person.age) return false;
//        return name != null ? name.equals(person.name) : person.name == null;
//    }
//
//    @Override
//    public int hashCode() {
//        int result = name != null ? name.hashCode() : 0;
//        result = 31 * result + age;
//        return result;
//    }
}

测试单元如下:

	@Test
    public void test5(){
        Collection obj = new ArrayList();
        obj.add(new Person("LC",12));
        Collection obj2 = Arrays.asList(new Person("LC",12));
        boolean equals = obj.equals(obj2);
        System.out.println(equals);
    }

看看结果(Person类中的注释没打开):
在这里插入图片描述
现在我在Person类打开了注释,再看看结果:

在这里插入图片描述
解释:第一次判断结果为false,是因为在执行equals方法的时候,调用的是Object里面的equals方法
在这里插入图片描述
因为地址值不同,所以返回false.
而第二种是自己重写了equals方法,没有按照地址值判断,所以返回true

  • Object[] toArray() 转成对象数组
    例子:
 @Test
    public void test6(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        obj.add(new Person("LC",12));
        Object[] objects = obj.toArray();
        System.out.println(objects[1]);
    }

结果:
在这里插入图片描述

  • hashCode(): 获取集合对象的哈希值
    例子:
	@Test
    public void test6(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        obj.add(new Person("LC",12));
        System.out.println(obj.hashCode());
    }

结果:
在这里插入图片描述

  • iterator() 返回迭代器对象,用于集合遍历

其实在试前面的方法的时候已经用到了。
例子:

	@Test
    public void test6(){
        Collection obj = new ArrayList();
        obj.add(123);
        obj.add("AA");
        obj.add(new Person("LC",12));
        Iterator iterator = obj.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

结果:
在这里插入图片描述
注意: Collection obj = new Collection(); //错误,因为接口不能实例化
Collection接口虽然不能直接被使用, 但提供了集合以及集合元素的方法且Set接口和List接口都可以调用Collection接口的方法。

Collection的子接口(一)—List接口

鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组。
通过源代码可以发现List接口继承与Collecion接口
在这里插入图片描述
List特点:

  • List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  • JDK中List接口的实现类常用的有:ArrayList、LinkedList和Vector

List类的一些方法

List 除了从 Collection 集合继承的方法外, List 集合里添加了一些根据索引来操作集合元素的方法,下面就来了解一下它的一些方法.
这里我用ArrayList来实现List接口中的一些方法

  • void add( int index, Object o) 在 index 位置插入o元素.
 @Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        list.add("CC");
        list.add("DD");
        System.out.println(list);
        list.add(1,"RR");
        System.out.println(list);
    }

结果:
在这里插入图片描述

  • boolean addAll(int index, Collection eles) 从 index 位置开始将 eles 中的所有元素添加进来

例子:

@Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        list.add("CC");
        list.add("DD");
        list.addAll(1, Arrays.asList("123","456"));
        System.out.println(list);
    }

结果:在这里插入图片描述

  • Object get( int index): 获取指定 index 位置的元素

例子:

@Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        list.add("CC");
        list.add("DD");
        Object o = list.get(1);
        System.out.println(o);
    }

结果:
在这里插入图片描述

  • int indexOf(Object obj):返回obj在集合中首次出现的位置,没找到返回-1

例子:

@Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        list.add("BB");
        list.add("BB");
        int num1 = list.indexOf("BB");
        int num2 = list.indexOf("Baa");
        System.out.println(num1+"    "+num2);
    }

结果:
在这里插入图片描述

  • int lastlndexOf(Object obj):返回obj在当前集合中末次出现的位置,没找到返回-1

例子:

@Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        list.add("BB");
        list.add("BB");
        int num1 = list.lastIndexOf("BB");
        int num2 = list.lastIndexOf("Baa");
        System.out.println(num1+"    "+num2);
    }

结果:
在这里插入图片描述

  • Object remove(int index):移除指定index位置的元素,并返回此元素
    例子:
@Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        Object o = list.remove(1);
        System.out.println(o);
    }

结果:
在这里插入图片描述

  • Object set(int index,Object ele):设置指定index位置的元素为ele,并返回之前在index位置的值

例子:

@Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        Object o = list.set(1, "CC");
        System.out.println(o);
        System.out.println(list);
    }

结果:
在这里插入图片描述

  • List subList(int fromlndex,int tolndex):返回从fromlndex到tolndex位置的子集合

例子:

@Test
    public void test(){
        ArrayList list  = new ArrayList();
        list.add("AA");
        list.add("BB");
        list.add("CC");
        list.add("DD");
        List list1 = list.subList(1, 3);
        System.out.println(list1);
    }

结果:
在这里插入图片描述

List实现类之一----ArrayList

看ArrayList的源码发现,ArrayList继承于AbstractList, 实现了List、RandomAccess, Cloneable, java.io.Serializable。
在这里插入图片描述
ArrayList 是 List 接口的典型 实现类、主要实现类。本质上, ArrayList 是对象引用的 一个变长数组

ArrayList的构造方法

在这里插入图片描述

在这里插入图片描述
从构造方法中我们可以看见,默认情况下,elementData是一个大小为0的空数组,当我们指定了初始大小的时候,elementData的初始大小就变成了我们所指定的初始大小了。

List实现类之二—LinkedList

LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量:
prev变量: 记录前一个元素的位置
next变量: 记录下一个元素的位置
在这里插入图片描述
对于 频繁的插入或删除元素 的操作,建议 使用 LinkedList 类,效率 较高

这是它的源码:
在这里插入图片描述

LinkedList的一些方法

除了List中的一些方法,LinkedList还有一些方法。

  • void addFirst(Object obj)
  • void addLast(Object obj)
  • Object getFirst()
  • Object getLast()
  • Object removeFirst()
  • Object removeLast()
    就看一个例子,来了解下这些方法:
@Test
        public void test3(){
            LinkedList linkedList = new LinkedList();
            linkedList.add("AA");
            linkedList.add("BB");
            linkedList.add("CC");
            linkedList.add("DD");
            linkedList.add("EE");
            linkedList.add("FF");
            linkedList.addFirst("begin");
            linkedList.addLast("last");
            System.out.println(linkedList);
            System.out.println("***************");
            Object first = linkedList.getFirst();
            Object last = linkedList.getLast();
            System.out.println(first);
            System.out.println(last);
            Object o = linkedList.removeFirst();
            Object o1 = linkedList.removeLast();
            System.out.println(linkedList);
        }

结果:
在这里插入图片描述

Vector

Vector是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。
在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。

Vector的一些方法
  • void addElement (Object obj

  • void insertElementAt (Object obj,int index)

  • void setElementAt (Object obj,int index)

  • void removeElement (Object obj

  • void removeAllElements

看一个例子:

public  void test4(){
            Vector vector = new Vector();
            vector.addElement("aaa");
            vector.addElement("aaa");
            vector.addElement("bbb");
            vector.insertElementAt("ccc",1);
            System.out.println(vector);
            vector.setElementAt("ddd",1);
            System.out.println(vector);
            vector.removeElement("aaa");
            System.out.println(vector);
            vector.removeAllElements();
            System.out.println("现在还剩下元素"+vector);

        }

结果:
在这里插入图片描述

一道关于ArrayList/LinkedList/Vector的面试题

问题:请问ArrayList/LinkedList/Vector 的 异同 谈谈你的理解? ArrayList 底层
是什么?扩容机制? Vector 和 ArrayList 的最大区别。

ArrayList 和 LinkedList 的 异同二者都线程不安全,相对线程安全的Vector ,执行效率高。
此外,ArrayList 是实现了基于动态数组的数据结构, LinkedList 基于链表的数据结构。对于
随机访问 get 和 set ArrayList 觉得优于 LinkedList ,因为 LinkedList 要移动指针。对于新增
和删除 操作 add( 特指 插入 和 remove LinkedList 比较占优势,因为 ArrayList 要移动数据。

ArrayList 和 Vector 的区别Vector和 ArrayList 几乎是完全相同的 唯一的区别在于 Vector 是同步类 ( synchronized),属于强同步类。因此开销就比 ArrayList 要大,访问要慢。正常情况下 大多数的 Java 程序员使用ArrayList 而不是 Vector, 因为同步完全可以由程序员自己来控制。 Vector 每次扩容请求其大小的 2 倍空间,而 ArrayList 是 1.5 倍。 Vector 还有一个子 类 Stack

Collection的子接口(二)—set接口

概述

  1. Set 接口 是 Collection 的子接口, set 接口没有 提供额外 的方法

  2. Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个

  3. Set 集合中,则添加操作失败。

  4. Set 判断两个对象是否相同不是使用 == 运算符,而是 根据 equals() 方法

Set实现类之一— Hashset

概述

  1. HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
  2. HashSet 按 Hash 算法来存储集合中的元素,因此具有很好 的 存取、查找、删除性能。
  3. HashSet具有以下特点:
    不能保证元素的排列顺序
    HashSet不是线程安全的
    集合元素可以是null
  4. HashSet 集合判断两个元素相等的标准:两个对象通过hashCode()方法比较相等,并且两个对象的equals()方法返回值也相等。
  5. 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。

Set的无序性和不可重复型
例子(这里的Person类是我自己创建的):

@Test
    public void test(){
        HashSet set = new HashSet();
        set.add("AA");
        set.add("BB");
        set.add("CC");
        set.add("CC");
        set.add(new Person("LC",20));
        set.add(new Person("LC",20));
        System.out.println(set);
    }

猜猜结果是多少?
发现这里把两个Person类的对象都输出来了
在这里插入图片描述
如果在重写equals()和hashcode()方法,那会怎么样呢

    @Override
    public boolean equals(Object o) {
        System.out.println("Person equals()....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

此时输出就只有一个Person对象了
在这里插入图片描述

向 HashSet 中添加元素的过程:

  1. 当向 HashSet 集合中存入一个元素时 ,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值 ,通过某种散列函数决定该对象在 HashSet 底层数组中 的 存储位置 。 这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布该散列函数设计的越好(这就和数组结构有点关系了)

  2. 如果两个元素的 hashCode() 值相等,会再继续调用 equals 方法。如果 equals 方法结果为 true 添加 失败。如果 为 false 那么会保存该元素 但是该数组的位置已经有元素了那么会通过链表的方式,继续链接 。

  3. 如果 两个元素的 equals() 方法返回 true ,但它们的 hashCode () 返回值不相等, hashSet 将会把它们存储在不同的位置,但依然可以添加 成功。

Set实现类之二—LinkedHashset

概述

  1. LinkedHashSet 是HashSet的子类
  2. LinkedHashSet 根据元素的 hashCode值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
  3. LinkedHashSet插入性能略低于HashSet,但在迭代访问Set里的全部元素时有很好的性能。
  4. LinkedHashSet不允许集合元素重复。

看一个关于LinkedHashset的例子

@Test
    public void test(){
        LinkedHashSet set = new LinkedHashSet();
        set.add("AA");
        set.add("BB");
        set.add("CC");
        set.add(new Person("LC",20));
        set.add("a");
        set.add("b");
        System.out.println(set);
    }

输出结果:
可以发现它的输出结果顺序就是添加的顺序。
在这里插入图片描述
在Linkedhashset的底层结构
在这里插入图片描述

Set实现类之三—Treeset

概要:

  • TreeSet 是 SortedSet 接口的实现类, TreeSet 可以确保集合元素处于排序 状态。

  • TreeSet 底层使用 红黑树 结构存储数据

  • TreeSet 两种排序方法: 自然排序 和 定制排序 。默认情况下, TreeSet 采用自然排序。
    自然排序:TreeSet 会调用集合元素的compare To(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列
    定制排序:通过 Comparator 接口来实现。 需要重写 compare(T o1,T o2) 方法

例子:

 @Test
    public void test2(){
        TreeSet treeSet = new TreeSet();
        treeSet.add(1);
        treeSet.add(3);
        treeSet.add(5);
        treeSet.add(2);
        treeSet.add(4);
        treeSet.add(6);
        Object first = treeSet.first();
        Object last = treeSet.last();
        Object o = treeSet.higher(5);
        System.out.println(treeSet);
        System.out.println(first);
        System.out.println(last);
        System.out.println(o);
    }

结果:
在这里插入图片描述

如果有错误,请指出 😄

喜欢的话,就点个赞吧!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值