集合那点事

什么是集合?

集合可以看作是一个容器,如红色的衣服可以看作是一个集合,所有Java类的书也可以看作是一个集合。

java.util  包中提供了一些集合类,这些集合类又被称为容器。

数组和集合的区别:

  1. 数组的长度是固定的,集合的长度是可变的
  2. 数组用来存放基本数据类型,集合用来存放对象的引用。
  3. 数组只能存储相同类型的数据,集合可以存储不同类型的数据。

常用集合类的继承关系

Collection接口

Collection接口的常用方法
方法 功能描述
size() 返回集合中元素的个数(集合的长度)
add(Object o) 添加元素
addAll(Collection c) 把集合c里面所有的元素添加到当前集合中
isEmpty() 判断当前集合是否为空,如果为空就为true
clear() 清空集合中的元素
contains(Object o) 判断当前集合中是否包含指定元素o
containsAll(Collection c) 判断集合c中所有的元素是否都存在于当前集合中
remove(Object o) 删除集合中的元素o
removeAll(Collection c) 从当前集合中删除另一个集合c所有的元素
toArray() 将集合转成一个数组
equals() 判断两个集合的元素值是否相等
hashCode() 返回是当前对象的哈希值

 

Collections和collection的区别?

Collections 是一个操作 Set、List 和 Map 等集合的工具类
collection是set和list的一个父接口

排序操作:(均为static方法)

  1. reverse(List):反转 List 中元素的顺序
  2. shuffle(List):对 List 集合元素进行随机排序
  3. sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
  4. sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
  5. swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
  6. Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
  7. Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
  8. Object min(Collection)
  9. Object min(Collection,Comparator)
  10. int frequency(Collection,Object):返回指定集合中指定元素的出现次数
  11. void copy(List dest,List src):将src中的内容复制到dest中
  12. boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

List集合

List 集合包括List 接口以及List 接口 的所有实现类。List集合存储的数据是有序的,是重复的。List集合中的元素允许重复,各元素的顺序就是对象插入的顺序

List继承Collection,所以Collection中的方法,在list中也能用
除此之外,List还定义了两个非常重要的方法
1. get(int index) 获得指定索引位置的元素
2. set(int index,Object obj) 将集合中指定索引位置的对象修改为指定的对象

List接口的实现类有ArrayList和LinkedList以及Vector

ArrayList和LinkedList以及Vector的异同

相同点:

  1. 都是list 集合的实现类
  2. 存储数据的特点相同:有序的、可重复的

不同点:

  1. ArrayList类实现了可变的数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问,缺点是向指定的索引位置插入对象或删除对象的速度较慢。
  2. LinkedList类采用链表结构保存对象。便于向集合中插入和删除元素,效率比ArrayList高,但是对于随机访问,效率则比ArrayList低。
  3. Vector:是list接口的古老实现类,线程安全的,效率比较低

ArrayList底层实现

 

List list=new ArrayList();  //并且对数组 Object[] elementData进行了初始化,初始化为{}
list.add(1);        

//第一次调用add方法,底层对数组长度进行了指定,指定为10,如果添加的新元素导致数组elementData容量不够,则进行了扩容,扩容了1.5倍,同时将原数组的元素值复制到了扩容后的新数组里面

LinkedList底层实现

List list=new LinkedList():在内部声明了Node类型的first和last属性值,默认为null
list.add(1); //调用add方法,把1封装到node中,创建了Node对象
node的定义为:
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;

}

Vector底层实现

在调用无参构造方法Vector()的时候,底层创建了一个长度为10的数组,它扩容的是2倍

Set集合

Set接口中的对象是无序的,是不能重复的,Set接口继承Collection接口
Set接口常用的实现类有HashSet与TreeSet
HashSet:由哈希表支持,不保证Set的迭代顺序,允许使用null
LinkedHashSet:是HashSet的子类,遍历内部数据的时候,可以按照添加的顺序进行遍历,LinkedHashSet效率要高于HashSet
TreeSet:不仅实现了Set接口,还实现了SortedSet接口,因此顺序是递增的
TreeSet新增方法:
1. first() 第一个元素,或者是最低的元素
2. last() 最后一个元素,或者最高的元素
3. comparator() 返回对此Set中的元素进行排序的比较器,如果是自然顺序,则返回null
4. headSet(E toElement) 返回一个新的集合,新集合是toElement(不包含)之前的所有对象
5. subSet(E fromElement,E fromElement) 截取集合并返回一个新的集合,包含前不包含尾
6. tailSet(E fromElement) 返回一个新的集合,新集合是fromElement(包含)之后的所有对象

HashSet实现原理

1.我们向HashSet里面添加元素a的时候,首先调用元素a所在类的hasCode方法,计算元素a的哈希值,
计算出哈希值以后通过一些算法计算在HashSet底层在数组中存放的位置,判断数组的此位置有没有元素,
如果没有,直接把元素a添加到该位置(重写后hascode相同元素的哈希是一样的)
2.如果此位置有其他元素b,则比较两个元素的值是否相等(equals),
如果相等,元素a添加不成功
如果不相等,通过链条的方式把元素a添加的元素B的后面

