parentage 来标明这种关系,作用是避免 B subscription 被同一个 subscription重复订阅的问题,Subscription 里定义了几个方法用于管理 _parentage 的数据...结束输出unsubscribe有订阅就有取消订阅,unsubscribe主要用作执行一些清理动作,例如执行在 subscribe 的时候收集到的 teardown,以及更新 _parentage 的数据...subscription1 = observable.subscribe(d => console.log(d))subscription1.unsubscribe()// 开始输出// 1// 取消订阅时执行...,但从方法名上来说显然更加语义化// node_modules/rxjs/src/internal/lastValueFrom.tsexport function lastValueFrom...,官方源码中的注释也非常详细(甚至在注释里写 example),简直就是在文档里写代码,再加上 ts的助攻,可以说源码看起来没啥难度,当然了,这只是 rxjs 系统中两个最基础的概念,一般情况下使用 rxjs
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。...当具体的类型确定后,泛型又提供了一种类型检测的机制,只有相匹配的数据才能正常的赋值,否则编译器就不通过。所以说,它是一种类型安全检测机制,一定程度上提高了软件的安全性防止出现低级的失误。...你可以相像一下,当一个泛型类被创建时,内部自动扩展成下面的代码。...我们可以看到,当 存在时,Collection 对象丧失了 add() 方法的功能,编译器不通过。 我们再看代码。 List<?...泛型中值得注意的地方 泛型类或者泛型方法中,不接受 8 种基本数据类型。 所以,你没有办法进行这样的编码。
Hash 表hash 表也称散列表(Hash table)哈希表是一种根据关键码去寻找值的数据映射结构也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度HashCodeHashCode...图片为什么不直接把 key 和 value 放到数组当中,我们想要把数据放到数组当中,如果按角标的顺序进行存放,可以这样存放如下图。...index : -index; } @Override public V get(K k) { // 1.判断当前集合中有没有元素,如果没有就直接返加null...图片图片图片图片图片图片图片图片图片图片图片图片图片图片图片图片造成就两个节点互样指向,变成了双向链表,在 put 元素时,循环会一直结束不了。...= 8:树化的阈值,当某个桶节点数量大于 8 时,会转换为红黑树,查询效率提高UNTREEIFY_THRESHOLD = 6:当某个桶节点数量小于 6 时,会转换为链表,前提是它当前是红黑树结构图片1.8
offer()和add()都可以 在容量有限的 PriorityQueue 中,offer() 更安全,因为它会在队列已满时返回 false,而 add() 会抛出 IllegalStateException...b{ (b.compareTo(a) } 花括号中是负数,创建的是大根堆 这个式子等价于 (a,b)-> (b-a) 4:为什么...if条件中用的是equals()方法,而不是==,因为Integer是int的包装类型,是一个对象,==比较的是对象的引用地址值,equals()才能比较对象中属性的值 5:如果使用idea,没有内置...0 : heap.peek(); } } 三:数据流中的第k大元素 心得: 1:这道题可以体会全局成员变量的好处 2:老实说这个题目读完题,给我一种无从下手的感觉,写完代码后豁然开朗,...数据流的中位数 心得: 1:用大小根堆来处理数据流的中位数问题,算是开拓思路了 2:暴力解法就是用每次add一个元素之后就Arrays.sort();一下 class MedianFinder {
那为什么还弄出来这么个方法呢?...,不同的版本稍有不同: 在 JDK1.6 和 1.7 中,是用链表存储的,这样如果碰撞很多的话,就变成了在链表上的查找,worst case 就是 O(n); 在 JDK 1.8 进行了优化,当链表长度较大时...这是因为 Java 5.0 之后允许数据结构不考虑线程安全的问题,因为实际工作中我们发现没有必要在数据结构的层面上上锁,加锁和放锁在系统中是有开销的,内部锁有时候会成为程序的瓶颈。...所以 HashMap, ArrayList, StringBuilder 不再考虑线程安全的问题,性能提升了很多,当然,线程安全问题也就转移给我们程序员了。...比如说 “I love leetcode, I love coding” 中频率最高的 2 个就是 I 和 love 了。
原来数组中的元素依次重新计算存放位置,并重新插入 插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容) 当Map中元素总数超过Entry数组的75%,触发扩容操作...,为了减少链表长度,元素分配更均匀 为什么说HashMap是线程不安全的?...前面说过HashMap的key是允许为null的,当出现这种情况时,会放到table[0]中。...为什么这里需要将高位数据移位到低位进行异或运算呢?这是因为有些数据计算出的哈希值差异主要在高位,而HashMap里的哈希寻址是忽略容量以上的高位的,那么这种处理就可以有效避免类似情况下的哈希碰撞。...一般情况下我们选用HashMap,因为HashMap的键值对在取出时是随机的,其依据键的hashCode和键的equals方法存取数据,具有很快的访问速度,所以在Map中插入、删除及索引元素时其是效率最高的实现
0 : e.getValue().hashCode()) 确保两个 Entry对象 equals返回true,则hashcode的值必然相同 equals 方法 当两个entry对象表示的是同一个映射关系时...元素 3....Node[] table; 说明 按我们的理解,map是一个kv结构,每个Node对象表示的就是一个kv对,那么这个table应该就是保存所有的kv对的数据结构了 为什么会是一个数组?...的存储结构 当出现hash碰撞时,即对于计算key的hash值相同的Node节点,以链表结构存在 ?...初始化 数组的初始化延迟在首次向Map中添加元素时进行 默认数组长度为16,阀值为12 阀值定义为: The next size value at which to resize (capacity *
这里可以看出,如果每个桶内部只有一个元素,那么查找的时候只有一次比较。当许多桶内没有值时,许多查询就会更快了(指查不到的时候). 由此可见,要实现哈希表, 和用户相关的是:hash函数和比较函数。...不过需要注意的是,当你使用[key ]操作符时,如果容器中没有key元素,这就相当于自动增加了一个key元素。因此当你只是想知道容器中是否有key元素时,你可以使用find。...如果你希望插入该元素时,你可以直接使用[]操作符。 ⑫ 插入 insert 函数。 在容器中不包含key值时,insert函数和[]操作符的功能差不多。...但是当容器中元素越来越多,每个桶中的元素会增加,为了保证效率,hash_map会自动申请更大的内存,以生成更多的桶。因此在insert以后,以前的iterator有可能是不可用的。...HashMap内存储数据的Entry数组默认是16,如果没有对Entry扩容机制的话,当存储的数据一多,Entry内部的链表会很长,这就失去了HashMap的存储意义了。
1.HashMap底层数据结构如何? 2.HashMap如何保存数据,增删改咋实现? 3.HashMap如何扩容? 4.为什么扩容的大小一定要是2的整数次幂,也就是2的N次方....在JDK1.7.0_45版本中,当首次put(新增)元素时,会新建一个容量为16的Entry[]数组赋值给table属性; DEFAULT_LOAD_FACTOR是HashMap扩容的关键参数,当HashMap...中形成链表的可能性更低; 而当length为奇数时,length-1为偶数,转换成二进制的话最后一位是0。...null : entry.getValue(); } //获取hashMap中key为 null的value值: private V getForNullKey() { //hashmap中没有元素...size--; //当为链表的第一个元素时,直接将下一个元素顶到链表头部: if (prev == e) table[i]
不知道大家有没有想过为什么对于一些数据结构(数组、ArrayList 等)可以使用 for each 语句去遍历它,其实就是通过这个 Iterable 接口来实现的,在这个接口中有一个用于产生 Iterator...一个都没有吗?是的,你没有看错,Set 接口中存在的方法都是 Collection 接口中已经声明的,那么为什么 Set 接口中没有新增的方法呢?...我们都直接可以通过下标来得到对应元素,因此通过线性结构的这种特性,我们可以新增一些更加具体的方法比如说获取线性结构中指定下标的元素(get(int index))等。...映射到我们正在学习的集合框架来说,这三个特性已经在 Collection 接口中提供了对应的方法,因此 Set 接口中没有提供另外的方法。那么为什么还要多写这么一个接口呢?...0 : e.getValue().hashCode()) * * 设计 hashCode 方法时,确保当两个对象的 equals 方法返回 true 时, *
: extern int array[]; 此时的array就是一个不完全类型的数组,一般这样的数组声明会放在.h中,而其定义放在.c中,在定义的时候在给出数组的具体长度,若之后有需要改变数组的长度时,...当程序执行到这些语句时,才为其分配。程序员自己负责释放内存。使用动态数组的优点是可以根据用户需要,有效利用存储空间。 (1)结构体实体定义在头文件中 比如我们本次的demo有如下三个文件: ?...我们创建了一些接口函数来操作DA对象,我们希望他人可以使用我们的这些接口来操作数据。并且,一般我们使用其它人写的代码时,一般也是优先找到相关头文件,然后调用头文件里提供的对外接口函数。...命名有接口可以用,却偏偏有人喜欢直接操作数据,这是比较容易出错的做法。而且此时调用者推锅的理由很充足:你暴露数据给我,我为什么不可以直接操控你的数据,我就不喜欢用你提供的接口,咋的。。。 ?...*/ int DA_GetValue(dynamic_array_def *pThis, size_t index, int *pValue) { if (index > pThis->len
通过在代码中使用泛型,我们可以清楚地看到数据的类型,从而更好地理解代码的含义和逻辑。这对于团队合作或长期维护代码来说非常重要。 让我通过一个简单的示例来说明为什么使用泛型。...而且,当我们需要打印其他类型的数据时,还需要继续添加新的重载方法。...强制类型检查:通过在编译时进行类型检查,可以尽早地捕获类型错误,确保数据类型的正确性。 5. 减少类型转换:使用泛型可以避免我们在代码中进行频繁的类型转换。...当使用泛型时,我们可以在类或方法的定义中使用泛型类型参数来代表具体的类型。下面我将分别介绍泛型类和泛型方法; 1. 泛型类的使用: 泛型类可以在类的定义中使用类型参数来代表具体的类型。...也就是说,编译后的代码会变成: public class MyGenericClass { private Object value; public Object getValue
-》 O(log n),如果数组长度没有满足,那么就会对数组进行一个扩容操作 前提:数据结构为数组加链表(尾插法)或红黑树 1.添加元素,计算key的哈希值,通过运算找到数组索引位置 2.判断索引位置是否为空...(默认为0.75),直接将数组长度扩容到原来的两倍 怎么扩容的: 判断可以进行扩容时,那么会计算出新数组的长度(长度为旧数组的两倍),当然如果没有满足实际扩容要求,还是需要继续2倍,直到满足长度后,创建一个新数组...在jdk1.8,解决了Entry死循环和数据丢失问题,但是在多线程背景下出现了新的问题put方法数据覆盖问题 分析:为什么jdk1.7会出现该问题,首先要了解jdk1.7链表添加一个元素采用的是头插法...将头插法换成尾插法,保证了顺序 分析:为什么jdk1.8会出现put方法覆盖问题,HashMap本身是线程不安全的集合,并发执行put方法肯定会出现问题 解释:当线程1将key计算出数组索引位置,判断为空...采用的是对头节点进行加锁,锁的粒度更小,并且引入红黑树,大大增加了性能 2.Set集合 2.1.特点 不可重复,元素唯一 2.2.原理 其实就是在计算添加元素的哈希值时,如果发现有哈希值一样的,会使用equals
什么是泛型 Java泛型是J2SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter),这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类...为什么使用泛型 一般我在思考这种问题时,会反过来思考,假如没有泛型会怎么样?...,List默认是Object类型,所以List里的元素可以是任意的,看起来集合里装着任意类型的参数是“挺不错”,但是任意的类型的缺点也是很明显的,就是要开发者对集合中的元素类型在预知的情况下进行操作,否则编译时不会提示错误...如果没有泛型,第二个小问题是,我们把一个对象放进了集合中,但是集合并不会记住这个对象的类型,再次取出时统统都会变成Object类,但是在运行时仍然为其本身的类型。...public 接口名称 { 泛型标识 方法名(); } 示例: public interface Generator { T next(); } 当实现泛型接口不传入实参时
是因为Java给我们做了一个偷懒性的拷贝动作,Object类原本就提供一个方法clone用来拷贝对象,因为其对象内部的数组、引用对象等都不拷贝,还是指向了原生对象的内部元素地址,这种拷贝就叫做浅拷贝。...为什么没有变化呢? 原始数据类型会被拷贝,如果从原始数据类型考虑,因为age是int类型,int是原始数据类型,所以上述场景没变,那也就无话可说,但是String并不是原始数据类型,那又是为什么呢?...所以String并没有clone方法。...implements java.io.Serializable, Comparable, CharSequence { //...省略其他 } 这段代码编译通不过,提示无法访问,为什么呢...相互之间没有什么关系了,你修改你的,我修改我的,完全不会有什么安全问题。这就是深拷贝。 深拷贝还有一种实现方式:通过写自己的二进制流来操作对象,然后实现对象的深拷贝。