带你了解Java高级编程-----集合

Posted 符工爱奇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带你了解Java高级编程-----集合相关的知识,希望对你有一定的参考价值。

一、Java集合的整体介绍

  • Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的
    关联数组。很好的应对了数组array的弊端。
  • 使用的场景:
    android客户端 ②服务器 ③端数据库

二、Collection接口

Collection接口:单列数据,定义了存取一组对象的方法的集合。

  1. Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法 既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
  2. JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List) 实现。
  3. Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理; 但可以增加泛型,来实现Java 集合记住容器中对象的数据类型。

1、Collection接口方法

方法方法说明
add(Object obj)添加元素
addAll(Collection coll)添加整个集合
int size()获取有效元素的个数
void clear()清空集合
boolean isEmpty()是否是空集合
boolean contains(Object obj)是否包含某个元素,是通过元素的equals方法来判断是否是同一个对象
boolean containsAll(Collection c)是否包含某个元素, 也是调用元素的equals方法来拿两个集合的元素挨个比较。
boolean remove(Object obj)通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
boolean removeAll(Collection coll)删除集合中所有的此元素(取当前集合的差集)
boolean retainAll(Collection c)取两个集合中的交集(把交集的结果存在当前集合中,不影响c)
boolean equals(Object obj)判断集合是否相等
Object[] toArray()转成对象数组
hashCode()获取集合对象的哈希值
iterator()返回迭代器对象,用于集合遍历
package Collection接口;

import org.junit.Test;

import java.util.*;

public class CollectionTest {
    @Test
    public void test1(){
        Collection coll= new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Jerry"));
        Person p = new Person("Tom",15);
        coll.add(p);
        coll.add(true);

        // 1.contains(object obj):判断当前集合中是否包含obj
        // 在判断时会调用obj对象所在类的equals()
        boolean contains = coll.contains(123);
        System.out.println(contains);    //true
        System.out.println(coll.contains(new String("Jerry")));  //true
        System.out.println(coll.contains(new Person("Tom", 15)));  //false  ---> true 进行重写equals方法
        System.out.println(coll.contains(p));   //true

        //2.containsAll(Collection coll1) : 判断形参coll1中的所有元素是否都存在于当前集合中
        Collection coll1 = Arrays.asList(123,456);
        System.out.println(coll.containsAll(coll1));  //true
    }

    @Test
    public void test2(){
        //3.remove(Object obj):
        Collection coll= new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Jerry"));
        Person p = new Person("Tom",15);
        coll.add(p);
        coll.add(false);

        coll.remove(1234);
        System.out.println(coll);   //[123, 456, Jerry, Collection接口.For_Iterator.Person{name='Tom', age=15}, false]
        coll.remove(new Person("Tom",15));
        System.out.println(coll);   //[123, 456, Jerry, false]

        //4.removeAll(Collection coll1):从当前的集合中移除从从coll1中的所有元素
        Collection coll1 = Arrays.asList(123,456);
        coll.removeAll(coll1);
        System.out.println(coll);    //[Jerry, false]
    }

    @Test
    public void test3(){
       Collection coll = new ArrayList();
       coll.add(123);
       coll.add(456);
       coll.add(new String("Jerry"));
       Person p = new Person("Tom",15);
       coll.add(p);
       coll.add(false);

  /*     // 5.retainAll(Collection coll): 交集 :获取当前集合和从coll1集合的交集,并返回给当前集合
        Collection coll1 = Arrays.asList(123,456,789);
        coll.retainAll(coll1);
        System.out.println(coll);   //[123, 456]*/

        //6.equals(Object obj) :
        Collection coll1 = new ArrayList();   //Array是有序的,如果add的顺序不同,依然输出false
        coll1.add(123);
        coll1.add(456);
        coll1.add(new String("Jerry"));
        coll1.add(new Person("Tom",15));
        coll1.add(false);

        System.out.println(coll.equals(coll1));   //true
    }

    @Test
    public void test4(){
        Collection coll= new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Jerry"));
        Person p = new Person("Tom",15);
        coll.add(p);
        coll.add(false);

        // 7.hasCode() : 返回当前对象的哈希值
        System.out.println(hashCode());

        //8.集合 --> 数组 :toArray()
        Object[] arr = coll.toArray();
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        //拓展 :数组 --> 集合  【注意asList要用包装类,否则将视为一个元素】
        List<String> strings = Arrays.asList(new String[]{"AA", "BB", "CC", "DD"});
        System.out.println(strings);  //[AA, BB, CC, DD]

        List ints = Arrays.asList(new int[]{12, 34, 56});
        System.out.println(ints.size());  // 1
        List ints1 = Arrays.asList(new Integer[]{12, 34, 56});
        System.out.println(ints1.size()); // 3

        // 9.iterator(): 返回Iterator()接口的实例,用于遍历集合元素。放在IteratorTest.java 中测试
    }
}

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 boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

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



2、Collection子接口一:List

List:元素有序,可重复的集合。

鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组
List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。

  • JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。

List接口的主要方法:
【除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法】

