【Java】集合框架

Collection接口

单列集合,用来存储一个一个的对象
在这里插入图片描述
List接口和Set接口都实现了Collection接口

常用方法:

1. add(Object e) 将元素e添加到集合Coll中

在这里插入图片描述

2. size() 获取添加的元素的个数

在这里插入图片描述

3. addAll 另一个Collection的元素全都添加

在这里插入图片描述

4. clear() 清空集合元素

coll.clear()

5. isEmpty() 判断当前集合是否为空

System.out.println(coll.Empty())

6. contains(Object obj) 判断当前集合中是否包含obj

用equals比的,而不是== 所以比的是内容不是地址
在这里插入图片描述

7. containsAll(Collection coll1) 判断形参coll1中的所有元素是否都存在于当前集合中

只要有不在的就是false
在这里插入图片描述

8. hashCode() 返回当前对象的哈希值

System.out.println(coll.hashCode())

9. toArray()

在这里插入图片描述
asList()数组–>集合
在这里插入图片描述

10. remove(Object o)

coll.remove(123);//也会调用equals方法

11. removeAll(Collection<?> c) 差集

12. retainAll(Collection<?> c) 求交集

Collection coll = new ArrayList();
coll.add(123);
coll.add(new String("AA"));
coll.add("122");

Collection coll1 = Arrays.asList(123,456,789);
coll.retainAll(coll1);//coll输出的是交集123
  1. equals(Object o) 判断两个集合相等

of() 和copyOf()

of() 创建一个只读的集合
copyOf(Xxx coll) 如果coll本身就是只读集合,那copyOf就直接返回coll;如果coll不是只读集合,那copyOf()就要返回一个新的集合
在这里插入图片描述

遍历

遍历集合的方法:

  • 方法一:iterator
  1. iterator() 返回Iterator接口的实例,用于遍历集合元素
    有hasNext()、next() 和remove()【没调next之前不要调remove】方法
Collection coll = new ArrayList();
coll.add(123);
coll.add(new String("AA"));
coll.add("122");

Iterator iterator = coll.iterator();

while(iterator.hasNext()){//判断是否还有下一个元素
    Object obj = iterator.next();//调next的时候指针下移,将下移以后集合位置上的元素返回
    if("122".equals(obj)){
    iterator.remove();//删除集合中122元素
}
}

iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法
如果还未调用next() 或在上一次调用next()方法之后已经调用了remove方法,再调用remove都会报IllegalStateException

  • 方法二:for each
    内部仍然调用了迭代器
for(Object obj:coll){
	System.out.println(obj);
}

子接口

子接口:List接口

有序、可重复
  1. 有序的、可重复的数据 —>“动态”数组(长度可变)
    由于Java中数组存储数据的局限性,通常使用List代替数组
ArrayList、LinkedList、Vector三者异同
  1. ArrayList、LinkedList、Vector三者异同
    三个类都实现了List接口,存储的特点相同:存储有序的、可重复的数据
  • ArrayList:作为List接口的主要实现类;线程不安全,效率高;底层使用Object[] elementData存储
  • LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
  • Vector:作为List接口的古老实现类;线程安全,效率低;底层使用Object[] elementData存储
