2018-03-28

集合框架

集合

数组和集合的区别?

A:长度区别
数组的长度固定
集合长度可变
B:内容不同
数组内存是同一种类型的元素
而集合可以储存不同类型的元素
C:元素的数据类型问题
数组可以储存基本类型,也可以储存引用类型
集合只能储存引用类型(原因是因为集合是泛型类,会有边界擦除)

集合体系

Collection和Collections的区别

  • Collection:是单列集合的顶层接口,有子接口List和Set
  • Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法

集合小问题

(1) Map和Collection的区别?
A:Map 是由键值对组成的集合,Map的键(key)是唯一的,值(value)可以重复。
B:Collection 是有单列数据组成的集合,它的儿子List是可以重复的,Set是唯一的。

(2) HashMap和Hashtable的区别?
HashMap:线程不安全,效率高。允许null键和值。
Hashtable:线程安全,效率低。不允许null键和值。
(3)List,Set,map等接口是否都继承自Map接口
List,Set不是继承自Map接口,他们继承自Collection接口
Map接口本身就是一个顶层接口。

(4)在集合中的数据结构问题
ArrayXxx:底层数据结构是数组。查询快,增删慢。
LinkedXxx:底层数据结构是链表。查询慢,增删快。
HashXxx:底层数据结构是哈希表。跟两个有关。hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种排序方式。Comparable接口和Comparator接口

Map(双列集合)

  • 概念:Map是一个键值对形式的集合。它的元素都是有键和值组成。
    (双列 底层结构是针对键有效,跟值无关)
  • 特点:
    键唯一,值可重复。
    允许以键集、值集或键-值映射关系集的形式查看Map
  • 功能:
    • 添加功能:
      Object put(Object key, Object value)
      当集合中不包含该key值时,添加,返回null
      当集合中包含该key值时,修改,覆盖该key原来对应的值,返回被替换掉的value值
    • 判断功能:
      boolean isEmpty() ---判断集合是否为空
      boolean containsKey(Object key) ---判断是否包含指定的键
      boolean containsValue(Object vlaue) ---判断是否包含指定的值
    • 删除功能:
      void clear() ---清空
      V remove(Object key) ---根据指定的键删除键值对,返回被删除的键值对元素的值(0如果没有指定的键,返回null)
    • 获取功能:
      Set keySet() ---获取Map集合中所有键的集合
      Collection values() ---获取Map集合中所有值的集合
      Set> entrySet() ---获取Map集合中所有键-值映射关系的集合
      V get(K key) ---根据指定的键获取该键对应的值
    • 长度功能:
      int size() ---返回Map集合长度,即键值对的对数
Map接口的三个子类的特点
HashMap
      底层数据结构是哈希表。
      线程不安全,效率高。允许null键和值
Hashtable
      底层数据结构是哈希表。
      线程安全,效率低。不允许null键和值
TreeMap
      底层数据结构是二叉树。
      线程不安全,效率高。
  • HashMap
    怎么保证唯一性的呢?
    它依赖两个方法:hashCode()和equals()
    顺序:
    首先判断hashCode()值是否相同。
    同:继续走equals(),看返回值
    如果true:就不添加到集合。
    如果false:就添加到集合。
    不同:就添加到集合。

  • Hashtable
    怎么保证唯一性的呢?
    它依赖两个方法:hashCode()和equals()
    顺序:
    首先判断hashCode()值是否相同。
    同:继续走equals(),看返回值
    如果true:就不添加到集合。
    如果false:就添加到集合。
    不同:就添加到集合。

  • TreeMap
    怎么保证唯一性的呢?是根据返回是否是0。
    怎么保证排序的呢?两种方式
    自然排序(元素具备比较性)
    实现Comparable接口
    比较器排序(集合具备比较性)
    你要排序的对象实现了comparable接口,自然会按自然顺序排序,如果你想要用比较器,得有个Comparator的实现类,要排序的时候将该实现类的对象传递过去,就按比较器规则排序。

Collection 单列集合体系:

List的特点:元素可重复,有序 (通过索引操作)            
Set的特点:元素无序,唯一。(这里的顺序是指存储和取出顺序)         

