superT

Java泛型

天涯浪子 提交于 2021-02-11 23:00:33
之前面试和这两天用到泛型解决了一些问题,才发现自己对泛型的了解只停留用的时候会想起来一点点....没有真正的准确梳理泛型,所以想写一写总结一下自己对泛型对理解 1、代码用泛型的好处 在写代码的时候经常不同数据类型,而泛型可以统一数据类型,便于操作。 将运行时的异常提前到了编译时,提高了效率(在jdk1.5中引入了新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法类型)。 避免了强制类型转换。 实现代码到模版化,把数据类型当作参数传递,提高了可重用性。 2、泛型 泛型,其实是"参数化类型"。泛型的本质是 参数化类型 (在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。换句话说在泛型使用过程中,操作数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别成为泛型类,泛型参数,泛型方法。 在jdk 1.5之前,没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,这种转换需要开发者对实际参数类型可以预知的情况下进行。对于强制类型转换错误的情况,编译气可能不提示错误,在运行的时候才出现异常。这时候泛型的好处就体现出来,使用泛型就可以首先通过IDE进行代码类型初步检测,然后在编译阶段进行编译类型检查,保证了类型转换的安全性;并且所有的强制转换都是自动和隐式的

了不起的Java-CompletableFuture组合异步编程

喜欢而已 提交于 2021-02-04 07:05:51
在多任务程序中,我们比较熟悉的是分支-合并框架的并行计算,他的目的是将一个操作(比如巨大的List计算)切分为多个子操作,充分利用CPU的多核,甚至多个机器集群,并行执行这些子操作。 而CompletableFuture的目标是并发(执行多个操作),而非并行,是利用CPU的核,使其持续忙碌,达成最大吞吐,在并发进行中避免等待远程服务的返回值,或者数据库的长时查询结果等耗时较长的操作,如果解决了这些问题,就能获得最大的并发(通过避免阻塞)。 而分支-合并框架只是并行计算,是没有阻塞的情况。 Future接口 Future接口用于对将来某个时刻发生的结果进行建模,它建模了一种异步计算,返回一个执行结果的引用,计算完成后,这个引用被返回给调用方, 在使用Future时,将耗时操作封装在一个Callable接口对象中,提交给ExecutorService。 public interface Future<V> { boolean cancel( boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get( long timeout, TimeUnit unit) throws

Java并发包异步执行器CompletableFuture

て烟熏妆下的殇ゞ 提交于 2021-02-04 06:32:38
前言 CompletableFuture是对Future的一种强有力的扩展,Future只能通过轮询isDone()方法或者调用get()阻塞等待获取一个异步任务的结果,才能继续执行下一步,当我们执行的异步任务很多,而且相互之前还要依赖结果的时候,可能会创建很多这样的Future,并通过get或者轮询等待执行结果返回之后继续执行,这样的代码显得很不方便而且也不高效。 通过前面的CompletionStage接口给我们提供了一系列将多个阶段(甚至是异步的)的结果相互关联执行的方法,如果把它和Future结合起来,那么可将这种便利与高效编程方式用于异步任务的执行。CompletableFuture就是这样的一个类,同时继承了CompletionStage和Future,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过lambda表达式的风格处理各个执行阶段的结果。 实现 CompletableFuture通过以下策略实现了接口CompletionStage: 依赖的非异步阶段提供的操作可以由完成当前CompletableFuture的线程执行,也可以由完成方法的任何其他调用者执行。 所有没有显式指定Executor参数的异步方法都使用ForkJoinPool.commonPool执行(除非它不支持至少两个并行级别,否则将创建一个新线程来运行每个任务).为了简化监视

CompletableFuture异步编排

孤人 提交于 2021-01-23 05:26:17
什么是CompletableFuture CompletableFuture是JDK8提供的Future增强类。CompletableFuture异步任务执行线程池,默认是把异步任务都放在ForkJoinPool中执行。 在这种方式中,主线程不会被阻塞,不需要一直等到子线程完成。主线程可以并行的执行其他任务。 Future存在的问题 Future实际采用FutureTask实现,该对象相当于是消费者和生产者的桥梁,消费者通过 FutureTask 存储任务的处理结果,更新任务的状态:未开始、正在处理、已完成等。而生产者拿到的 FutureTask 被转型为 Future 接口,可以阻塞式获取任务的处理结果,非阻塞式获取任务处理状态。 使用 runAsync 和 supplyAsync方法 CompletableFuture 提供了四个静态方法来创建一个异步操作。 public static CompletableFuture<Void> runAsync(Runnable runnable) public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) public static <U> CompletableFuture<U> supplyAsync(Supplier<U>

异步神器CompletableFuture

廉价感情. 提交于 2021-01-22 04:47:05
介绍 上个礼拜我们线上有个接口比较慢,这个接口在刚开始响应时间是正常的。但随着数据量的增多,响应时间变慢了。 这个接口里面顺序调用了2个服务,且2个服务之间没有数据依赖。我就用CompletableFuture把调用2个服务的过程异步化了一下,响应时间也基本上缩短为原来的一半,问题解决。 正好上次分享了函数式接口和Stream的使用,这次就分享一下CompletableFuture,里面也用到了大量的函数式接口 想方便的异步执行任务,就必须放到单独的线程中。继承Thread类,实现Runnable都不能拿到任务的执行结果,这时就不得不提创建线程的另一种方式了,实现Callable接口。 @FunctionalInterface public interface Callable < V > { V call () throws Exception ; } Callable接口一般配合ExecutorService来使用 // ExecutorService.java <T> Future<T> submit (Callable<T> task) ; ExecutorService executor = Executors.newCachedThreadPool(); Future<Integer> result = executor.submit(() -> { int sum =

Arraylist 与 LinkedList 异同

大城市里の小女人 提交于 2021-01-09 08:08:28
1. 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; 2. 底层数据结构: Arraylist 底层使用的是Object数组;LinkedList 底层使用的是双向链表数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。注意双向链表和双向循环链表的区别:); 详细可阅读JDK1.7-LinkedList循环链表优化 https://www.cnblogs.com/xingele0917/p/3696593.html 3. 插入和删除是否受元素位置的影响: ① ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行 add(E e) 方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话( add(int index, E element) )时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。 4. 是否支持快速随机访问: LinkedList

[从今天开始修炼数据结构]队列、循环队列、PriorityQueue的原理及实现

删除回忆录丶 提交于 2020-12-25 18:13:48
[从今天开始修炼数据结构]基本概念 [从今天开始修炼数据结构]线性表及其实现以及实现有Itertor的ArrayList和LinkedList [从今天开始修炼数据结构]栈、斐波那契数列、逆波兰四则运算的实现 [从今天开始修炼数据结构]队列、循环队列、PriorityQueue的原理及实现 一、什么是队列   队列queue是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。   队列是先进先出的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。如下图所示      例如聊天室消息发送就是队列形式,先发出去的消息会先显示,后发的会后显示。 二、队列的抽象数据类型   队列的抽象数据类型与线性表的基本相同,只不过插入删除的位置有限制。 ADT Queue Data 同线性表,相邻的元素具有前驱后继关系 Operation InitQueue( * Q):初始化操作 DestroyQueue( * Q):若队列Q存在,销毁他 ClearQueue( * Q):将队列Q清空 QueueEmpty(Q):若队列Q为空,返回true,否则返回false GetHead(Q, * e):若Q存在且非空,用e返回队首元素 EnQueue( * Q,e):若Q存在,插入新元素e到队尾 DeQueue( *Q,* e):删除Q中的队首元素,并用e返回其值

java的集合工具类Collections

与世无争的帅哥 提交于 2020-12-17 15:48:57
集合框架的工具类。 Collections: 集合框架的工具类。里面定义的都是静态方法。 Collections 和 Collection 有什么区别? Collection 是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。 它有两个常用的子接口 : List :对元素都有定义索引。有序的。可以重复元素。 Set :不可以重复元素。无序。 Collections 是集合框架中的一个工具类。该类中的方法都是静态的 提供的方法中有可以对 list 集合进行排序,二分查找等方法。 通常常用的集合都是线程不安全的。因为要提高效率。 如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。 Collections 常用方法 排序 static <T extends Comparable<? super T>> void sort(List<T> list) 根据元素的自然顺序 对指定列表按升序进行排序 <T extends Comparable> 要排序的对象必须是 Comparable 的子类 static <T> void sort(List<T> list, Comparator<? super T> c) 根据指定比较器产生的顺序对指定列表进行排序。 自定义比较器排序 最大值最小值 static <T extends Object &

java8 Stream的实现原理 (从零开始实现一个stream流)

岁酱吖の 提交于 2020-11-26 07:50:17
1.Stream 流的介绍 1.1 java8 stream介绍   java8新增了stream流的特性,能够让用户以函数式的方式、更为简单的操纵集合等数据结构,并实现了用户无感知的并行计算。 1.2 从零开始实现一个stream流   相信很多人在使用过java8的streamAPI接口之后,都会对其实现原理感到好奇,但往往在看到jdk的stream源码后却被其复杂的抽象、封装给弄糊涂了,而无法很好的理解其背后的原理。究其原因,是因为jdk的stream源码是高度工程化的代码,工程化的代码为了效率和满足各式各样的需求,会将代码实现的极其复杂,不易理解。   在这里,我们将抛开jdk的实现思路, 从零开始实现一个stream流 。   我们的 stream流 同样拥有 惰性求值 , 函数式编程接口 等特性,并 兼容jdk的Collection等数据结构 (但不支持并行计算 orz)。   相信在亲手实现一个stream流的框架之后,大家能更好的理解流计算的原理。 2.stream的优点   在探讨探究stream的实现原理和动手实现之前,我们先要体会stream流计算的独特之处。   举个例子: 有一个List<Person>列表,我们需要获得年龄为70岁的前10个Person的姓名。 过程式的解决方案:    稍加思考,我们很快就写出了一个过程式的解决方案( 伪代码 ):

RxJava

ε祈祈猫儿з 提交于 2020-11-19 04:03:43
一 RxJava 的原理 RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。 1.创建一个简单的Observable public class Observable<T> { final OnSubscribe<T> onSubscribe; private Observable(OnSubscribe<T> onSubscribe) { this .onSubscribe = onSubscribe; } public static <T> Observable<T> create(OnSubscribe<T> onSubscribe) { return new Observable<T> (onSubscribe); } public Subscriber subscribe(Subscriber<? super T> subscriber) { // 是 Subscriber 增加的方法 事件还未发送之前执行,用于数据清零或重置 // 如果对线程有要求,要求在主线程上就只能用doOnSubscribe