JAVA基础复习-集合

4 篇文章 0 订阅

集合框架

集合框架:★★★★★,用于存储数据的容器。

 

对于集合容器,有很多种。因为每一个容器的自身特点不同,其实原理在于每个容器的内部数据结构不同。

集合容器在不断向上抽取过程中。出现了集合体系。

在使用一个体系时,原则:参阅顶层内容。建立底层对象。

------------------------------------------------------------

主要分为两大类:Collection和Map 
1:Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。

包括了List和Set

List:List接口通常表示一个列表(数组、队列、链表、栈等),其中的元素可以重复,常用实现类为ArrayList和LinkedList,另外还有不常用的Vector。另外,LinkedList还是实现了Queue接口,因此也可以作为队列使用。

List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。

Set: Set接口通常表示一个集合,其中的元素不允许重复(通过hashcode和equals函数保证),常用实现类有HashSet和TreeSet,HashSet是通过Map中的HashMap实现的,而TreeSet是通过Map中的TreeMap实现的。另外,TreeSet还实现了SortedSet接口,因此是有序的集合(集合中的元素要实现Comparable接口,并覆写Compartor函数才行)。

Set是一个不允许有重复元素的集合。

2:Map是一个映射接口,即key-value键值对。一个key对应一个value。

Map是一个映射接口,其中的每个元素都是一个key-value键值对,同样抽象类AbstractMap通过适配器模式实现了Map接口中的大部分函数,TreeMap、HashMap、WeakHashMap等实现类都通过继承AbstractMap来实现,另外,不常用的HashTable直接实现了Map接口,它和Vector都是JDK1.0就引入的集合类。

3:Iterator,它是遍历集合的工具,即我们通常通过Iterator迭代器来遍历集合。不能遍历Map,只用来遍历Collection。 
Collection的实现类都实现了iterator()函数,它返回一个Iterator对象,用来遍历集合,ListIterator则专门用来遍历List

4:Enumeration,它是JDK 1.0引入的抽象类。作用和Iterator一样,也是遍历集合;但它的功能比Iterator要少,它只能再Hashtable、Vector和Stack中使用。

5:Arrays和Collections。它们是操作数组、集合的两个工具类。

List本身是Collection接口的子接口,具备了Collection的所有方法。现在学习List体系特有的共性方法,查阅方法发现List的特有方法都有索引,这是该集合最大的特点。

 

List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。

    |--ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。

  • 实现了RandomAccess接口,提供了随机访问功能,实际上就是通过下标序号进行快速访问。
  • 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
  • 实现了Serializable接口,支持序列化,也就意味了ArrayList能够通过序列化传输。

1.ArrayList 本质实现方法是用数组!是非同步的!

2.初始化容量 = 10 ,最大容量不会超过 MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8!

3.indexOf和lastIndexOf 查找元素,若元素不存在,则返回-1!

4.当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 ”。

5.ArrayList的克隆函数,即是将全部元素克隆到一个数组中。

6.ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

7.从代码中可以看出,当容量不够时,每次增加元素,都要将原来的元素拷贝到一个新的数组中,非常之耗时,也因此建议在事先能确定元素数量的情况下,才使用ArrayList,否则建议使用LinkedList。

8.ArrayList的实现中大量地调用了Arrays.copyof()和System.arraycopy()方法。具体分析见第一篇参考文章

9.ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低。

10.在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,ArrayList中允许元素为null

    |--LinkedList:底层的数据结构是链表,线程不同步,增删元素的速度非常快。

LinkedList继承AbstractSequentialList,AbstractSequentialList 实现了get(int index)、set(int index, E element)、add(int index, E element) 和 remove(int index)这些函数。这些接口都是随机访问List的。

LinkedList 实现 List 接口,能对它进行队列操作。

LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。

LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。

LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

1:LinkedList的实现是基于双向循环链表,实现的 List和Deque 接口。实现所有可选的列表操作,并允许所有元素(包括null)。

2:LinkedList是非线程安全的,只在单线程下适合使用。

3:这个类的iterator和返回的迭代器listIterator方法是fail-fast ,要注意ConcurrentModificationException 。

