0902(045天 集合框架09 总结点 问)

0902(045天 集合框架09 总结点 问)

每日一狗(田园犬西瓜瓜

在这里插入图片描述

集合框架09 总结点 问

1. 问:

补充:快速失败机制(快死异常)

多个线程对线程不安全的容器同时进行过操作时会抛出ConcurrentModificationException(并发修改异常)

原因:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。

解决办法:

  1. 在遍历过程中,所有涉及到改变modCount值得地方全部加上synchronized。
  2. 使用CopyOnWriteArrayList来替换ArrayList
  3. 或者你也可以接收异常,只有运行正确后才跳出循环

1.1 问:集合框架一些总结

常见的集合有哪些

Map接口和Collection接口是所有集合框架的父接口

  1. Collection接口的子接口包括:Set接口和List接口

  2. Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等(ConcurrentHashMap可以理解为HashMap的线程安全版)

  3. Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等

    HashSet–HashMap TreeSet—TreeMap LinkedHashSet–LinkedHashMap

  4. List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等

    ArrayList–CopyOnWriteArrayList

集合框架大总结

在这里插入图片描述

1、所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出:Collection和Map,
Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。

2、集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。
Collection List Set Queue Map Comparable Comparator Iterable Iterator

3、抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。
AbstractList AbstractSet AbstractMap …

4、实现类:8个实现类(实线表示),对接口的具体实现。
ArrayList LinkedList HashSet TreeSet HashMap TreeMap Stack PriorityQueue
Vector LinkedHashSet Hashtable LinkedHashMap

5、Collection 接口是一组无序并允许重复的对象。

6、Set 接口继承 Collection,集合元素无序且不重复。

7、List接口继承 Collection,允许重复,维护元素插入顺序。

8、Map接口是键-值对象,与Collection接口没有什么关系。

9、Set、List和Map可以看做集合的三大类:

  • List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。
  • Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。
  • Map集合中保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value。

10、遍历集合中的对象,Iterable iterator ListIterator[双向遍历]

特殊的迭代器(走访器)Enumeration属于已经不建议使用的方法

//@since   1.0
    public interface Enumeration<E>
    Enumeration<Integer> enu = list.elements();
while(enu.hasMoreElements()) {
    Integer obj=enu.nextElement();
    System.out.println(obj);
}

11、看Arrays和Collections。它们是操作数组、集合的两个工具类
Arrays:排序,折半查找,数组比较,数组深比较,数组展示

Collections:排序,把一些不安全的容器转换成安全的容器,批量元素替换

1.2 作业

  1. ArrayList 和 Vector 的区别。

    Vector线程安全 ,ArrayList 线程不安全。

    ArrayList采用延迟初始化,延迟到第一次添加数据的时候

    ArrayList默认扩容比为1.5,Vector有固定的扩容步长,没设定时扩容比为2.0

  2. 说说 ArrayList,Vector, LinkedList 的存储性能和特性。

    ArrayList,Vector的存储都用数组

    LinkedList采用双向链表

    数组访问O(1),增删O(n)

    双向链表访问O(n),增删O(1)

  3. 快速失败 (fail-fast) 和安全失败 (fail-safe) 的区别是什么?

    快速失败:

    安全失败:基于对底层集合进行拷贝

  4. hashmap 的数据结构。

    数组+链表(红黑树)

  5. HashMap 的工作原理是什么?

    HashMap

  6. Hashmap 什么时候进行扩容呢?

    当存储容量到达一定阈值时扩容(最大容积*负载因子)

    当单链>8,总链<64时,也会进行扩容操作

  7. List、Map、Set 三个接口,存取元素时,各有什么特点?

    List:可以用对象比较,也可以用索引

    Map:存取使用key值进行定位键值对

    Set:存取使用对象比较方式进行

  8. Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用 == 还是 equals()? 它们有何区别?

    hashCode和equals用的都是HashMap key的判定流程,TreeSet用的是TreeMap,这里用的红黑树,用的是比较器那一套

  9. 两个对象值相同 (x.equals(y) == true),但却可有不同的 hash code,这句话对不对?

    可以,咱们自己封装的自定义数据类型,由于equals和hashCode方法写的不够全面才可能导致这种情况的发生。因为equals是判定两个对象是否相等用的,而hashCode是由另一个方法生成的,不知道咱们计算hashCode值所用属性和equals判定对象相同时所用的属性是否一致,所以这边一般不建议自己写这两个方法,直接用IDE进行生成。

    hash code是以一个对象属性放到散列函数中计算出来的值,但这样想,两个对象的数据一样,但是放到散列函数中计算出来的值却不一样,这咋可能嘛,唯一的可能就是equals和hashCode中用的属性不一样,而且肯定是equals

  10. heap 和 stack 有什么区别。

2. 流式编程

多线程针对集合的操作

Stream不是数据结构,不会存储数据,而是算法的封装。

操作是并行或并发执行的。

数据源本身是可以源源不断的

2.1 概念

定义

Stream API借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。

同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。

通常编写并行代码很难而且容易出错, 但使用Stream API无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

所以Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。

元素

Stream不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的Iterator。

原始版本的Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如过滤掉长度大于10的字符串、获取每个字符串的首字母等,Stream会隐式地在内部进行遍历,做出相应的数据转换。

Stream就如同一个迭代器Iterator,单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。

而和迭代器又不同的是,Stream可以并行化操作,迭代器只能命令式地、串行化操作。
顾名思义,当使用串行方式去遍历时,每个item读完后再读下一个item。

而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。

Stream的并行操作依赖于Java7中引入的Fork/Join框架(JSR166y)来拆分任务和加速处理过程。

特点

数据源本身可以是无限的。

2.2 应用

当使用一个流的时候,通常包括三个基本步骤:

获取一个数据源source → 数据转换 → 执行操作获取想要的结果。

每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。

Integer transactionsIds = 
	roomList.stream()  // 将List转换为stream对象
		.filter(b -> b.getLength() == 10) // 针对stream种的数据元素进行过滤,只使用为true
		.sorted((x,y) -> x.getHigh() - y.getHigh()) // 针对stream种的数据进行自定义规则的排序
		.mapToInt(Room::getWidth)	// 从集合元素通过调用当前对象getWidth方法获取对应的int类型数据
		.sum();  // 针对整数值进行求和处理
使用Stream步骤
  1. 创建Stream;
  2. 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换)
  3. 对Stream进行聚合(Reduce)操作,获取想要的结果;
