java基础之多线程与Lambda表达式
一、Lambda表达式
Java从1.8以后引入了函数式编程,这是很大的一个改进。函数式编程的优点在提高编码的效率,增强代码的可读性。本文历时两个多月一点点写出来,即作为心得,亦作为交流。
1、无参和返回值
这样写非常的简单,其实就是简化我们的代码量,可以提供性能。
2、有且只能定义一个方法
3、有参实现
4、函数式接口
以上的接口必须是一个,java8出现了一个新的注解
- 只能写一个方法
6、default关键字的复习
二、java多线程
(一)线程概念
1、进程与线程
(1)进程概念
(2)线程概念
举个例子康康
进程与进程和进程与线程
所以得到概念为
看一下传统的进程使用资源情况
现代操作系统的情况
查看CPU的一些信息
(二)线程实现
1、多线程实现分析
1)Thread实现多线程
(1)概念部分
package java.lang.Thread,是jdk1.0就提供了。
(2)启动多线程
- 看一下错误的调用
- 看一下正确情况
- 分析原因
public synchronized void start() {/*** This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionality added* to this method in the future may have to also be added to the VM.** A zero status value corresponds to state "NEW".*///有一个异常抛出,但是没有强制要求处理,因为该异常是RuntimeExceptionif (threadStatus != 0)throw new IllegalThreadStateException();/* Notify the group that this thread is about to be started* so that it can be added to the group's list of threads* and the group's unstarted count can be decremented. */group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}}
private native void start0();
- 异常分析
- start0分析
- 启动总结
2)Runnable实现多线程
(1)看概念
package java.lang.Runnable
(2)实现多线程
- 这样编写
(3)分析此时多线程的启动(和Thread构造方法)
通过这里发现都是去调用了init方法,再去看init方法
(3)既然是函数式接口,那就Lambda上
3)Thread与Runnable之间的关系
(1)明白继承关系
public class Thread implements Runnable
- 这样启动都是一个接口
使用Thread类也同样可以实现数据的共享
(2)小总结
4)使用Callable实现多线程
它是在这个包下:import java.util.concurrent.*;
(1) 传统Runnable存在的问题
(2)看看callable接口
- 来看看Future接口
(3)再来看继承关系
- 再来看RunnableFuture的实现类
- 再来看继承关系
(4)Callable实现多线程
(三)多线程的操作
1)多线程的运行状态(生命周期)
其实就操作系统里面学的
(1)看图分析
(2)过程分析
2)线程命名和取得以及方法的使用
(1)构造方法
public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);}Thread(Runnable target, AccessControlContext acc) {init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);}public Thread(ThreadGroup group, Runnable target) {init(group, target, "Thread-" + nextThreadNum(), 0);}public Thread(String name) {init(null, null, name, 0);}public Thread(ThreadGroup group, String name) {init(group, null, name, 0);}
不详细介绍了
(2)获取线程名称
(3)设置或修改线程名称
强烈不建议这样进行修改操作
当我们设置的名字的时候
当我们不进行手动设置名字的时候呢【为什么能自动编号呢】
原因其实就是如下
观察线程的获取
进程分析
经过分析可以发现,都在看各个线程的概念,咱们程序的核心问题,所有的线程都是在进程里面创建的,那进程在哪里呢?答案其实很简单,每当java命令运行一个类的时候就会在操作系统的内部为其分配一个进程,而现在所有的程序执行的时候都是基于线程的方式运行的,其中会由JVM帮助用户手工创建一个主线程(main),而后再由主线程创建若干个线程。
(4)线程休眠
看一下方法
看一下异常继承关系
线程休眠【如下处理就感觉线程A和B是一起执行的一样,这是为什么呢】
(5)线程中断
- 看点概念
- 它有如下的一些方法
(5)线程的强制执行
正常情况下我们是多个线程在竞争去抢夺,但是有特殊情况下,某个线程会强制抢夺。
public class MyThread {public static void main(String[] args) throws InterruptedException {Thread mainThread = Thread.currentThread();Thread joinThread = new Thread(() -> {for (int i = 0; i < 10000; i++) {if (i > 10) {try {Thread.sleep(1000);//只要满足i>10那就要把所有的资源交给主线程处理mainThread.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + "子线程");}},"线程A");joinThread.start();for (int i = 0; i < 1000; i++) {Thread.sleep(1000);System.out.println("当前主线程" + mainThread);}}}
(6)线程礼让
- 像这样的话就感觉差不多是交替执行的【仅仅是感觉】
- 礼让情况
public class MyThread {public static void main(String[] args) throws InterruptedException {Thread mainThread = Thread.currentThread();Thread joinThread = new Thread(() -> {for (int i = 0; i < 10000; i++) {try {if ( i % 2 == 0) {Thread.yield();System.out.println("应该是礼让线程执行");}Thread.sleep(1000);System.out.println(Thread.currentThread().getName() + "子线程");} catch (Exception e) {}}},"线程A");joinThread.start();for (int i = 0; i < 1000; i++) {Thread.sleep(1000);System.out.println("当前主线程" + mainThread);}}}
(7)线程优先级
- 首先模拟三个线程执行
- 主方法(主线程)决定了子线程的优先级
- 优先是可以修改的,在线程启动之前。【你设置了也不起什么卵用】
优先级高的,有可能先执行,仅仅是有可能。
(四)线程同步与死锁
1、同步问题
1)问题的引入
多线程的引入是在为了能在尽可能的提高效率,但是操作不当是会出现问题的。
- 创建5个线程进行卖票处理
并不是加入了延迟才会出现这个问题,仅仅是更加明显而已。
能让问题更加明显的原因是我们线程休眠正好处于了修改和检查的期间,所以更加明显。
当最后一张票被5个线程抢着了,同时对原来的数据进行减1,那就会出现了这个了。
2)线程同步处理
(1)使用同步代码块来解决
- 可以采用synchronized(同步对象) {业务逻辑}
- 也可以这样写
class Thread1 implements Runnable {private Integer ticket = 5;@Overridepublic void run() {//线程运行的主方法synchronized(this) {while (true) {if (ticket > 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "正在卖票" + "当前剩余票数" + (--ticket));} else {break;}}}}
}public class MyThread {public static int ticket = 5;public static void main(String[] args) throws InterruptedException {Thread1 thread1 = new Thread1();for (int i = 0; i < 5; i++) {new Thread(thread1,"售票机" + i).start();}}
}
(2)使用同步方法实现
public class MyThread {public static int ticket = 5;public static void main(String[] args) throws InterruptedException {Thread1 thread1 = new Thread1();for (int i = 0; i < 5; i++) {new Thread(() -> {hello();},"售票机" + i).start();}}public static synchronized boolean hello() {while (true) {if (ticket > 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "正在卖票" + "当前剩余票数" + (--ticket));return true;} else {return false;}}}
}
2、线程死锁
class Book {//描述的书资源}class Paint {//描述回话资源}public class LockTest {public static void main(String[] args) {Book book = new Book();Paint paint = new Paint();Thread threadA = new Thread(() -> {synchronized(book) {System.out.println("A对B说,你借给我回话资源,我再给你书资源");try {Thread.sleep(10000);//现在A要锁paint资源synchronized(paint) {System.out.println("A得到了回话资源");}} catch (InterruptedException e) {e.printStackTrace();}}},"线程A");Thread threadB = new Thread(() -> {synchronized(paint) {System.out.println("B对A说,你借给我书资源,我再给你回话资源");try {Thread.sleep(10000);//现在A要锁paint资源synchronized(book) {System.out.println("B得到了书资源");}} catch (InterruptedException e) {e.printStackTrace();}}},"线程B");threadA.start();threadB.start();}
}
只有用点工具进行监控,现实生活中很难预测。
- 结论:多个线程更新同一资源的时候必须考虑到同步,而且同步所带来的问题就是线程的死锁。
3、生产者和消费者
1)生产者和消费者模型
(1)看概念
(2)类结构分析
2)代码操作模型
(1)代码实现
class Message {private String title;private String content;public Message(String title,String content) {this.title = title;this.content= content;}public Message() {}public void setContent(String content) {this.content = content;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public String getTitle() {return title;}}class Producer implements Runnable {Message message;public Producer(Message message) {this.message = message;}@Overridepublic void run() {try {for (int i = 0; i < 50; i++) {//生成50个产品if (i % 2 == 0) {message.setTitle("你");Thread.sleep(1000);message.setContent("好");} else {message.setTitle("不");Thread.sleep(1000);message.setContent("hao");}}} catch (Exception e) {e.printStackTrace();}}
}class Consumer implements Runnable {Message message;public Consumer(Message message) {this.message = message;}@Overridepublic void run() {try {for (int i = 0; i < 50; i++) {System.out.println("消费者 title" + this.message.getTitle() + "content = " + this.message.getContent());Thread.sleep(1000);}} catch (Exception e) {}}
}public class mainClass {public static void main(String[] args) {Message message = new Message();new Thread(new Producer(message)).start();new Thread(new Consumer(message)).start();}
}
- 观察结果
这些问题并不是加上sleep才会出现问题的,仅仅是我们现在电脑比价牛逼,不加sleep很少出现问题。
(2)类结构分析
(3)解决数据同步问题
- 问题分析
- 代码实现
package cn.mldn.Juc.producerAndcustomer;class Message {private String title;private String content;public Message(String title,String content) {this.title = title;this.content= content;}public Message() {}public synchronized void setContentAndsetTitle(String content,String title) {this.content = content;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}this.title = title;}public synchronized String GetString() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "Message{" +"title='" + title + '\'' +", content='" + content + '\'' +'}';}
}class Producer implements Runnable {Message message;public Producer(Message message) {this.message = message;}@Overridepublic void run() {try {for (int i = 0; i < 50; i++) {//生成50个产品if (i % 2 == 0) {message.setContentAndsetTitle("绝地","求生");Thread.sleep(10000);} else {message.setContentAndsetTitle("王者","荣耀");Thread.sleep(1000);}}} catch (Exception e) {e.printStackTrace();}}
}class Consumer implements Runnable {Message message;public Consumer(Message message) {this.message = message;}@Overridepublic void run() {try {for (int i = 0; i < 50; i++) {System.out.println(this.message.GetString());Thread.sleep(1000);}} catch (Exception e) {}}
}public class mainClass {public static void main(String[] args) {Message message = new Message();new Thread(new Producer(message)).start();new Thread(new Consumer(message)).start();}
}
- 看结果分析:有重复生产和重复消费
(4)解决线程重复操作问题
问题分析和方法学习
显示肯定不用这种来处理,具体的可以学习JUC内容代码实现
class Message {private String title;private String content;boolean flag = true;//等于true为可以生产,不可以消费。为false,可以消费,不可以生产public Message(String title,String content) {this.title = title;this.content= content;}public Message() {}public synchronized void setContentAndsetTitle(String content,String title) {if (this.flag == false) {try {//说明有消费者线程在执行,等消费者线程执行完毕后唤醒super.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.content = content;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}this.title = title;//生产完成后,把消费者线程唤醒this.flag = false;super.notify();//唤醒其他线程}public synchronized String GetString() {if (flag == true) {try {//说明生产者线程在执行,等待生成完成后被唤醒super.wait();} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//消费完成后,把生产者线程唤醒this.flag = true;super.notify();return "Message{" +"title='" + title + '\'' +", content='" + content + '\'' +'}';}
}class Producer implements Runnable {Message message;public Producer(Message message) {this.message = message;}@Overridepublic void run() {try {for (int i = 0; i < 50; i++) {//生成50个产品if (i % 2 == 0) {message.setContentAndsetTitle("绝地","求生");Thread.sleep(1000);} else {message.setContentAndsetTitle("王者","荣耀");Thread.sleep(1000);}}} catch (Exception e) {e.printStackTrace();}}
}class Consumer implements Runnable {Message message;public Consumer(Message message) {this.message = message;}@Overridepublic void run() {try {for (int i = 0; i < 50; i++) {System.out.println(this.message.GetString());Thread.sleep(1000);}} catch (Exception e) {}}
}public class mainClass {public static void main(String[] args) {Message message = new Message();new Thread(new Producer(message)).start();new Thread(new Consumer(message)).start();}
}
- 观察结果
3)优雅的停止线程
- 停止多线程
(五)线程相关其他知识
1、守护线程
概念
常用方法
代码观察
package cn.mldn.Juc.class1;class Message implements Runnable {public Message() {Thread thread = new Thread(() -> {for (int i = 0; i < Integer.MAX_VALUE; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("守护线程执行");}});thread.setDaemon(true);//设置Thread线程为守护线程thread.start();}@Overridepublic void run() {for (int i = 0; i < Integer.MAX_VALUE; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("当前线程执行" + Thread.currentThread().getName() + "执行");}}
}public class WatchThread {public static void main(String[] args) {new Thread(new Message()).start();}
}
- 案例分析
2、volatile关键字
- 观察代码和结果
package cn.mldn.Juc.class1;class Message implements Runnable {private volatile int ticket = 3;@Overridepublic void run() {while (true) {if (ticket > 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("剩余票数位" + (--this.ticket));} else {break;}}}
}public class WatchThread {public static void main(String[] args) {Message message = new Message();new Thread(message,"机器A").start();new Thread(message,"机器B").start();}
}
那既然它实现不了同步,那这关键字有什么用呢?
volatile正确使用格式
package cn.mldn.Juc.class1;class Message implements Runnable {private volatile int ticket = 3;@Overridepublic void run() {while (sale()) {}}public synchronized boolean sale() {if (ticket > 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("剩余票数位" + (--this.ticket));return true;} else {return false;}}
}public class WatchThread {public static void main(String[] args) {Message message = new Message();new Thread(message,"机器A").start();new Thread(message,"机器B").start();}
}
3、线程加减面试题
- 问题是:设计4个线程,两个实现加操作,另外两个实现减操作。
package cn.mldn.Juc.class1;class Message1 {private int number = 0;public synchronized void add() {//1判断while (number == 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//2干活number++;System.out.println(Thread.currentThread().getName() + "完成工作" + number);//3通知this.notifyAll();}public synchronized void sub() {//1判断while (number != 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//2干活number--;System.out.println(Thread.currentThread().getName() + "完成工作" + number);//3通知this.notifyAll();}
}public class InterviewTest {public static void main(String[] args) {Message1 message = new Message1();new Thread(() -> {for (int i = 0; i < 10; i++) {message.add();}},"一号加法线程").start();new Thread(() -> {for (int i = 0; i < 10; i++) {message.add();}},"二号加法线程").start();new Thread(() -> {for (int i = 0; i < 10; i++) {message.sub();}},"三号减法线程").start();new Thread(() -> {for (int i = 0; i < 10; i++) {message.sub();}},"四号减法线程").start();}
}
4、电脑生产面试题
package cn.mldn.Juc.class1;class Computer {private String brand;//电脑品牌private double price;//电脑价格public Computer(String brand,double price) {this.brand = brand;this.price = price;}@Overridepublic String toString() {return "Computer{" +":品牌=" + brand + '\'' +":价格=" + price +'}';}
}class Resource {private int number = 0;//公共资源电脑数量private Computer computer = null;//当前电脑public Resource() {Thread numberDaemonThread = new Thread(() ->{while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("后台统计线程在统计电脑,当前生产电脑数量为= " + this.number);}});numberDaemonThread.setDaemon(true);numberDaemonThread.start();}public synchronized void create(String brand,double price) {//首先判断(如果为空,等待消费while (this.computer != null) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//干活this.computer = new Computer(brand,price);this.number ++;System.out.println("" + Thread.currentThread().getName() + "完成电脑生产完成");//通知我生产好啦this.notifyAll();}public synchronized void decreate() {//首先判断(如果为空,等待生产while (this.computer == null) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//干活try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("" + Thread.currentThread().getName() + "完成搬运");this.computer = null;//通知我生产好啦this.notifyAll();}
}public class ComputerTest {public static void main(String[] args) {Resource resource = new Resource();new Thread(() -> {for (int i = 0; i < 50; i++) {if (i % 2 == 0) {resource.create("惠普",6000.00);} else {}}},"生产线程").start();new Thread(() -> {for (int i = 0; i < 50; i++) {if (i % 2 == 0) {resource.decreate();} else {}}},"搬运线程").start();}
}
5、竞拍抢答面试题
package cn.mldn.Juc.class1;import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;class Resource1 implements Callable<String> {private boolean flag;//抢答结果状态@Overridepublic String call() throws Exception {Thread.sleep(1000);//由于我们要每个线程进行先后执行synchronized(this) {if (this.flag == false) {this.flag = true;return Thread.currentThread().getName() + "抢答成功";} else {return Thread.currentThread().getName() + "抢答失败";}}}
}public class CallableInterview {public static void main(String[] args) {Resource1 resource = new Resource1();FutureTask<String> futureTask = new FutureTask<>(resource);FutureTask<String> futureTask1 = new FutureTask<>(resource);FutureTask<String> futureTask2 = new FutureTask<>(resource);new Thread(futureTask,"抢答人A").start();new Thread(futureTask1,"抢答人B").start();new Thread(futureTask2,"抢答人C").start();}
}
三、最后补充一下JUCSaleTicket
1、概念
并发:多个线程去抢占同一个资源
并行:两件事情同时进行【你在看视频和做笔记】
2、JUC的三个包
java.util.concurrent
java.util.concurrent.atomic
java.util.concurrent.locks
3、如何编写企业家多线程
在高内聚低耦合的前提下,线程,操作,资源类
1)Lock介绍
- 首先说说为什么需要Lock
我们实现同步第一想到的应该都是synchronized加到方法或者方法的内部实现同步,以实现数据的唯一性,但是它是重量级的,一旦锁了就把整个方法都锁住了(这样可以把synchronized加到方法内,以实现数据的共享而不出问题),但是synchronized是比较重量级的,锁就把内部完全给锁住了并发性就不行了,重量级了不行。所以就会有了Lock来处理。Lock可以实现可重复锁,性能更高效。
(1)实现30张卖票程序分析
- 来看一下Lock的莫办
- 看看代码
package cn.mldn.Juc.class2;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;public class SaleTicket {public static void main(String[] args) {//在高内聚低耦合的前提下(其实就是一个类,如果想去操作,必须去通过方法去调用)//1、先创建资源类(在高内聚低耦合的前提下)Ticket ticket = new Ticket();//2、创建线程 3、操作new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 40; i++) {ticket.sale();}}},"线程1").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 40; i++) {ticket.sale();}}},"线程2").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 40; i++) {ticket.sale();}}},"线程3").start();}
}class Ticket {//资源类就是一个类[内聚就是要聚变量]private int number = 30;Lock lock = new ReentrantLock();public void sale() {lock.lock();try {if (number > 0) {System.out.println(Thread.currentThread().getName() + "卖出" + (number --) + "还剩下:" + number);}} catch (Exception e) {} finally {lock.unlock();}}}
- 看看简洁版
public class SaleTicket {public static void main(String[] args) {//在高内聚低耦合的前提下(其实就是一个类,如果想去操作,必须去通过方法去调用)//1、先创建资源类(在高内聚低耦合的前提下)Ticket ticket = new Ticket();//2、创建线程 3、操作new Thread(() -> {for (int i = 0; i < 40; i++) {ticket.sale();}},"线程3").start();new Thread(() -> {for (int i = 0; i < 40; i++) {ticket.sale();}},"线程2").start();new Thread(() -> {for (int i = 0; i < 40; i++) {ticket.sale();}},"线程1").start();}
}class Ticket {//资源类就是一个类[内聚就是要聚变量]private int number = 30;Lock lock = new ReentrantLock();public void sale() {lock.lock();try {if (number > 0) {System.out.println(Thread.currentThread().getName() + "卖出" + (number --) + "还剩下:" + number);}} catch (Exception e) {} finally {lock.unlock();}}}
java基础之多线程与Lambda表达式相关推荐
- Java基础_面向对象,Lambda 表达式
面向对象 类,对象 类是对象的抽象,对象是类的具体,类是概念模型,定义对象的所有特性和所需的操作,对象是真实的模型,是一个具体的实体 1.显式创建对象 //最为常用 Object object = n ...
- Java基础、多线程、JVM、集合八股文自述(持续更新)
Java基础.多线程.JVM.集合八股文自述 一.Java基础 1.1 object类有哪些方法? getClass().hashCode().equals().clone().toString(). ...
- 【Java 8 in Action】Lambda表达式
文章目录 Lambda表达式 Lambda表达式的介绍 Lambda表达式的语法 Method References Default methods Functional Interface 浅析La ...
- 五、Java中常用的API(通过包进行分类)————异常、多线程和Lambda表达式
之前已经介绍了java.lang包下的相关类,今天将要补充两个常用的API:java.lang.Throwable和java.lang.Thread 一.异常(java.lang.Throwable) ...
- java 文件路径表达式_Java基础(二十二) Lambda表达式和File类
函数式编程思想 强调的是做什么,而不是以什么样的方式来做,它忽略了面向对象的复杂语法,只要能够获取到结果,谁去做的,怎么做的,都不重要,重要的是结果,不重视过程. 冗余的Runnable代码 传统的写 ...
- Java多线程:Lambda 表达式
什么是Lambda 表达式 Lambda 表达式,也可称为闭包,它是Java 8 发布的最重要新特性. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). 使用 Lambda 表 ...
- java学习笔记20(Lambda表达式、函数式编程、流式计算、练习)
文章目录 11.3 学习内容 Lambda表达式 Lambda标准格式 格式说明 省略规则 使用前提 函数式接口 预定义的函数式接口 工作内容 任务1 总结&明日计划 11.4 学习内容 流式 ...
- 不少Java程序员都觉得Lambda表达式很鸡肋,它到底有何用呢?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:https://urlify.cn/B3uiI3 # 什么是 ...
- java thread lambda_Java8新特性--Lambda表达式
从java8出现以来lambda是最重要的特性之一,它可以让我们用简洁流畅的代码完成一个功能. 很长一段时间java被吐槽是冗余和缺乏函数式编程能力的语言,随着函数式编程的流行java8种也引入了 这 ...
- 【Java】Java8新特性Lambda表达式和Stream API
Lambda表达式是实现支持函数式编程技术的基础. 函数式编程与面向对象编程:函数式编程将程序代码看作数学中的函数,函数本身作为另一个函数参数或返回值,即高阶函数.而面向对象编程按照真实世界客观事物的 ...
最新文章
- 1084 Broken Keyboard
- 两个奇技淫巧,将 Docker 镜像体积减小 99%
- Posix多线程编程—线程属性
- python pywin32 微信_python win32con安装_python-2.7 – 安装pywin32
- 通过Nagios监控weblogic服务
- Java面试题目,java工程师成神之路
- Python 之面向对象 继承
- python怎么读取csv文件-Python如何读取csv文件
- 五种常用web服务器jvm参数设置
- 【HDU - 4342】History repeat itself(数学)
- FPGA芯片行业科普
- 税收分类编码_四个要点教你如何又快又准选好编码?会计实操干货
- 安装ENVI过程中的问题记录
- 【SDE】随机微分方程(1)
- 车辆销售系统用例_汽车销售管理系统UML建模分析.doc
- 图书条形码跟ISBN号互相转换的类
- RabbitMQ——01安装
- 从JPG和JPEG图片获取压缩比详细教程
- button和submit的区别
- Java计算两个时间的月份差值