常用方法
  1. 常用方法
  • void add(int index,Object ele)
    在index位置插入ele元素
    ArrayList list = new ArrayList();
    list.add(123);
    list.add(456);
    list.add("AA");
    list.add(456);
    System.out.println(list);//[123, 456, AA, 456]
    
    //void add(int index,Object ele) :在index位置插入ele元素
    list.add(1,"BB");
    System.out.println(list); //[123, BB, 456, AA, 456]
    
  • boolean addAll(int index, Collection eles)
    从index位置开始将eles中所有的元素添加
    //boolean addAll(int index, Collection eles) 从index位置开始将eles中所有的元素添加
    List list1 = Arrays.asList(1,2,3);
    list.addAll(3,list1);
    System.out.println(list);//[123, BB, 456, 1, 2, 3, AA, 456]
    
  • Object get(int index)
    获取指定index位置的元素
    //Object get(int index) 获取指定index位置的元素
    System.out.println(list.get(5));//3
    
  • int indexOf(Object obj)
    返回obj在集合中首次出现的位置,如果不存在返回-1
    int index  = list.indexOf("BB");
    System.out.println(index);//1
    
  • int lastIndexOf(Object obj)
    返回obj在集合中末次出现的位置
    System.out.println(list.lastIndexOf("BB"));//1
    
  • Object remove(int index)
    移除指定index位置的元素,并返回此元素
    Object remove = list.remove(1);//remove 是“BB”
    System.out.println(remove);//BB
    System.out.println(list);//[123, 456, 1, 2, 3, AA, 456]
    
  • Object set(int index, Object ele)
    设置指定index位置的元素为ele
    list.set(5,"CC");
    System.out.println(list);//[123, 456, 1, 2, 3, CC, 456]
    
  • List subList(int fromIndex,int toIndex)
    返回从fromIndex到toIndex位置的左闭右开区间
    List subList = list.subList(2,4);
    System.out.println(subList);//[1, 2]
    
遍历
  1. 遍历
  • 方式一:Iterator迭代器方式
    Iterator iterator = list.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }
    
  • 方式二:增强for循环 for each
    for (Object obj:list) {
        System.out.println(obj);
    }
    
  • 方式三:普通for循环
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
    
  1. 面试题
  • 区分list中的remove方法
    collection有一个remove(Object o)删的是对象
    list有一个重载的remove(int index)按索引删的
public void updateList(List list){
    list.remove(2);//删的是索引2指的3 [1,2,3] --> [1,2]
    list.remove(new Integer(2));//[1,2]-->[1]
}
实现类
ArrayList

ArrayList:作为List接口的主要实现类;线程不安全,效率高;底层使用Object[] elementData存储

  1. jdk7 new ArrayList的时候就创建了数组,类似单例的饿汉式,
    在这里插入图片描述
  2. jdk8 add的时候才创建,类似于单例的懒汉式,延迟数组创建,节省内存
    在这里插入图片描述
LinkedList

LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList高;底层使用双向链表存储

在这里插入图片描述

Vector

Vector:作为List接口的古老实现类;线程安全,效率低;底层使用Object[] elementData存储
在这里插入图片描述

子接口:Set

无序、不可重复
  1. Set是无序的(不等于素姬姓)、不可重复的数据 类似高中讲的集合

    • 无序性
      无序性不等于随机性。以HashSet为例,存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。所以无序指的存放的位置不是挨着一个一个放的。
    • 不可重复性
      保证添加的元素按照equals()方法判断时,不能返回true。即:相同的元素只能添加一个
  2. Set接口没有额外定义新的方法,使用的都是Collection中生命过的方法

  3. 对于自定义类要调用Set方法要重写HashCode和equals方法

添加元素的过程
  1. 添加元素的过程,以HashSet为例
    向HashSet中添加元素a,首先计算元素a所在类的hashCode()方法,计算元素a的哈希值;此时哈希值通过某种算法在HashSet底层数组中的存放位置(索引位置),判断此位置上是否有元素;
    如果此位置没有其他元素,则元素a添加成功。【情况1】
    如果此位置有其他元素b(或以链表形式存在的多个元素),则比较元素a和元素b的hash值:
    如果hash值不同,则元素a添加成功。【情况2】
    如果hash值相同,进而需要调用元素a所在类的equals方法,equals()返回true元素a添加失败;equals返回false,则则元素a添加成功。【情况3】

对于添加成功的情况2和情况3而言:元素a与已经存在指定索引位置上数据以链表的方式存储。jdk7中元素a放到数组中,指向原来的元素。jdk8中原来的元素在数组中,指向元素a。(总结:七上八下)
在这里插入图片描述