创建Stream方法

创建方法1:可以使用Arrays.stream()方法来使用Stream

Integer[] array = new Integer[]{3,4,8,16,19,27,23,99,76,232,33,96};
long count = Arrays.stream(array)
    .filter(i->i>20)
    .count();

创建方法2:使用List创建一个并行流对象Stream

Stream<Integer> stream = list.parallelStream();

Stream<Integer> stream = list.stream();

创建方法3:Collection.stream()用Java集合都创建一个Stream

2.3 Stream的一些方法

  • collect 收集操作,将所有数据收集起来,这个操作非常重要,官方的提供的Collectors 提供了非常多收集器,可以说Stream 的核心在于Collectors

  • count 统计操作,统计最终的数据个数

  • findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional

  • noneMatch、allMatch、anyMatch 匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值

  • min、max 最值操作,需要自定义比较器,返回数据流中最大最小的值

  • reduce 规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce

  • forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了

  • toArray 数组操作,将数据流的元素转换成数组。

  • map(mapToInt,mapToLong,mapToDouble) 转换操作符,把比如A->B,这里默认提供了转int,long,double的操作符

  • flatmap(flatmapToInt,flatmapToLong,flatmapToDouble) 拍平操作,比如把 int[]{2,3,4} 拍平变成 2,3,4 也
    就是从原来的一个数据变成了3个数据,这里默认提供了拍平成int,long,double的操作符

  • limit 限流操作,比如数据流中有10个只要出前3个就可以使用

  • distint 去重操作,对重复元素去重,底层使用了equals方法

  • filter 过滤操作,把不想要的数据过滤

  • peek 挑出操作,如果想对数据进行某些操作,如:读取、编辑修改等

  • skip 跳过操作,跳过某些元素

  • sorted(unordered) 排序操作,对元素排序,前提是实现Comparable接口,当然也可以自定义比较器。

扩展小芝士

  • 接口中只定义最基础的东西
  • 对hashSet的元素修改时最好先取出来改完后再放回去,他会重新计算hashCode然后重新定位
  • BigInteger的计算使用一个数组存着然后像手算一样来计算
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值