Java面试相关---集合

Collection  
        |--List
            |--ArrayList
            |--Vector
            |--LinkedList
        |--Set
            |--HashSet
            |--TreeSet

集合和数组的区别

A:长度区别

  •         数组的长度固定
    
  •         集合长度可变  
    

B:内容不同

  •         数组存储的是同一种类型的元素
    
  •         而集合可以存储不同类型的元素
    

C:元素的数据类型问题

  •         数组可以存储基本数据类型,也可以存储引用数据类型
    
  •         集合只能存储引用类型
    

数组有没有length()方法,字符串有没有length()方法。集合有没有length()方法;

没有,有,没有

迭代器集合的专门遍历方式

Iterator iterator():迭代器,集合的专用遍历方式

while (it.hasNext()) {
         System.out.println(it.next());
    }

用for循环改写效率高,因为用Iterator之后就是垃圾了。
for(Iterator it;it.hasNext();){
System.out.println(it.next());
}

迭代器为什么是接口,而不是一个类。

假设迭代器定义的是一个类,这样我们就可以创建该类的对象,调用该类的方法来实现集合的遍历。

由于Java提供了很多的集合类,而这些集合类的数据结构是不同的。所以,存储的方式和遍历的方式应该是不同的。进而遍历方式也应该不一样,最终没有定义迭代器类的。

而无论你是哪种集合,你都应该具备获取元素的操作,并且,最好在辅助于判断功能,这样,在获取前,先判断,这样就更不容易出错,也就是说,判断功能和获取功能应该是一个集合遍历所具备的,而每种集合的方式又不太一样,所以我们把这两个功能给提取出来,并不提供具体实现,这种方式就是接口。

那么,真正的具体的实现类在哪里呢?
在真正的具体的子类中,以内部类的方式体现的。
(增强for就是用来替代迭代器的)

List集合

  • 有序:进去的时候是什么顺序出去也是什么顺序(并不是排序)
  • 允许重复的元素;

list集合的特有遍历功能

size()方法和get()方法结合使用用for循环

list集合的特有迭代器列表迭代器listIterator

listIterator继承于Iterator接口

  • 特有功能1 previous().往回走。获取前一个元素
    1. hasPrevious(),判断是否有元素
  • 3.add()将指定元素添加。如果我们用Iterator去添加元素会出现并发修改异常。

数组

存储同一种类型的多个元素的容器,有索引,方便我们获取。
查询快,增删慢

链表

由一个链子把多个结点连起组成的数据
结点:有数据和地址组成(数据域和指针域组成)
查询慢,增删快

List子类的特点

  • ArrayList:
    底层数据结构是数组,查询快,增删慢。
    线程不安全,效率高
  • Vector:
    底层数据结构是数组,查询快,增删慢。
    线程安全,效率低
  • LinkedList:
    底层数据结构是链表,查询慢,增删快。
    线程不安全,效率高

Vector的特有功能

因为Vector是1.0出现,在1.2版本才加入到list集合中,所以它有自己的特有功能。
addElement---add
elementAt----get
elements----iterator
JDK升级的原因:A,安全。B.效率。C.简化书写

LinkedList的特有功能

A:addFirst()/addLast()
B:getFirst()/getLast()
C:removeFirst()/removeLast()

contains()

contains()方法的底层是依赖equals()方法。当我们比较一个集合是否包含另一个集合的时候如果存储的对象没有重写equals方法时,它就默认用的Object类中的方法,比较的是地址值。

asList(T...a)把数组转换成集合

其本质还是数组,所以长度不能改变。集合的增加,删除就会报错。修改则可以。

Set

无序:存储顺序和取出顺序不一致,(虽然)

唯一

HashSet

它不保证set的迭代顺序,特别是不保证该顺序恒久不变。

底层是HashMap保证hashset唯一,因为调用add就是hashmap的put()方法
通过add方法的源码我们可以知道底层依赖的判断两个方法就是:hashCode()和equals()

  • 步骤:
    • 首先比较哈希值:如果相同继续走,比较地址值或者走equals()
  • 如果不同:就直接添加到集合中

