欢迎查看List、Set、Map

List、Set、Map各自的特点

一、结构特点

(一)list

1、实现了collection接口
2、允许重复的对象
3、可以有多个空值
4、里边元素有序(即为每个元素的插入顺序)
5、单列数据集合
6、实现类ArrayList、LinkedList 、Vector

(二)Set

1、实现了collection接口
2、元素唯一,不保存重复元素。
3、允许出现空值(只能有一个)
4、单列数据集合
5、元素位置固定(由hashcode决定)
6、元素无序(指不按照用户输入的顺序排序)
7、实现类HashSet、TreeSet、LinkedHashSet、SortedSet等

(三)Map

1、Map是存储键值对这样的双列数据的集合;(key,value)
2、Map中存储的数据是无序(按照hashcode来排的)
3、键不允许重复,值可用重复
4、键只能有一个null,值可用有多个null
5、实现类HashMap、HashTable、LinkedHashMap等
总结: List单列集合,元素:有序、可重复、可为空;
    Set单列集合,元素:无序、不重复、只有一个空元素;
    Map单列集合,元素:无序、键不重,值可重、可一个空键、多可空值;

二、实现类

(一)List接口有三个实现类

    1 LinkedList
    基于链表实现,链表内存是散列的,增删快,查找慢;
    2 ArrayList
    基于数组实现,非线程安全,效率高,增删慢,查找快;
    3 Vector
基于数组实现,线程安全,效率低,增删慢,查找慢;

(二)Map接口有四个实现类

 1 、HashMap
 基于 hash 表的 Map 接口实现,非线程安全,高效,支持 null 值和 null
 键;
 2 、HashTable
 线程安全,低效,不支持 null 值和 null 键;
 3 、LinkedHashMap
 是 HashMap 的一个子类,保存了记录的插入顺序;
 4 、SortMap 接口
 5、TreeMap,能够把它保存的记录根据键排序,默认是键值的升序排序

(三) Set接口有两个实现类

1 HashSet
底层是由 Hash Map 实现,不允许集合中有重复的值,使用该方式时需要重写 equals()和 hash Code()方法;
2 LinkedHashSet
继承于 HashSet,同时又基于 LinkedHashMap 来进行实现,底层使用的是 LinkedHashMap

三、List、Set、Map区别

  1. List 集合中对象按照索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象,例如通过list.get(i)方法来获取集合中的元素;
  2. Map 中的每一个元素包含一个键和一个值,成对出现,键对象不可以重复,值对象可以重复;
  3. Set 集合中的对象不按照特定的方式排序,并且没有重复对象,但它的实现类能对集合中的对象按照特定的方式排序,例如 Tree Set 类,可以按照默认顺序,也可以通过实现 Java.util.Comparator< Type >接口来自定义排序方式。

四、补充知识

(一)、HashMap 和 HashTable的区别?

1、HashMap 是线程不安全的,HashMap 是一个接口,是 Map的一个子接口,是将键映射到值得对象,不允许键值重复,允许空键和空值;由于非线程安全, HashMap的效率要较 HashTable 的效率高一些。HashMap的初始容量和负载因子决定,初始容量16,负载因子0.75。当当前大小和当前容量的比例超过了扩容因子,就会扩容,扩容后大小为 一倍。即每次为2n
2、HashTable 是线程安全的一个集合,不允许 null 值作为一个 key 值或者 Value 值;HashTable 是 sychronize(同步化),多个线程访问时不需要自己为它的方法实现同步,而 HashMap 在被多个线程访问的时候需要自己为它的方法实现同步; 目前不用HashTable,需要线程安全时候用ConcurrentHashMap(分段锁)替代HashTable。HashTable初始容量为11,每次扩容2n+1

(二)HashMap和HashSet的区别

在这里插入图片描述

(三)ArrayList和LinkedList的区别

答:ArrayList的底层数据结构为数组,增删慢、查询快,线程不安全,效率高。
LinkedList的底层数据结构为链表,增删快、查询慢,线程不安全,效率高。
备注:一个对象可以被反复存储进List中,每调用一次add方法,这个对象就被插入进集合中一次,其实,并不是把这个对象本身存储进了集合中,而是在集合中用一个索引变量指向这个对象,当这个对象被add多次时,即相当于集合中有多个索引指向了这个对象。

(四)ArrayList与Vector的区别?

答:Vector底层数据结构为数组,增删慢、查询快,线程安全,效率低,每次扩容为原来数组的2倍。
ArrayList底层数据结构为数组,增删慢、查询快,线程不安全,效率高,每次扩容为原来数组的1.5倍。

(五) ArrayList的底层是数组,数组的名称是什么?类型是什么?