常用子类

  • List
    • ArrayList
    • LinkedList
    • Vector
  • Set
    • HashSet
    • TreeSet
List接口的三个子类的特点
    ArrayList
        底层数据结构是数组,查询快,增删慢
        线程不安全,效率高
    Vector
        底层数据结构是数组,查询快,增删慢
        线程安全,效率低
    LinkedList
        底层数据结构是链表,查询慢,增删快
        线程不安全,效率高

到底使用谁?根据需求看

  • 是否要安全:
    • 是:Vector
    • 否:ArrayList,LinkedList
      • 查询多:ArrayList
      • 增删多:LinkedList
      • (如果你什么都不知道,用ArrayList。)
  • ArrayList:存储字符串和自定义对象

重写emphasized textequqls三个步骤
1. 判断是否为同一个对象(提高效率)
2. 判断是否为该类的对象(提高健壮性)
3. 向下转型,然后根据需求比较成员变量

  • Vector:存储字符串和自定义对象

Vector 成员方法
public void addElement(Object obj) 添加
public Object elementAt(int index) 获取
public Enumeration elements() 获取
public int size() 长度

有自己的特殊功能。但是不用,被新功能给替代了。
A:添加功能。
void addElement( Object obj )
B:获取功能。
public Object elementAt( int index )
public Enumeration elements()
类Enumeration里边有两个方法。(类似于迭代器)
boolean hasMoreElements()
Object nextElement()
public int size()
JDK版本升级考虑的因素:A:安全。B:效率。C:简化书写。

  • LinkedList:存储字符串和自定义对象

有自己的特殊功能。可以很方便的操作头和尾。
A:添加功能
void addFirst( Object o ):将指定元素插入此列表的开头。
void addLast( Object o ):将指定元素添加到此列表的结尾。
B:获取功能
Object getFirst()
Object getLast()
C: 删除功能
Object removeFirst()
Object removeLast()

Set接口子类的特点
常用子类
HashSet
        底层数据结构是哈希表。
        线程不安全,效率高。
TreeSet
        底层数据结构是二叉树。
        线程不安全,效率高
  • HashSet类
    • 哈希值概念:
      • 哈希值:哈希值就是调用对象的hashCode()方法后返回的一个int型数字
      • 哈希桶:简单点理解就是存储相同哈希值对象的一个容器
    • HashSet的特点:不保证元素的迭代顺序。并且,不保证该顺序恒久不变。
    • HashSet类中的add(obj)方法如何保证元素的唯一性
      HashSet底层数据结构是哈希表。
      它依赖两个方法:hashCode()和equals()
      顺序:
      首先,判断hashCode()值是否相同。
      相同:
      继续走equals()方法,根据其返回值:
      true:说明元素重复,不添加到集合。
      false:说明元素不重复,添加到集合。
      不同:直接添加到集合。
    • 怎么重写hashCode()和equals()方法呢?
      • hashCode():
        把对象的所有成员变量值相加即可。
        如果是基本类型,就加值。如果是引用类型,就加哈希值。
      • equals():
        A:this==obj
        B:!(obj instanceof Student)
        C:所有成员变量的值比较。基本类型用==,引用类型用equals()。
        如果不会,自动生成。
  • TreeSet
    • TreeSet:根据构造方法的不同,选择使用自然排序或者比较器排序。
      按照实际的需求,可以对元素进行排序。并且保证唯一。
    • 怎么保证唯一性的呢?是根据返回是否是0。
      怎么保证排序的呢?两种方式
      自然排序(元素具备比较性)
      实现Comparable接口
      比较器排序(集合具备比较性)
      实现Comparator接口

迭代器的使用

  • 什么是迭代器
    • 迭代器是集合的一种遍历(一个一个的获取元素)方式。
    • 迭代器是一个获取元素的一个工具,类似数组中的遍历。
    • Java为了方便对集合中的元素获取,为集合类中提供了一个迭代的方法iterator(),该方法返回值实现了Iterator接口,这个接口就获取集合元素的一个迭代器
  • 使用步骤
    • 通过集合对象获取迭代器对象。
    • 通过迭代器对象判断。
    • 通过迭代器对象获取。