方法方法说明
void add(int index, Object ele)在index位置插入ele元素
boolean addAll(int index, Collection eles)从index位置开始将eles中的所有元素添加进来
Object get(int index)获取指定index位置的元素
int indexOf(Object obj)返回obj在集合中首次出现的位置
int lastIndexOf(Object obj)返回obj在当前集合中末次出现的位置
Object remove(int index)移除指定index位置的元素,并返回此元素
Object set(int index, Object ele)设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex)返回从fromIndex到toIndex位置的子集合

①ArrayList ⭐

作为List 接口的主要实现类;线程不安全,效率高

  • ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
  • ArrayList 继承了 AbstractList ,并实现了 List 接口。

ArrayList 是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

package List接口;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 常用方法总结:
 * 增:add(Object obj)
 * 删:remove(int index) / remove(Object obj
 * 改:set(int index,Object ele)
 * 查:get(int index,Object ele)
 * 插:add(int index,Object obj)
 * 长度:size()
 */
public class ListTest {

    @Test
    public void test1(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(false);

        System.out.println(list);   //[123, 456, AA, For_Iterator.Person{name='Tom', age=12}, false]

        //1. void add (int index, Object ele) : 在index位置插入ele元素
        list.add(1,"BB");
        System.out.println(list);  //[123, BB, 456, AA, For_Iterator.Person{name='Tom', age=12}, false]
        List list1 = Arrays.asList(1,2,3);
        //list.addAll(list1);     //[123, BB, 456, AA, For_Iterator.Person{name='Tom', age=12}, false, 1, 2, 3]
        list.add(list1);          //[123, BB, 456, AA, For_Iterator.Person{name='Tom', age=12}, false, [1, 2, 3]]
        System.out.println(list);

        //2.Object get(int index) : 获取指定index位置的元素
        System.out.println(list.get(2));   // 456
    }

    @Test
    public void test2(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(false);

        //3.int index(Object obj) :  返回obj在集合中首次出现的位置
        int index = list.indexOf(123);
        System.out.println(index);   // 0
        //4.int lastIndexOf(Object obj) : 返回obj在集合中末次出现的位置
        int lastIndexOf = list.lastIndexOf(456);
        System.out.println(lastIndexOf);  // 1
        //5.Object remove(int index) : 移除指定index位置的元素,并返回此元素
        Object obj = list.remove(0);
        System.out.println(obj);   // 123
        System.out.println(list);  // [456, AA, For_Iterator.Person{name='Tom', age=12}, false]
        //6.Object set(int index,Object ele) : 设置指定index位置的元素ele
        list.set(0,123);
        System.out.println(list);  //[123, AA, For_Iterator.Person{name='Tom', age=12}, false]
        //7.list subList(int formIndex,int toIndex) : 返回从fromIndex到toIndex位置的左闭右开区间
        List subList = list.subList(2, 4);
        System.out.println(subList);  //[For_Iterator.Person{name='Tom', age=12}, false]
        System.out.println(list);   //[123, AA, For_Iterator.Person{name='Tom', age=12}, false]
    }
}

②LinkedList

对于频繁的插入、删除操作、使用此类的效率比ArrayList搞;底层使用的是双向列表存储

链表(Linkedlist)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表可分为单向链表双向链表

  • 一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
  • 一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。

    【使用方式于ArrayList基本相同,在此就不进行代码上的重复】

③Vector

作为List 接口古老实现类;线程安全,效率低;

面试题

  • 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。

3、Collection子接口二:Set

Set:元素无序,不可重复的集合。 储存无序的 ≠ 随机性,根据数据的hash值顺序进行添加

  • Set接口是Collection的子接口,set接口没有提供额外的方法。
  • Set集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
  • Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法。

①HashSet

作为Set接口的主要实现类 ;线程不安全 ,可以存储null值

LinkHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历

import org.junit.Test;

import java.util.*;

public class SetTest {
    /*
    Set接口 :1. 储存无序的 ≠ 随机性,根据数据的hash值顺序进行添加
             2. 不可重复的数据
     */
    @Test
    public void HashTest(){
        Set set = new HashSet();
        set.add(456);
        set.add(123);
        set.add(123);
        set.add("AA");
        set.add(new Person("Tom",12));
        //set.add(new User("Tom",12));
        set.add("cc");
        set.add(false);

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next() + " ");
            //AA cc Collection接口.For_Iterator.Person{name='Tom', age=12} false 456 123
        }
    }
    

    @Test
    public void LinkedHashTest(){
        /*
        LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据前后两个数据。
                优点 :对于频繁的遍历操作,LinkedHashSet的效率要高于HashSet
         */
        Set set = new LinkedHashSet();
        set.add(456);
        set.add(123);
        set.add(123);
        set.add("AA");
        set.add(new Person("Tom",12));
        set.add("cc");
     

以上是关于带你了解Java高级编程-----集合的主要内容,如果未能解决你的问题,请参考以下文章

Java8 Stream流如何操作集合,一文带你了解!

46道面试题带你了解高级Java面试,在线面试指南

46道面试题带你了解中高级Java面试,系列教学

一文带你了解Java8之Stream

一文带你了解Java8之Stream

一文带你了解Java8之Stream