实现类
HashSet

作为Set接口的主要实现类;线程不安全的;可以存储null值

LinkedHashSet

LinkedHashSet是HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个数据和后一个数据。
遍历其内部数据时,可以按照添加的顺序的遍历
优点:对于频繁的遍历操作,LinkedHashSet效率高于HashSet

TreeSet

可以按照添加对象的指定属性进行排序

  1. 向TreeSet中添加的数据,要求是相同类的对象。
  2. 两种排序方式:自然排序(实现comparable接口)和定制排序(comparator)
  • 自然排序
    比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()
  • 定制排序
    比较两个对象是否相同的标准为:compare()返回0,不再是equals()

练习:TreeSet 通过hash值存放元素

public void test1(){
    HashSet set = new HashSet();
    Person p1 = new Person(1001,"AA");
    Person p2 = new Person(1002,"BB");

    set.add(p1);
    set.add(p2);

    System.out.println(set); //[Person{id=1002, name='BB'}, Person{id=1001, name='AA'}]
    p1.setName("CC");
    set.remove(p1);//当前p1位置是通过name 为AA的p1算出来的, remove时计算name为CC的p1的hashcode 所以p1没有被删除
    System.out.println(set);//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}]

    set.add(new Person(1001,"CC")); //能添加成功 因为p1位置的是通过“AA”算的
    System.out.println(set);//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}, Person{id=1001, name='CC'}]

    set.add(new Person(1001,"AA"));//能添加成功 虽然和最初的p1位置一样,但是现在p1的是“CC” add的是“AA”
    System.out.println(set);//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}, Person{id=1001, name='CC'}, Person{id=1001, name='AA'}]

}

Map接口

双列集合,用来存储一对一对(key-value)的数据
在这里插入图片描述

  1. Map结构的理解
    在这里插入图片描述

Map接口常用方法

在这里插入图片描述

添加put(Object key,Object value) putAll(Map m)

在这里插入图片描述

移除 Object remove(Object key)

返回移除的key对应的value
在这里插入图片描述

清空 clear()

清空当前map的所有数据
在这里插入图片描述

查询Object get(Object key)

获取指定key对应的value
在这里插入图片描述

boolean containsKey(Object key) containsValue(Object value)

containsKey是否包含指定的key
containsValue是否包含指定的value
在这里插入图片描述

遍历

  1. keySet() 遍历所有的key集
    在这里插入图片描述

  2. values() 遍历所有的value集
    在这里插入图片描述

  3. entrySet() 遍历所有的key-value
    方式一:
    在这里插入图片描述
    方式二:
    在这里插入图片描述

实现类:HashMap

  1. HashMap是Map的主要实现类。
  2. 线程不安全,效率高。
  3. HashMap可以存储null的key和value

HashMap的底层实现原理(面试题)

  1. jdk7中HashMap的底层实现原理
    在这里插入图片描述

  2. jdk8和7的不同
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

LinkedHashMap

保证在遍历map元素时,可以按照添加的顺序来实现遍历。因为LinkedHashMap在原有的HashMap底层结构基础上添加了一对指针,指向前一个和后一个元素。
对于频繁的遍历操作,LinkedHashMap效率高于HashMap
在这里插入图片描述

实现类: TreeMap

按照添加的key value进行排序,实现排序遍历。此时考虑key的自然排序或定制排序。

向TreeMap添加key value,要求key必须是由同一个类创建的对象。因为要用key进行排序

实现类:Hashtable

古老的实现类。线程安全,效率低。
不能存储null的key和value

Properties

常用来处理配置文件,key和value都是String类型
在这里插入图片描述

Collections工具类:操作Collection和Map

在这里插入图片描述
在这里插入图片描述
copy方法:
要注意dest的size() 要比list的size() 大,不然会抛异常。size()是实际的元素数而不是数组的长度
在这里插入图片描述

同步控制

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值