Java面试题-集合

title: Java面试题—集合
categories:

  • 面试题
    tags:
  • Java
  • 后端开发
    date: 2023-02-27 19:26:00

集合
categories:

  • 面试题
    tags:
  • Java
  • 后端开发
    date: 2023-02-27 19:26:00

集合
categories:

  • 面试题
    tags:
  • Java
  • 后端开发
    date: 2023-02-27 19:26:00

集合
categories:

  • 面试题
    tags: [‘Java’,‘后端开发’]
    date: 2023-02-27 19:26:00

集合概述

Java集合,也是容器,构成于两个接口:Collection和Map接口.用于存放键值对。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4GoPShNQ-1680940906631)(/666.github.io/pic/1.png)]

说说List,Set,Queue,Map四种集合的区别。

  • List比较适合存储有序的、可以重复的元素
  • Set常用于存储无序的、不可重复的元素
  • Queue按照特定的排队规则来确定先后顺序,存储的元素是有序的且可以重复
  • Map查询比较快,其中key无序且不重复,value无序但可重复,一个键key对应一个value值

跟着视频复习一遍吧

韩顺平视频地址(https://www.bilibili.com/video/BV1YA411T76k/?spm_id_from=333.337.search-card.all.click&vd_source=7c6c7bb18c7ca81e3c9e3e6722861c9d)


主要的两大类,需要背
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ofFemIK-1680940906632)(/666.github.io/pic/47.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9PlAnWeH-1680940906633)(/666.github.io/pic/48.png)]

List接口的三种实现方法

LinkedList,ArrayList,Vector。

List的三种输出方式

package com.jun.List_;

import java.util.ArrayList;
import java.util.Iterator;

/*
 * @Author: jun
 * @Date:2023/4/4 16:37
 * @概述:
 */
public class ListFor {
    @SuppressWarnings("all")
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        for (int i = 0; i < 12; i++) {
            list.add("jun"+i);
        }
        System.out.println(list);

        //三种遍历方式
        //1.迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println("迭代器输出:"+next);
        }
        
        //2.增强for
        for (Object j :
                list) {
            System.out.println("增强for输出:"+j);
        }

        //3.常规for输出
        for (int i = 0; i < list.size(); i++) {
            System.out.println("常规for输出:"+list.get(i));
        }
    }
}

ArrayList是线程不安全的,因为没有添加 synchronized互斥锁,线程之前会同时进行操作,会导致脏读,幻读,错读。

所以在多线程情况下就不要使用ArrayList了。

ArrayList底层结构和源码分析

1) ArrayList中维护了一个Object类型的数组elementData.

2) 当创建ArrayList对象时,如果使用的是无参构造器(即没有指明大小),则初始化elementData容量为0,第一次添加,则扩容elementData为10,如果需要再次扩容elementData就为1.5倍。

3) 如果使用的指定大小的构造器,初始的大小elementData容量为指定大小,如果需要再次扩容,则直接扩容elementData为1.5倍。

Vector底层结构和源码分析

还是List接口的实现子类。


1) 底层也是一个对象数组。

2) 是线程同步的,即线程安全。Vector类的操作方法有synchronized
3) 在开发的过程中,需要考虑到线程同步安全问题时,可以考虑使用Vector。

LinkedList底层结构和源码分析

1) LinkedList底层实现了双向链表和双端队列特点
2) 可以添加任意元素(元素可以重复),包括null
3) 线程不安全,没有实现同步。

双向链表

package com.jun.List_;

/*
 * @Author: jun
 * @Date:2023/4/7 19:12
 * @概述:
 */
public class LinkedList01_ {
    public static void main(String[] args) {
        //模拟一个简单的双向链表
        node jack = new node("jack");
        node tom = new node("tom");
        node jun = new node("jun");

        //连接三个节点,形成双向链表
        //jack -> tom -> jun
        jack.next = tom;
        tom.next = jun;
        //jun -> tom -> jack
        jun.pre = tom;
        tom.pre = jack;

        node first = jack; //让first引用指向jack,就是双向链表的头结点
        node last = jun;    //让last引用指向jun.就是双向链表的尾结点

        System.out.println("从头到尾遍历");
        while (true) {
            if (first == null) {
                break;
            }
            //输出first信息
            System.out.println(first);
            first = first.next;
        }

        System.out.println("从尾到头遍历");
        //演示,从尾到头遍历
        while (true) {
            if (last == null) {
                break;
            }
            //输出first信息
            System.out.println(last);
            last = last.pre;
        }

    }


}

//定义一个node,表示一个双向连表的节点
class node{
    public Object item; //真正存放数据
    public node next; //指向下一个结点
    public node pre;    //

    public node(Object name){
        this.item = name;
    }

    @Override
    public String toString() {
        return "node name" + item;
    }
}