Map集合

什么是Map集合,其结构是怎样的

Map集合提供的是key到value的映射,Map中不能包含相同的key,每个key只能映射一个value
Map中的key:无序、不可重复、使用set存储的
Map中value:无序、可重复的,使用collection进行存储的
key和value的组合就是一个Entry对象
Entry:无序的、不可重复的,使用set进行存储的

Map接口中的常用方法:

  1. put(K key, V value) 添加
  2. containsKey() 是否包含指定key的映射关系
  3. containsValue() 是否包含指定Value的映射关系
  4. get(key) 获取指定key的值,如果没有就返回null
  5. keySet 所有key形成的Set集合
  6. values 所有values形成的Collection集合
  7. clear()  清除

map的实现类

HashMap:map的主要实现类,线程不安全,效率高,存储null的key和value
 -- LinkedHashMap:HashMap的子类,保证在变量map元素的时候,按照添加的顺序进行输出元素值
原因:在HashMap这个类的基础上,添加了一对指针,指向上一个元素的引用地址和下一个元素的引用地址,遍历效率比HashMap高
TreeMap:可以保证key-value进行排序,有序的输出,(自然排序和自定义排序)
Hashtable:古老的实现,线程安全的,效率低,不能存储null的key和value
  --Properties:用来处理配置文件,jdbc

HashMap的底层实现?

 

Map map=new HashMap();对加载因子进行了初始化

map.put(123,123):首次调用put方法的时候,创建了一个长度为16的Node[]数组,并且对临界值进行了初始化为12

添加一个元素put(key1,value1),调用key1所在类的hashcode方法,计算key1的哈希值,对哈希值通过一些算法进行计算,得key1元素的位置,拿着这个位置去Node[]数组里面去找位置,

如果此位置数据为空,key1,value1添加成功。

如果此位置上的元素不为空,如果key1的哈希值和已经存在的一个数据(key2-value)哈希值不相同,直接添加成功。

如果key1的哈希值和已经存在的一个数据(key2-value)哈希值相同,调用key1的equals方法和key2进行比较:

   如果equals比较的结果返回false,此key1,value1添加成功(已链条的形式存在)

   如果equals比较的结果返回true,使用value1替换value2的值

jdk1.8hashMap地址结构:数组+链条+红黑树 当数组的某一个索引的位置上的元素以链条的形式纯在的数据个数>8 并且数组的长度>64的时候,此位置变成了红黑树 进行存储数据

遍历集合的三种方式

Collection<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");

//1.迭代器
Iterator<String> iterator = list.iterator();    //创建迭代器
        while (iterator.hasNext()){
            String str = (String) iterator.next();      //iterator.next()返回的是Object对象,要强行转换成String
            System.out.println(str);
        }

//2. 增强for循环
for(Object o: list){
    System.out.println(o);
}

//3.把集合转成数组,遍历数组
Object[] objects=list.toArray();
for(Object o:objects){
    System.out.println(o);
}

遍历List集合的三种方式

List list=new ArrayList();
        //1.添加元素
        list.add("aaa");
        list.add("bbb");
        list.add(123);
        list.add("bbb");

        System.out.println("=============1.迭代器");
        Iterator i=list.iterator();
        while(i.hasNext()){
            System.out.println(i.next());
        }

        System.out.println("=============2.增强for");
        for(Object o:list){
            System.out.println(o);
        }

        System.out.println("=====3.for循环");
        for(int a=0;a<list.size();a++){
            System.out.println(list.get(a));
        }

遍历Map的两种方式

public void test(){
        Map map=new HashMap();
        map.put("1001","阿轲");
        map.put("1002","韩信");
        map.put("1003","李白");
        map.put("1004","百里玄策");

        //keySet():获取所有的key
        Set set=map.keySet();
        for (Object o:set){
            System.out.println(o);
        }
        System.out.println("==================");
        //values():获取所有的value值
        Collection values=map.values();
        Iterator i=values.iterator();
        while (i.hasNext()){
            System.out.println(i.next());
        }
        System.out.println("==================");
        //key-value:通过一个循环获取key和value值
        //遍历map的第一种方法
        Set set1=map.keySet();
        for (Object key:set1){
            //根据key获取对应的value值
            Object value=map.get(key);
            System.out.println(key+"-"+value);

        }

        System.out.println("=================");
        //遍历map的第二种方式
        Set set2= map.entrySet();//获取所有的entry(key+value的组合)
        //从set集合里面取出每一个entry
        for(Object objs:set2){
            //把父类转成子类
            Entry entry=(Entry)objs;
            //获取对应的key
            Object key=entry.getKey();
            //获取对应的value
            Object value=entry.getValue();
            System.out.println(key+"-"+value);

        }
}

 

posted @ 2021-03-01 17:13  山石满棠  阅读(125)  评论(0)    收藏  举报