4:LinkedList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了Cloneable接口,能被克隆。

5:在查找和删除某元素时,都分为该元素为null和不为null两种情况来处理,LinkedList中允许元素为null。

6:由于是基于列表的,LinkedList的没有扩容方法!默认加入元素是尾部自动扩容!

7:LinkedList还实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用,如peek 、push、pop等方法。

8:LinkedList是基于链表实现的,因此插入删除效率高,查找效率低!(因为查找需要遍历整个链表)
 

    |--Vector:底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢。

Vector实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。

Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。

Vector 实现Serializable接口,支持序列化。

1: Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;若使用默认构造函数,则Vector的默认容量大小是10。

2: 当Vector容量不足以容纳全部元素时,Vector的容量会增加。若容量增加系数 大于0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。

3: Vector的克隆函数,即是将全部元素克隆到一个数组中。

4: 很多方法都加入了synchronized同步语句,来保证线程安全。

5: 同样在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,Vector中也允许元素为null。

6: 遍历Vector,使用索引的随机访问方式最快,使用迭代器最慢。

7: Vector很多地方都与ArrayList实现大同小异,现在已经基本不再使用。
 

可变长度数组的原理:(扩容)

当元素超出数组长度,会产生一个新数组,将原数组的数据复制到新数组中,再将新的元素添加到新数组中。

ArrayList:是按照原数组的50%延长。构造一个初始容量为 10 的空列表。

Vector:是按照原数组的100%延长。

------------------------------------------------------------

--< java.util >-- Set接口

数据结构:数据的存储方式;

Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器

    |--HashSet:底层数据结构是哈希表,线程是不同步的无序,高效;

        HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。

        当元素的hashCode值相同时,才继续判断元素的equals是否为true。

        如果为true,那么视为相同元素,不存。如果为false,那么存储。

        如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。

|--LinkedHashSet:有序,hashset的子类。

    |--TreeSet:对Set集合中的元素的进行指定顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。

1.概述 
HashSet实现Set接口,那么它也是一个不包含重复元素的一个无序的集合,允许使用null,有且仅有一个元素为null!

HashSet也是一个非同步的方法,如果要在多个线程中使用,要注意进行同步封装!

Set s = Collections.synchronizedSet(new HashSet(...));
1
HashSet通过iterator()返回的迭代器是fail-fast的。
 

对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。

对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。

 

------------------------------------------------------------

Map集合:

|--Hashtable:底层是哈希表数据结构,是线程同步的。不可以存储null键,null值。
 

|--HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了Hashtable.

1:HashMap是通过哈希表来存储一个key-value的键值对,每个key对应一个value,允许key和value为null! hash 
2:HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。HashMap的容量不足的时候,可以自动扩容resize(),但是最大容量为MAXIMUM_CAPACITY==2^30!

3:put和get都是分为null和非null进行判断!

4:resize非常耗时的操作,因此,我们在用HashMap的时,最好能提前预估下HashMap中元素的个数,这样有助于提高HashMap的性能。 
5:求hash值和索引值的方法,这两个方法便是HashMap设计的最为核心的部分,二者结合能保证哈希表中的元素尽可能均匀地散列。

|--TreeMap:底层是二叉树结构,可以对map集合中的键进行指定顺序的排序。
1、TreeMap是根据key进行排序的,它的排序和定位需要依赖比较器或覆写Comparable接口,也因此不需要key覆写hashCode方法和equals方法,就可以排除掉重复的key,而HashMap的key则需要通过覆写hashCode方法和equals方法来确保没有重复的key。

2、TreeMap的查询、插入、删除效率均没有HashMap高,一般只有要对key排序时才使用TreeMap。

3、TreeMap的key不能为null,而HashMap的key可以为null。

4、TreeMap不是同步的。如果多个线程同时访问一个映射,并且其中至少一个线程从结构上修改了该映射,则其必须 外部同步。
 