如果类中没有重写这两个方法,默认使用的是Object(),一般来说不同
而String类重写了这两个方法,所以内容相同就添加不进去。只添加一个

哈希表

是一个元素为链表的数组。综合了数组和链表的好处。(好比如新华字典)

LinkedHahSet

底层数据结构由哈希表和链表组成。哈希表保证元素唯一性,链表保证元素有序(存储和取出一致)
具有可预知的迭代顺序

TreeSet

能够对元素按照某种规则进行排序(自然排序,比较器排序)
特点:排序和唯一

  • 唯一性:根据比较的返回是否是0来决定
  • 排序:
  • 自然排序(元素具备比较性):让元素所属的类实现自然排序的接口Comparable
  • 比较器排序(集合具备比较性):让集合的构造方法比较器接口的子类对象Comparator
    底层数据结构是红黑树(红黑树是一种自平衡的二叉树)保证元素的排序和唯一性。

自然排序

如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口Comparable<Student>,重写方法

//按照姓名的长度排序
@Override
public int compareTo(Student s) {
    // 主要条件 姓名的长度
    int num = this.name.length() - s.name.length();
    // 姓名的长度相同,不代表姓名的内容相同
    int num2 = num == 0 ? this.name.compareTo(s.name) : num;
    // 姓名的长度和内容相同,不代表年龄相同,所以还得继续判断年龄
    int num3 = num2 == 0 ? this.age - s.age : num2;
    return num3;
  }

比较器排序

第二个构造器需要我们传入一个参数就是比较器对象,自定义一个类重写方法:

  new Comparator<Student>() {
        @Override
        public int compare(Student s1, Student s2) {
            // 姓名长度
            int num = s1.getName().length() - s2.getName().length();
            // 姓名内容
            int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
                    : num;
            // 年龄
            int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
            return num3;
        }
    }

Map

将键映射到值得对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。

  • Map集合的数据结构值针对键有效,跟值无关
  • Collection集合的数据结构是针对元素有效

map集合的遍历

  • 根据丈夫找妻子

  • 获取所有的键

  • 遍历键的集合,获取每一键

  • 根据去找值

         // 获取所有的键
         Set<String> set = map.keySet();
         // 遍历键的集合,获取得到每一个键
            for (String key : set) {
              // 根据键去找值
              String value = map.get(key);
              System.out.println(key + "---" + value);
          }
    
  • 根据结婚证找丈夫和妻子

  • 获取所有键值对对象的集合

  • 遍历键值对对象的集合得到每一个键值对对象

  • 根据键值对对象获取键和值

        // 获取所有键值对对象的集合
        Set<Map.Entry<String, String>> set = map.entrySet();
        // 遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry<String, String> me : set) {
        // 根据键值对对象获取键和值
        String key = me.getKey();
        String value = me.getValue();
        System.out.println(key + "---" + value);
          }

HashMap