ArrayList和LinkedList比较

ArrayList和LinkedList的比较:

ArrayList是可变数组,增删的效率比较低,数组可以扩容,改查的效率也比较高


LinkedList 是双向链表,通过链表追加,改查的效率比较低。

Set接口

主要的两个子实现类:HashSet和TreeSet


1)接口无序:添加和取出的顺序不一致,没有索引
2)不允许重复元素,最多包含一个null
3)JDK API中Set接口的实现类有AbstractSet , ConcurrentHashMap.KeySetView , ConcurrentSkipListSet , CopyOnWriteArraySet , EnumSet , HashSet , JobStateReasons , LinkedHashSet , TreeSet

package com.jun.Set;

import java.util.HashSet;

/*
 * @Author: jun
 * @Date:2023/4/7 20:05
 * @概述:
 */
public class SetMethod {
    public static void main(String[] args) {
        //1. 以Set接口的实现类HashSet 为例
        //2. set接口的实现类对象,不能存放重复的元素
        //3. 无序,即添加的顺序与取出的数据不一致
        //4. 注意:取出的顺序是始终一致的,不会每次都不一样
        HashSet set = new HashSet();
        set.add("john");
        set.add("lucy");
        set.add("jun");
        set.add("jack");
        set.add(null);
        set.add(null);
        System.out.println(set);
    }
}

遍历方式

//方式1:迭代器
        Iterator iterator = 					set.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }


        //方式2:增强for
        for (Object o :
                set) {
            System.out.println(o);
        }
        

HashSet

1) 实现了Set接口
2) 实际上是HashMap
3) 可以存放null值,但是只有一个null
4) 不保证有序,即,不保证存放元素的顺序和取出的顺序一致。
5) 不重复的元素。

Map

package com.jun.map_;

import java.util.HashMap;
import java.util.Map;

/*
 * @Author: jun
 * @Date:2023/4/8 10:13
 * @概述:
 */
public class Map_ {
    public static void main(String[] args) {
        //1.Map用于保存具有映射关系的数据Key-Value
        //2.Map与Collection并列存在,用于保存具有映射关系的数据:Key-Value(双列元素)
        //3.Map中的Key和Value可以是任何引用类型的数据,会封装到HashMap&Node对象中
        //4.一般情况下以String类作为Map的Key
        //5.key和value之间存在单向一对一的关系,即通过指定的key可以找到对应的value
        Map map = new HashMap();
        map.put("no1","jun");
        map.put("no2","lili");
        map.put("no1","zhang");//当有相同的k,就等价于替换
        map.put("no3","lili");//value可以重复
        map.put(null,null);//map中的key可以为null,value也可以为null
        //两者的细微不同是,key只能一个为null,而value可以有多个null

        map.put(new Object(),"人人");
        System.out.println(map);

    }
}

开发中如何选择集合实现类

选择什么集合实现类,主要取决于业务操作特点:
1) 先判断存储的类型(一组对象[单列]或者一组键值对[双列])
2) 一组对象:collection接口

允许重复:list

增删多:LinkedList(底层维护了一个双向链表)

不允许重复:Set

无序:HashSet
排序:TreeSet

3) 一组键值对:Map
键无序:HashMap(哈希表,jdk7:数组+链表,jdk8:数组+链表+红黑树)
键排序:TreeMap

键插入和取出一致:LinkedHashMap
读取文件:properties

Collections工具类

package com.jun.collection_;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/*
 * @Author: jun
 * @Date:2023/4/8 15:24
 * @概述:
 */
@SuppressWarnings({"all"})
public class Collections_tool {
    public static void main(String[] args) {
        //创建ArrayList集合,用于测试
        List list = new ArrayList();
        list.add("jun01");
        list.add("jun02");
        list.add("jun03");
        list.add("jun04");

        //reverse(List):反转List中元素的顺序
        Collections.reverse(list);
        System.out.println(list);//result:[jun04, jun03, jun02, jun01]

        //shuffle(List):对List集合元素进行随机排序
        Collections.shuffle(list);
        System.out.println(list);//[jun02, jun03, jun01, jun04]

        //sort(List):根据元素的自然顺序对指定List集合元素按升序排序
        Collections.sort(list);
        System.out.println(list);//[jun01, jun02, jun03, jun04]

        //swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
        Collections.swap(list,0,1);
        System.out.println(list);//[jun02, jun01, jun03, jun04]

        //Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
        System.out.println(Collections.max(list));

        Object maxObject = Collections.max(list, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).length() - ((String) o2).length();
            }
        });
        System.out.println(maxObject);
    }
}

脑瓜子痛
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yQko03fx-1680940906633)(/666.github.io/pic/f4aa9cd4d88b8eda7d695ba4f1c6cbb0_1.jpg)]

你可能感兴趣的:(java,jvm,面试)