答:名称是elementData,类型是Object[],所以ArrayList里面可以存放任意类型的元素。

(六) ArrayList底层数组的默认初始化容量是多少?当超出这个大小时,每次扩容是多少?

答:默认初始化容量是10。当超出这个大小时,每次扩容1.5倍。

(七)当向ArrayList集合中添加元素时需要调用add()方法,add()方法的执行流程是怎样的?

答:调用add()方法时,add()方法首先调用ensureCapacityInternal()来判断elementData数组容量是否足够,ensureCapacityInternal()之所以能够判断,是因为它内部调用了ensureExplicitCapacity()方法,这个方法才是真正判断elementData数组容量是否够用的关键方法。如果容量足够,则直接将元素添加到ArrayList中;如果容量不够,则ensureExplicityCapacity()方法内部会调用grow()方法来对数组进行扩容。扩容成功之后,再将元素添加到ArrayList扩容之后的新数组中。

(八)在调用ArrayList的remove(int index)方法时,执行流程是怎样的?

答:首先判断index是否合理,如果合理的话,会调用System.arraycopy()方法把指定下标到数组末尾的元素向前移动一个单位,并且会把数组最后一个元素设为null。这样是为了方便GC回收。

(九) ArrayList在调用get(int index)方法查询的时候,执行流程是怎样的?

答:首先判断index是否合理,然后调用elementData()方法,elementData()方法返回根据index查到的具体的元素。注意:这里的返回值都经过了向下转型(Object -> E)。

(十)ArrayList的大小是如何自动增加的?你能分享一下你的代码吗?

答:当向ArrayList中增加一个对象的时候,Java首先会判断ArrayList的底层数组elementData是否还有足够的空间来存储这个对象,如果有,就直接存,如果没有,就会基于原有的数组扩容出一个1.5倍的新数组,并将数据全部复制到新数组中。
注意:新建了一个数组,旧数组的对象被复制到了新的数组中,并且现有的数组引用指向新的数组。

(十一)什么情况下你会使用ArrayList?什么情况下你会选择LinkedList?

答:当对数据的主要操作为索引或只在集合的末端增加、删除数据时,使用ArrayList效率比较高;当对数据的操作主要为指定位置的插入或删除操作时,使用LinkedList效率比较高。

(十二). ArrayList的时间复杂度是多少?

答:当修改、查询或者只在数组末尾增、删时,时间复杂度为O(1);对指定位置的元素进行增、删时,时间复杂度为O(n)。

(十三)HashSet中调用add()时不允许重复原理

答:HashSet底层由HashMap实现,插入的元素被当做是HashMap的key,value默认为一个固定的Object,根据hashCode值来确定在集合中的位置,在添加元素时,先判断key的hashCode值是否相同,如果相同,则调用equals()、==进行判断,若相同则覆盖原有元素;如果不同,则直接向Map中添加元素;

(十四)HashMap执行put()方法时候的原理

答:
情况一:调用该元素键的equals方法与该位置上元素的键进行比较,如果返回ture则视新键与已经存在的键相同,用新值去更新旧值,然后put方法返回旧值
情况二:调用该元素键的equals方法与该位置上元素的键进行比较,如果返回false则新键与已经存在的键不相同,任然可以将新的元素存储在该位置。

五、List、set、Map的遍历

(一)遍历形式

list可用for、forEach、Iterator遍历
Set只能用迭代器遍历
Map可用for、forEach、Iterator遍历

(二)数组转换为集合在用迭代器输出

Int [] ={1,2,3,4,5,6};
List list=new ArrayList(Arrays.asList(arr));
Iterator it=list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}

(三)遍历Map的方式

Map<Integer,String> map = new HashMap<Integer,String>();

方式一:只能遍历value,不能遍历key

//		System.out.println(m.size());
//		for(String s:m.values()) {
//			System.out.println(s);
//		}

方式二:(推荐使用,尤其在大量数据操作的时候)

//		for(Map.Entry<Integer, String> v:m.entrySet()) {
//			System.out.println("键:"+v.getKey()+","+"值:"+v.getValue());
//		}

方式三:使用map中的entrySet()方式,将map转换为set利用迭代器迭代

//		Iterator<Entry<Integer, String>>  map1it=m.entrySet().iterator();
//        while(map1it.hasNext())
//        {
//         Map.Entry<Integer, String> entry=(Entry<Integer, String>) map1it.next();
//         System.out.println("Key: "+entry.getKey()+" Value: "+entry.getValue());
//        }

方式四:根据key二次取值,

//        for(Integer key:m.keySet()) {
//        	System.out.println("键:"+key+","+"值:"+m.get(key));
//        }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值