键是哈希表结构,可以保证键的唯一性(hashCode()和equals()

LinkedHashMap

Map接口的哈希表和链表列表实现,具有可预知的迭代顺序

  • 哈希表保证唯一性
  • 链表保证有序(存储和取出顺序一致)

TreeMap

  • 键是红黑树结构,可以保证键的排序(默认自然排序)和唯一性.
  • 排序的话如果是自定义对象也得重写Comparable接口,否则会报错

HashMap和Hashtable(这里的't'是小写)的区别

Hashtable:线程安全,效率低。不允许null建和null值
HashMap:线程不安全,效率高,允许null建和null值

Collections接口

是针对集合进行操作的工具类

Collection和Collections的区别

  • :Collection 是单列集合的顶层接口,有两个子接口List和Set
  • :Collections 是针对集合进行操作的工具类,可以对集合进行排序和查找等

总结

  • :集合

      Collection(单列集合)
      List(有序,可重复)
          ArrayList
              底层数据结构是数组,查询快,增删慢
              线程不安全,效率高
          Vector
              底层数据结构是数组,查询快,增删慢
              线程安全,效率低
          LinkedList
              底层数据结构是链表,查询慢,增删快
              线程不安全,效率高
      Set(无序,唯一)
          HashSet
              底层数据结构是哈希表。
              哈希表依赖两个方法:hashCode()和equals()
              执行顺序:
                  首先判断hashCode()值是否相同
                      是:继续执行equals(),看其返回值
                          是true:说明元素重复,不添加
                          是false:就直接添加到集合
                      否:就直接添加到集合
              最终:
                  自动生成hashCode()和equals()即可
                  
              LinkedHashSet
                  底层数据结构由链表和哈希表组成。
                  由链表保证元素有序。
                  由哈希表保证元素唯一。
          TreeSet
              底层数据结构是红黑树。(是一种自平衡的二叉树)
              如何保证元素唯一性呢?
                  根据比较的返回值是否是0来决定
              如何保证元素的排序呢?
                  两种方式
                      自然排序(元素具备比较性)
                          让元素所属的类实现Comparable接口
                      比较器排序(集合具备比较性)
                          让集合接收一个Comparator的实现类对象
      Map(双列集合)
      A:Map集合的数据结构仅仅针对键有效,与值无关。
      B:存储的是键值对形式的元素,键唯一,值可重复。
      
      HashMap
          底层数据结构是哈希表。线程不安全,效率高
              哈希表依赖两个方法:hashCode()和equals()
              执行顺序:
                  首先判断hashCode()值是否相同
                      是:继续执行equals(),看其返回值
                          是true:说明元素重复,不添加
                          是false:就直接添加到集合
                      否:就直接添加到集合
              最终:
                  自动生成hashCode()和equals()即可
          LinkedHashMap
              底层数据结构由链表和哈希表组成。
                  由链表保证元素有序。
                  由哈希表保证元素唯一。
      Hashtable
          底层数据结构是哈希表。线程安全,效率低
              哈希表依赖两个方法:hashCode()和equals()
              执行顺序:
                  首先判断hashCode()值是否相同
                      是:继续执行equals(),看其返回值
                          是true:说明元素重复,不添加
                          是false:就直接添加到集合
                      否:就直接添加到集合
              最终:
                  自动生成hashCode()和equals()即可
      TreeMap
          底层数据结构是红黑树。(是一种自平衡的二叉树)
              如何保证元素唯一性呢?
                  根据比较的返回值是否是0来决定
              如何保证元素的排序呢?
                  两种方式
                      自然排序(元素具备比较性)
                          让元素所属的类实现Comparable接口
                      比较器排序(集合具备比较性)
                          让集合接收一个Comparator的实现类对象
    
  • 到底使用那种集合

    是否是键值对象形式:
       是:Map
        键是否需要排序:
            是:TreeMap
            否:HashMap
        不知道,就使用HashMap。
        
      否:Collection
        元素是否唯一:
            是:Set
                元素是否需要排序:
                    是:TreeSet
                    否:HashSet
                不知道,就使用HashSet
                
            否:List
                要安全吗:
                    是:Vector(其实我们也不用它,后面我们讲解了多线程以后,我在给你回顾用谁)
                    否:ArrayList或者LinkedList
                        增删多:LinkedList
                        查询多:ArrayList
                    不知道,就使用ArrayList
        不知道,就使用ArrayList
  • 集合的常见方法及遍历方式

      Collection:
      add()
      remove()
      contains()
      iterator()
      size()
      
      遍历:
          增强for
          迭代器
          
      |--List
          get()
          
          遍历:
              普通for
      |--Set
    
      Map:
      put()
      remove()
      containskey(),containsValue()
      keySet()
      get()
      value()
      entrySet()
      size()
      
      遍历:
          根据键找值
          根据键值对对象分别找键和值
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,444评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,867评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,157评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,312评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,673评论 3 289
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,802评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,010评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,743评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,470评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,696评论 2 250
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,187评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,538评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,188评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,127评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,889评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,741评论 2 274

推荐阅读更多精彩内容

  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 1,121评论 0 16
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,637评论 0 11
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,214评论 0 16
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,019评论 11 349