List list = new ArrayList();
  list.add(1);
  list.add(3);
  Iterator iterator = list.iterator();
  while(iterator.hasNext()){
      Integer next = (Integer)iterator.next();
      System.out.println(next);
         }
  • 迭代器原理
    • 迭代器是一个内部类,在集合的内部定义了一个类,这个类实现了Iterator接口(集合迭代器是以内部类的方式实现的)
    • 由于多种集合的数据结构不同,所以存储方式不同,所以,取出方式也不同。这个时候,我们就把判断和获取功能定义在了一个接口中,将来,遍历哪种集合的时候,只要该集合内部实现这个接口即可。

Iterator迭代器

  • Iterator接口
    • 概述:
      对 collection 进行迭代的迭代器。(迭代是取出集合中元素的一种方式)
      迭代器取代了Enumeration(枚举)。
    • 方法:
      boolean hasNext() ---如果仍有元素可以迭代,则返回 true。
      E next() ---返回迭代的下一个元素。
      void remove() ---从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
  • 成员方法
    • Iterator
      boolean hasNext() ---若被迭代的集合元素还没有被遍历,返回 true
      Object next() ---返回集合的下一个元素
      void remove() ---删除集合上一次 next()方法返回的元素。 (若集合中有多个相同的元素, 都可以删掉)
    • ListIterator 继承自Iterator
      void add(Object obj) ---将指定元素插入next()方法返回的元素后面
      void set(Object obj) ---用指定元素替换next()或previouse()方法返回的元素
      boolean hasPrevious() ---若被迭代的集合元素还没有被遍历,返回 true
      Object previous() ---返回集合的上一个元素
  • Iterator和ListIterator的区别
    • Iterator是ListIterator的父接口
    • Iterator是Collection集合的公共的取出容器中元素的方式,对于List,Set都通用。而ListIterator是List集合的特有的取出元素的方式
    • Iterator中只具备hasNext(),next(),remove()方法,可以删除被遍历到的元素
      ListIterator中具备对遍历到的元素进行增(add)删(remove)改(set)查(next)的方法,可以对元素逆向遍历previous相对于next,hasPrevious相对于hasNext(用的很少)

常见问题

并发修改异常
  • 简单来讲,并发修改异常就是在对集合元素进行迭代的时候,集合本身发生了改变,所以抛出此异常。(或者说并发修改异常 是在迭代过程中,被迭代的集合发生了变化才引发的)
  • 并发修改异常
    A:出现的现象
    迭代器遍历集合,集合修改集合元素
    B:原因
    迭代器是依赖于集合的,而集合的改变迭代器并不知道。
    C:解决方案
    a:迭代器遍历,迭代器修改(ListIterator)
    元素添加在刚才迭代的位置
    b:集合遍历,集合修改(size()和get())
    元素添加在集合的末尾

拆箱与装箱

来源:基本类型的数值不是对象,不能调用对象的toString()、hashCode()、getClass()、equals()等方法。所以Java提供了针对每种基本类型的包装类型。
装箱就是 自动将基本数据类型转换为包装类型;
拆箱就是 自动将包装类型转换为基本数据类型。
下表是基本数据类型对应的包装器类型:

基本数据类型 包装类型
int(4字节) Integer
byte(1字节) Byte
short(2字节) Short
long(8字节) Long
float(4字节) Float
double(8字节) Double
char(2字节) Character
boolean(未定) Boolean

包装类与基本类型的区别

  • 包装类:
    • 包装类是对象,拥有方法和字段.对象的调用都是通过引用对象的地址,
      产生对象时直接用引用指向这个对象。
    • 包装类是引用传递
    • 表示一个值(不用于计算,只用于保存值时和int类型一样);
    • 对象存储在堆里(堆栈更高效,这也是Java保留基本类型的原因)
  • 基本类型:
    • 基本类型是变量,变量的值存储在栈里;
    • 基本类型是值传递

你可能感兴趣的:(2018-03-28)