Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组,而内存中对数据进行存储和管理的容器组,集合。

但数组有一定的弊端:

    ①数组的长度不可变

    ②数组存储的数据类型比较单一

    ③数组的API较少,没有插入,删除等方法

    ④数组存储元素是有序的,对于无序的无能为力

而集合相对于数组的这些弊端做了优化:

    ①集合的长度可变

    ②集合可以存储任意数据类型,因为默认存储的是Object类型

    ③ 集合中的API比较丰富,有增,删,改,查,插,大小等操作

    ④集合底层存储数据的结构较多(比如,数组,链表,二叉树)

Collection集合与数组间的转换

    集合> 数组 : toArray()

    数组> 集合 : Arrays.asList(T...t)

注意:

List:使用Collection集合存储数据,要求数据所在的类满足:必须重写equals方法

Set:存储元素所在类的要求:必须重写hashCodeequals

TreeSet:自然排序的情况下该对象的类必须实现 Comparable 接口,且重写compareTo()方法与equals()方法

说明:Arrays.asList() 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList()  返回值是一个固定长度的 List 集合

Java 集合可分为 Collection Map 两种体系

Collection常用接口:

    Set:元素无序、不可重复的集合

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

Map接口:具有映射关系“key-value对”的集合


Collection接口

|----Collection

     |----List   

             |----ArrayList(主要实现类):底层是用数组实现的,线程不安全的,比Vector 效率高。增删慢,查找快。

             |----Vector:底层是用数组实现的,线程安全的,效率低

             |----LinkedList:底层是用链表实现的,增删快,查找慢

    |----Set : 存储的元素是无序的且不可重复的

            |----HashSet(主要实现类):底层是创建了hashMap对象

            |----LinkedHashSet:继承了HashSet,底层实现原理和HashSet一样。

                        但是LinkedHashSet可以按照元素添加的顺序进行遍历。因为LinkedHashSet

                        底层维护了一对指针(链表)用来记录元素添加的顺序。

            |----TreeSet:可以对对象中的属性进行排序

Collection 接口是 ListSet Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List Queue 集合。

注:JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:SetList)实现。

Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 JDK 5.0 增加了泛型以后,Java 集合可以记住容器中对象的数据类型

遍历Collection的两种方式: Iteratorforeach循环

    增强for循环 :只能用于数组和集合

              Iterator 接口 用来遍历集合中的元素

增强for循环:(foreach循环)

    格式:

    for(元素的类型 临时变量 : 数组、集合的对象名){

    }

Collection接口之List接口

List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引

常用实现类主要区别:

    |----ArrayList(主要实现类):底层是用数组实现的,线程不安全的,比Vector效率高。增删慢 查找快

    |----Vector:底层是用数组实现的,线程安全的,效率低

    |----LinkedList:底层是用链表实现的,增删快查找慢

ArrayList底层是用数组存储数据的,线程不安全的

②构造器

        a)new ArrayList(); //默认创建一个长度为10的数组

        b)new ArrayList(int initialCapacity) //创建一个长度为initalCapcity的数组

如何向ArrayList中添加数据?ArrayList的底层实现?

创建一个ArrayList空参的对象,底层会创建一个长度为10的数组。当我们向集合中放第11个元素的时候会进行扩容。扩容为原来数组长度的1.5倍。再把原来数组中的内容copy到新的数组中。如果我们知道数组元素的个数建议使用new ArrayList(int initialCapacit)

注意List的这两个方法:

        remove(int index)

        remove(Object obj)

                ArrayList al = new ArrayList();
		al.add("aaa");
		al.add("bbb");
		al.add(1);
		
		al.remove(1); //删除当前集合对应的索引值上的元素。(bbb)
		al.remove(new Integer(1)); //删除当前集合中对应的元素(1)
		
		System.out.println(al);

Collection接口之set接口

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

常用实现类

|----HashSet(主要实现类):底层是创建了hashMap对象  

    |----LinkedHashSet:继承了HashSet,底层实现原理和HashSet一样。

            但是LinkedHashSet可以安照元素添加的顺序进行遍历。因为LinkedHashSet

           底层维护了一对指针(链表)用来记录元素添加的顺序。 

    |----TreeSet:可以对对象中的属性进行排序


Set存储的数据特点:无序的且不可重复的

 无序的:指的不是随机性,根据自定义类中的hashCode方法返回的值来决定在数组中存放的位置

 不可重复的:指的是调用自定义类中的equals方法进行比较,如果返回的是true认为两个对象相同,反之则不相同。

如何向HashSet中添加数据?HashSet的底层实现原理?

当我们向HashSet中存放数据a时,会先根据该对象中的hashCode方法返回的值决定存放在数组中的位置。如果存放的位置没有其它元素那么直接存放。如果存放的位置已经有了其它元素b时,会调用aequals方法进行内容的比较。如果返回的是true那么认为两个元素是相同的则不能再次存放。如果返回的是false那么认为两个元素不同。以链表的形式进行存放。

注:

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

存储元素所在类的要求:求必须重写hashCodeequals

Collection接口之set接口之TreeSet

TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。

自然排序:

自然排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序排列

如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。

实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。

因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象

对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 方法比较返回值

当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0

定制排序

TreeSet的自然排序是根据集合元素的大小,进行元素升序排列。如果需要定制排序,比如降序排列,可通过Comparator接口的帮助。需要重写compare(T o1,T o2)方法。

利用int compare(T o1,T o2)方法,比较o1o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2

要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。

此时,仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。

使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0