(1):AbstractMap是一个抽象类, 继承Map,实现了Map的大部分API,它的作用Map的实现类继承它,可以减少重复编码! 
(2):SortedMap是一个接口 继承Map,自己也封装一下方法,SortedMap中的内容是排序的键值对,排序的方法是通过比较器(Comparator)。SortedMap的排序方式有两种:自然排序 或者 用户指定比较器。 
(3):ConcurrentMap是一个接口,并且继承Map接口,在java.util.concurrent包下! 
(4):HashMap 继承于AbstractMap,HashMap的内容是“键值对,但不保证次序”! 
(5): TreeMap 继承于AbstractMap,且实现了NavigableMap接口;因此,TreeMap中的内容是键值对,有序的键值对!

(6):ConcurrentHashMap继承AbstractMap实现ConcurrentMap,是一个并发的哈希表!此类与 Hashtable 相似,但与 HashMap 不同,它不 允许将 null 用作键或值。线程安全,但是实现方法和Hashtable完全不同(并发情况可以使用) 。

(7):Dictionary是一个抽象类(数据字典),HashTable继承Dictionary并实现Map接口,也是键值对,但不保证次序!Hashtable是线程安全的,而且它支持通过Enumeration去遍历。(现在使用很少,并发操作效率太低)
 

Map集合存储和Collection有着很大不同:

Collection一次存一个元素;Map一次存一对元素。

Collection是单列集合;Map是双列集合。

Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。

特点:要保证map集合中键的唯一性。

 

5,想要获取map中的所有元素:

    原理:map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,可以使用迭代器了。之所以转成set,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。

  • 把map集合转成set的方法:

    Set keySet();

    Set entrySet();//取的是键和值的映射关系。

Entry就是Map接口中的内部接口;

为什么要定义在map内部呢?entry是访问键值关系的入口,是map的入口,访问的是map中的键值对。

---------------------------------------------------------

取出map集合中所有元素的方式一:keySet()方法。

可以将map集合中的键都取出存放到set集合中。对set集合进行迭代。迭代完成,再通过get方法对获取到的键进行值的获取。

        Set keySet = map.keySet();

        Iterator it = keySet.iterator();

        while(it.hasNext()) {

            Object key = it.next();

            Object value = map.get(key);

            System.out.println(key+":"+value);

        }

--------------------------------------------------------

取出map集合中所有元素的方式二:entrySet()方法。

Set entrySet = map.entrySet();

        Iterator it = entrySet.iterator();

        while(it.hasNext()) {

            Map.Entry me = (Map.Entry)it.next();

            System.out.println(me.getKey()+"::::"+me.getValue());

        }

--------------------------------------------------------

 

将非同步集合转成同步集合的方法:Collections中的 XXX synchronizedXXX(XXX);

List synchronizedList(list);

Map synchronizedMap(map);

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {

return new SynchronizedMap<K,V>(m);

}

原理:定义一个类,将集合所有的方法加同一把锁后返回。

List list = Collections.synchronizedList(new ArrayList());

Map<String,String> synmap = Collections.synchronizedMap(map);

 

Collection 和 Collections的区别:

Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。

Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。

-------------------------------------------------------

自动拆装箱:java中数据类型分为两种 : 基本数据类型 引用数据类型(对象)

在 java程序中所有的数据都需要当做对象来处理,针对8种基本数据类型提供了包装类,如下:

int --> Integer

byte --> Byte

short --> Short

long --> Long

char --> Character

double --> Double

float --> Float

boolean --> Boolean

 

jdk5以前基本数据类型和包装类之间需要互转:

基本---引用 Integer x = new Integer(x);

引用---基本 int num = x.intValue();

1)、Integer x = 1; x = x + 1; 经历了什么过程?装箱 à 拆箱 à 装箱

2)、为了优化,虚拟机为包装类提供了缓冲池,Integer池的大小 -128~127 一个字节的大小

3)、String池:Java为了优化字符串操作 提供了一个缓冲池;

----------------------------------------------------------

泛型:jdk1.5版本以后出现的一个安全机制。表现格式:< >

好处:

1:将运行时期的问题ClassCastException问题转换成了编译失败,体现在编译时期,程序员就可以解决问题。

2:避免了强制转换的麻烦。

 

泛型中的通配符:可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

-------------------------------------------------------------------------------------------------------------------------------

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值