TreeSet可以对元素进行排序 要求:元素的类须必须一致

排序有两种方式:自然排序  vs 定制排序

   1自然排序

   ①实现Comparable接口

   ②重写compareTo方法

   ③按照属性进行排序

   ④添加元素

   2 定制排序

   ①创建一个Comparator实现类的对象

   ②将Comparator对象传入TreeSet的构造器中

   ③重写compare方法

   ④按照属性进行排序

   ⑤添加元素

自然排序的情况下该对象的类必须实现 Comparable 接口,且重写compareTo()方法与equals()方法

Map接口 


 |----Map

      |----HashMap(主要实现类) : 底层是用数组来存放数据的(数组 +  链表),线程不安全的HashMap中可以存放null

              |----LinkedHashMap:继承了HashMap底层实现和HashMap一样。

                           LinkedHashMap可以安照添加元素的顺序进行遍历。因为底层维护了一张链表用来记录存放的元素的顺序。

   |----TreeMap:用来对Key中的元素进行排序。 

   |----Hashtable : 底层是用数组来存放数据的(数组 +  链表),线程安全的

                              Hashtable中不可以存放null

              |----Properties : 用来读取配置文件中的内容。读取的内容都是字符串。

                                       keyvalue都是String类型

HashMapHashtable对比?

HashMap: 底层是用数组来存放数据的(数组 +  链表),线程不安全的HashMap可以存放null

Hashtable: 底层是用数组来存放数据的(数组 +  链表),线程安全的

Hashtable中不可以存放null

HashMap的底层实现原理?

当我们向HashMap中存放一个元素(k1,v1),首先会根据k1hashCode方法来决定在数组中存放的位置。如果当前位置没有其它元素则直接存放。如果当前位置有其它元素(k2,v2),会调用k1equals方法和k2进行对比。如果返回值是true则代表内容相同,那么v1会覆盖v2.如果返回的是false则以链表的形式进行存放。当链表的长度为8时,链表将会改成红黑树进行存放。

Map之TreeMap

TreeMap Key 的排序:

自然排序:

TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException

定制排序:

创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map Key 实现 Comparable 接口

结构说明:

new HashMap() : 创建一个空参的构造器。那么底层默认创建一个长度为16加载因子为0.75。当我们向集合中添加元素超过12时会进行扩容,扩容为原来大小的2倍。

 

HashSet的底层是:HashMap(将数据存放在Key)

LinkedHashSet的底层是:LinkedHashMap(将数据存放在Key)

TreeSet的底层是 : TreeMap(将数据存放在Key)



Iterator迭代器接口

terator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。

所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。

Iterator 仅用于遍历集合Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合

常用方法:

    hasNext() : 是否还有下一个元素

    next(): ①指针下移  ②获取元素

注:

    Iterator常见的两种错误:

                Collection coll = new ArrayList();
		coll.add("aaa");
		coll.add(123); // 装箱
		coll.add(456);
		//错误 方式一  :coll.iterator();因为每次循环底层都创建了一个新的对象,如下图
		while(coll.iterator().hasNext()){
			System.out.println(coll.iterator().next());
		}
		
		Iterator iterator = coll.iterator();
		//错误方式二 : 因为每next一次指针就会下移,一旦没有元素就会报错
		while(iterator.next() != null){
			System.out.println(iterator.next());
		}

Collections工具类

注意Collection集合和Collections工具类的区别:

Collections是工具类:

Collections 是一个操作 SetList Map 等集合的工具类,Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法

排序操作:(均为static方法

l reverse(List):反转 List 中元素的顺序

l shuffle(List):对 List 集合元素进行随机排序

l sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序

l sort(ListComparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序

l swap(Listintint):将指定 list 集合中的 i 处元素和 j 处元素进行交换

 

查找、替换

l Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素

l Object max(CollectionComparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素

l Object min(Collection)

l Object min(CollectionComparator)

l int frequency(CollectionObject):返回指定集合中指定元素的出现次数

l void copy(List dest,List src):将src中的内容复制到dest

l boolean replaceAll(List listObject oldValObject newVal):使用新值替换 List 对象的所有旧值

注:

操作数组的工具类:Arrays

操作集合的工具类:Collections

再次总结

底层实现:

ListArrayList的底层实现?

 *    创建一个ArrayList空参的对象,底层会创建一个长度为10的数组。当我们向集合中放第11个元素的时候会进行扩容。

 *    扩容为原来数组长度的1.5倍。再把原来数组中的内容copy到新的数组中。

 *    如果我们知道数组元素的个数建议使用new ArrayList(int initialCapacit)

SetHashSet的底层实现原理?

 *   当我们向HashSet中存放数据a时,会先根据该对象中的hashCode方法返回的值决定存放在数组中的位置。

 *  如果存放的位置没有其它元素那么直接存放。如果存放的位置已经有了其它元素b时,会调用aequals方法进行内容的比较。

 *  如果返回的是true那么认为两个元素是相同的则不能再次存放。如果返回的是false那么认为两个元素不同。以链表的形式进行

 *  存放。

MapHashMap的底层实现原理?

当我们向HashMap中存放一个元素(k1,v1),首先会根据k1hashCode方法来决定在数组中存放的位置。如果当前位置没有其它元素则直接存放。如果当前位置有其它元素(k2,v2),会调用k1equals方法和k2进行对比。如果返回值是true则代表内容相同,那么v1会覆盖v2.如果返回的是false则以链表的形式进行存放。当链表的长度为8时,链表将会改成红黑树进行存放。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