当前位置: 首页 > news >正文

【JavaSE】Lambda、Stream(659~686)

659.每天一考

1.写出获取Class实例的三种常见方式

Class clazz1 = String.class;
Class clazz2 = person.getClass(); //sout(person); //xxx.yyy.zzz.Person@...
Class clazz3 = Class.forName(String classPath);//体现反射的动态性

2.谈谈你对Class类的理解

Class实例对应着加载到内存中的一个运行时类。

3.创建Class对应运行时类的对象的通用方法,代码实现。以及这样操作,需要对应的运行时类构造器方面满足的要求。

Object obj = clazz.newInstance();//创建了对应的运行时类的对象
1.必须有空参的构造器
2.权限修饰符的权限要够。通常设置为public

4.在工程或module的src下有名为”jdbc.properties”的配置文件,文件内容为:name=Tom。如何在程序中通过代码获取Tom这个变量值。代码实现

5.如何调用方法show()
类声明如下:
package com.atguigu.java;
class User{
public void show(){
System.out.println(“我是一个中国人!”);
} }

User user = (User)clazz.newInstance();
Method show = clazz.getDeclaredMethod("show");
show.setAccessiable(true);
show.invoke(user);

660.复习:反射与Class
661.ClassLoader与反射的应用

662.代理模式与动态代理

代理设计模式的原理:
使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上

之前为大家讲解过代理机制的操作,属于静态代理,特征是代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。最好可以通过一个代理类完成全部的代理功能。

动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时 根据需要动态创建目标类的代理对象。

动态代理使用场合:
调试
远程方法调用

动态代理相比于静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中 处理,这样,我们可以更加灵活和统一的处理众多的方法。

663.代理模式与动态代理

静态代理举例
特点:代理类和被代理类在编译期间,就确定下来了。

package com.atguigu.java;interface ClothFactory{//代理类和被代理类都需要实现ClothFactoryvoid produceCloth();
}//代理类
class ProxyClothFactory implements ClothFactory{private ClothFactory factory;//用被代理类对象进行实例化public ProxyClothFactory(ClothFactory factory){//初始化this.factory = factory;}@Overridepublic void produceCloth() {System.out.println("代理工厂做一些准备工作");factory.produceCloth();System.out.println("代理工厂做一些后续的收尾工作");}
}//被代理类
class NikeClothFactory implements ClothFactory{@Overridepublic void produceCloth() {System.out.println("Nike工厂生产一批运动服");}
}public class StaticProxyTest {public static void main(String[] args) {//创建被代理类的对象ClothFactory nike = new NikeClothFactory();//创建代理类的对象ClothFactory proxyClothFactory = new ProxyClothFactory(nike);proxyClothFactory.produceCloth();}
}

664.代理模式举例

动态代理的举例

package com.atguigu.java;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface Human{String getBelief();void eat(String food);
}//被代理类
class SuperMan implements Human{@Overridepublic String getBelief() {return "I believe I can fly!";}@Overridepublic void eat(String food) {System.out.println("我喜欢吃" + food);}
}class HumanUtil{public void method1(){System.out.println("====================通用方法一====================");}public void method2(){System.out.println("====================通用方法二====================");}
}/*
要想实现动态代理,需要解决的问题?
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。*/class ProxyFactory{//调用此方法,返回一个代理类的对象。解决问题一public static Object getProxyInstance(Object obj){//obj:被代理类的对象MyInvocationHandler handler = new MyInvocationHandler();handler.bind(obj);return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);//类的加载器,接口}
}class MyInvocationHandler implements InvocationHandler{private Object obj;//需要使用被代理类的对象进行赋值public void bind(Object obj){this.obj = obj;}//当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()//将被代理类要执行的方法a的功能就声明在invoke()中@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {HumanUtil util = new HumanUtil();util.method1();//method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法//obj:被代理类的对象Object returnValue = method.invoke(obj,args);util.method2();//上述方法的返回值就作为当前类中的invoke()的返回值。return returnValue;}
}public class ProxyTest {public static void main(String[] args) {SuperMan superMan = new SuperMan();//proxyInstance:代理类的对象Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);//当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法String belief = proxyInstance.getBelief();System.out.println(belief);proxyInstance.eat("四川麻辣烫");System.out.println("*****************************");NikeClothFactory nikeClothFactory = new NikeClothFactory();ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);proxyClothFactory.produceCloth();}
}

665.AOP与动态代理的举例

前面介绍的Proxy和InvocationHandler,很难看出这种动态代理的优势,下面介绍一种更实用的动态代理机制
在这里插入图片描述
在这里插入图片描述
使用Proxy生成一个动态代理时,往往并不会凭空产生一个动态代理,这样没有 太大的意义。通常都是为指定的目标对象生成动态代理

这种动态代理在AOP中被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异:
AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理
在这里插入图片描述

package com.atguigu.java;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//动态代理的举例
interface Human{String getBelief();void eat(String food);}
//被代理类
class SuperMan implements Human{@Overridepublic String getBelief() {return "I believe I can fly!";}@Overridepublic void eat(String food) {System.out.println("我喜欢吃" + food);}
}class HumanUtil{public void method1(){System.out.println("====================通用方法一====================");}public void method2(){System.out.println("====================通用方法二====================");}}/*
要想实现动态代理,需要解决的问题?
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。*/class ProxyFactory{//调用此方法,返回一个代理类的对象。解决问题一public static Object getProxyInstance(Object obj){//obj:被代理类的对象MyInvocationHandler handler = new MyInvocationHandler();handler.bind(obj);return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);}}class MyInvocationHandler implements InvocationHandler{private Object obj;//需要使用被代理类的对象进行赋值public void bind(Object obj){this.obj = obj;}//当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()//将被代理类要执行的方法a的功能就声明在invoke()中@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {HumanUtil util = new HumanUtil();util.method1();//method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法//obj:被代理类的对象Object returnValue = method.invoke(obj,args);util.method2();//上述方法的返回值就作为当前类中的invoke()的返回值。return returnValue;}
}public class ProxyTest {public static void main(String[] args) {SuperMan superMan = new SuperMan();//proxyInstance:代理类的对象Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);//当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法String belief = proxyInstance.getBelief();System.out.println(belief);proxyInstance.eat("四川麻辣烫");System.out.println("*****************************");NikeClothFactory nikeClothFactory = new NikeClothFactory();ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);proxyClothFactory.produceCloth();}
}

666.Java8新特性内容概述

在这里插入图片描述

667.Java8新特性的好处

Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。 Java 8 是oracle公司于2014年3月发布,可以看成是自Java 5 以 来最具革命性的版本。Java 8为Java语言、编译器、类库、开发 工具与JVM带来了大量新特性。

Java 8新特性简介
速度更快
代码更少(增加了新的语法:Lambda 表达式)
强大的 Stream API
便于并行
最大化减少空指针异常:Optional
Nashorn引擎,允许在JVM上运行JS应用

并行流与串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。

Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。 Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流 之间进行切换。

668.Lambda表达式使用举例

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

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

import org.junit.Test;
import java.util.Comparator;//Lambda表达式的使用举例
public class LambdaTest {@Testpublic void test1(){Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("我爱北京天安门");}};r1.run();System.out.println("***********************");Runnable r2 = () -> System.out.println("我爱北京故宫");r2.run();}@Testpublic void test2(){Comparator<Integer> com1 = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1,o2);}};int compare1 = com1.compare(12,21);System.out.println(compare1);System.out.println("***********************");//Lambda表达式的写法Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);int compare2 = com2.compare(32,21);//Lambda表达式System.out.println(compare2);System.out.println("***********************");//方法引用Comparator<Integer> com3 = Integer :: compare;int compare3 = com3.compare(32,21);System.out.println(compare3);}
}

669.Lambda表达式语法的使用1

import org.junit.Test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;/*** Lambda表达式的使用** 1.举例: (o1,o2) -> Integer.compare(o1,o2);* 2.格式:*      -> :lambda操作符 或 箭头操作符*      ->左边:lambda形参列表 (其实就是接口中的抽象方法的形参列表)*      ->右边:lambda体 (其实就是重写的抽象方法的方法体)** 3. Lambda表达式的使用:(分为6种情况介绍)**    总结:*    ->左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对()也可以省略*    ->右边:lambda体应该使用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),省略这一对{}和return关键字** 4.Lambda表达式的本质:作为函数式接口的实例** 5. 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。我们可以在一个接口上使用 @FunctionalInterface 注解,*   这样做可以检查它是否是一个函数式接口。** 6. 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。*/
public class LambdaTest1 {//语法格式一:无参,无返回值@Testpublic void test1(){Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("我爱北京天安门");}};r1.run();System.out.println("***********************");Runnable r2 = () -> {System.out.println("我爱北京故宫");};r2.run();}//语法格式二:Lambda 需要一个参数,但是没有返回值。@Testpublic void test2(){Consumer<String> con = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};con.accept("谎言和誓言的区别是什么?");System.out.println("*******************");Consumer<String> con1 = (String s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");}//语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”@Testpublic void test3(){Consumer<String> con1 = (String s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*******************");Consumer<String> con2 = (s) -> {System.out.println(s);};con2.accept("一个是听得人当真了,一个是说的人当真了");}@Testpublic void test4(){ArrayList<String> list = new ArrayList<>();//类型推断int[] arr = {1,2,3};//类型推断}//语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略@Testpublic void test5(){Consumer<String> con1 = (s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*******************");Consumer<String> con2 = s -> {System.out.println(s);};con2.accept("一个是听得人当真了,一个是说的人当真了");}//语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值@Testpublic void test6(){Comparator<Integer> com1 = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);}};System.out.println(com1.compare(12,21));System.out.println("*****************************");Comparator<Integer> com2 = (o1,o2) -> {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);};System.out.println(com2.compare(12,6));}//语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略@Testpublic void test7(){Comparator<Integer> com1 = (o1,o2) -> {return o1.compareTo(o2);};System.out.println(com1.compare(12,6));System.out.println("*****************************");Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);System.out.println(com2.compare(12,21));}@Testpublic void test8(){Consumer<String> con1 = s -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*****************************");Consumer<String> con2 = s -> System.out.println(s);con2.accept("一个是听得人当真了,一个是说的人当真了");}
}

670.Lambda表达式语法的使用2

import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;/*** java内置的4大核心函数式接口** 消费型接口 Consumer<T>     void accept(T t)* 供给型接口 Supplier<T>     T get()* 函数型接口 Function<T,R>   R apply(T t)* 断定型接口 Predicate<T>    boolean test(T t)*/
public class LambdaTest2 {@Testpublic void test1(){happyTime(500, new Consumer<Double>() {@Overridepublic void accept(Double aDouble) {System.out.println("学习太累了,去天上人间买了瓶矿泉水,价格为:" + aDouble);}});System.out.println("********************");happyTime(400,money -> System.out.println("学习太累了,去天上人间喝了口水,价格为:" + money));}public void happyTime(double money, Consumer<Double> con){con.accept(money);}@Testpublic void test2(){List<String> list = Arrays.asList("北京","南京","天津","东京","西京","普京");List<String> filterStrs = filterString(list, new Predicate<String>() {@Overridepublic boolean test(String s) {return s.contains("京");}});System.out.println(filterStrs);List<String> filterStrs1 = filterString(list,s -> s.contains("京"));System.out.println(filterStrs1);}//根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定public List<String> filterString(List<String> list, Predicate<String> pre){ArrayList<String> filterList = new ArrayList<>();for(String s : list){if(pre.test(s)){filterList.add(s);}}return filterList;}
}

671.函数式接口的介绍

只包含一个抽象方法的接口,称为函数式接口。

你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式 抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽 象方法上进行声明)。

我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检 查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

在java.util.function包下定义了Java 8 的丰富的函数式接口

如何理解函数式接口

  • Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP) 编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,Java不 得不做出调整以便支持更加广泛的技术要求,也即java不但可以支持OOP还 可以支持OOF(面向函数编程)
  • 在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的 编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在 Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的 对象类型——函数式接口。
  • 简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是
    Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口 的实例,那么该对象就可以用Lambda表达式来表示。
  • 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。

672.Java内置的函数式接口介绍及使用举例

//自定义函数式接口@FunctionalInterface
public interface MyInterface {void method1();//    void method2();
}

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

673.方法引用的使用情况1

674.方法引用的使用情况2

675.方法引用的使用情况3

676.构造器引用与项目引用的使用

677.Stream API的概述

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API

Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。这 是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程 序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进 行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用 Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。 也可以使用 Stream API 来并行执行操作。简言之,Stream API 提供了一种 \高效且易于使用的处理数据的方式。

为什么要使用Stream API
实际开发中,项目中多数数据源都来自于Mysql,Oracle等。但现在数 据源可以更多了,有MongDB,Radis等,而这些NoSQL的数据就需要 Java层面去处理
Stream 和 Collection 集合的区别:,Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。

什么是 Stream
Stream到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。 “集合讲的是数据,Stream讲的是计算!”

注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
在这里插入图片描述

678.Stream的实例化

创建 Stream方式一:通过集合
Java8 中的 Collection 接口被扩展,提供了两个获取流 的方法:
default Stream stream() : 返回一个顺序流
default Stream parallelStream() : 返回一个并行流

创建 Stream方式二:通过数组
Java8 中的 Arrays 的静态方法 stream() 可以获取数组流:
static Stream stream(T[] array): 返回一个流
重载形式,能够处理对应基本类型的数组:
public static IntStream stream(int[] array)
public static LongStream stream(long[] array)
public static DoubleStream stream(double[] array)

创建 Stream方式三:通过Stream的of()
可以调用Stream类静态方法 of(), 通过显示值创建一个
流。它可以接收任意数量的参数。
public static Stream of(T… values) : 返回一个流

创建 Stream方式四:创建无限流
可以使用静态方法 Stream.iterate() 和 Stream.generate(),创建无限流。
迭代
public static Stream iterate(final T seed, final UnaryOperator f)
生成
public static Stream generate(Supplier s)

package com.atguigu.java2;
import java.util.ArrayList;
import java.util.List;
//提供用于测试的数据
public class EmployeeData {public static List<Employee> getEmployees(){List<Employee> list = new ArrayList<>();		list.add(new Employee(1001, "马化腾", 34, 6000.38));list.add(new Employee(1002, "马云", 12, 9876.12));list.add(new Employee(1003, "刘强东", 33, 3000.82));list.add(new Employee(1004, "雷军", 26, 7657.37));list.add(new Employee(1005, "李彦宏", 65, 5555.32));list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));list.add(new Employee(1007, "任正非", 26, 4333.32));list.add(new Employee(1008, "扎克伯格", 35, 2500.32));		return list;}	
}
import com.atguigu.java2.Employee;
import com.atguigu.java2.EmployeeData;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;/*** 1. Stream关注的是对数据的运算,与CPU打交道*    集合关注的是数据的存储,与内存打交道** 2.* ①Stream 自己不会存储元素。* ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。* ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行** 3.Stream 执行流程* ① Stream的实例化* ② 一系列的中间操作(过滤、映射、...)* ③ 终止操作** 4.说明:* 4.1 一个中间操作链,对数据源的数据进行处理* 4.2 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用**  测试Stream的实例化*/
public class StreamAPITest {//创建 Stream方式一:通过集合@Testpublic void test1(){List<Employee> employees = EmployeeData.getEmployees();//得到EmployeeData集合//        default Stream<E> stream() : 返回一个顺序流,拿数据按照集合中的顺序来Stream<Employee> stream = employees.stream();//        default Stream<E> parallelStream() : 返回一个并行流,几个线程同时去集合中取数据,不保证顺序Stream<Employee> parallelStream = employees.parallelStream();}//创建 Stream方式二:通过数组@Testpublic void test2(){int[] arr = new int[]{1,2,3,4,5,6};//调用Arrays类的static <T> Stream<T> stream(T[] array): 返回一个流IntStream stream = Arrays.stream(arr);Employee e1 = new Employee(1001,"Tom");Employee e2 = new Employee(1002,"Jerry");Employee[] arr1 = new Employee[]{e1,e2};Stream<Employee> stream1 = Arrays.stream(arr1);}//创建 Stream方式三:通过Stream的of()@Testpublic void test3(){Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);}//创建 Stream方式四:创建无限流@Testpublic void test4(){//      迭代
//      public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)//遍历前10个偶数Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);//      生成
//      public static<T> Stream<T> generate(Supplier<T> s)Stream.generate(Math::random).limit(10).forEach(System.out::println);}
}

679.Stream的中间操作:筛选与切片

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全 部处理,称为“惰性求值”。
在这里插入图片描述

package com.atguigu.java3;
import com.atguigu.java2.Employee;
import com.atguigu.java2.EmployeeData;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;//测试Stream的中间操作
public class StreamAPITest1 {//1-筛选与切片@Testpublic void test1(){List<Employee> list = EmployeeData.getEmployees();//filter(Predicate p)——接收 Lambda , 从流中排除某些元素。Stream<Employee> stream = list.stream();//先创建顺序流//练习:查询员工表中薪资大于7000的员工信息stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);//e为Employee,forEach终止操作//limit(n)——截断流,使其元素不超过给定数量。list.stream().limit(3).forEach(System.out::println);//list.stream()生成新的顺序流Stream,每次执行终止操作之后需要重新创建      //skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补list.stream().skip(3).forEach(System.out::println);//distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素list.add(new Employee(1010,"刘强东",40,8000));//list里面加一些重复数据list.add(new Employee(1010,"刘强东",41,8000));list.add(new Employee(1010,"刘强东",40,8000));list.add(new Employee(1010,"刘强东",40,8000));list.add(new Employee(1010,"刘强东",40,8000));//System.out.println(list);list.stream().distinct().forEach(System.out::println);}   
}

680.Stream的中间操作:映射

在这里插入图片描述

	//映射@Testpublic void test2(){//map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。List<String> list = Arrays.asList("aa", "bb", "cc", "dd");list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);//返回toUpperCase大写的//练习1:获取员工姓名长度大于3的员工姓名。List<Employee> employees = EmployeeData.getEmployees();Stream<String> namesStream = employees.stream().map(Employee::getName);//调用Employee的getName方法得到员工的名字namesStream.filter(name -> name.length() > 3).forEach(System.out::println);System.out.println();//练习2:Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::fromStringToStream);streamStream.forEach(s ->{s.forEach(System.out::println);});System.out.println();//flatMap(Function f)——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);characterStream.forEach(System.out::println);}//将字符串中的多个字符构成的集合转换为对应的Stream的实例public static Stream<Character> fromStringToStream(String str){//aaArrayList<Character> list = new ArrayList<>();for(Character c : str.toCharArray()){list.add(c);}return list.stream();}@Testpublic void test3(){ArrayList list1 = new ArrayList();list1.add(1);list1.add(2);list1.add(3);ArrayList list2 = new ArrayList();list2.add(4);list2.add(5);list2.add(6);//list1.add(list2);list1.addAll(list2);//addAll先取出来list2中的数据,依次添加到list1,得到的list1为6个元素System.out.println(list1);}

681.Stream的中间操作:排序

在这里插入图片描述

 //3-排序@Testpublic void test4(){
//        sorted()——自然排序List<Integer> list = Arrays.asList(12, 43, 65, 34, 87, 0, -98, 7);list.stream().sorted().forEach(System.out::println);//抛异常,原因:Employee没有实现Comparable接口
//        List<Employee> employees = EmployeeData.getEmployees();
//        employees.stream().sorted().forEach(System.out::println);//        sorted(Comparator com)——定制排序List<Employee> employees = EmployeeData.getEmployees();employees.stream().sorted( (e1,e2) -> {int ageValue = Integer.compare(e1.getAge(),e2.getAge());if(ageValue != 0){return ageValue;}else{return -Double.compare(e1.getSalary(),e2.getSalary());}}).forEach(System.out::println);}

682.Stream的终止操作:匹配与查找

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例
如:List、Integer,甚至是 void 。
流进行了终止操作后,不能再次使用。
在这里插入图片描述
在这里插入图片描述

package com.atguigu.java3;
import com.atguigu.java2.Employee;
import com.atguigu.java2.EmployeeData;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;//测试Stream的终止操作
public class StreamAPITest2 {//1-匹配与查找@Testpublic void test1(){List<Employee> employees = EmployeeData.getEmployees();//        allMatch(Predicate p)——检查是否匹配所有元素。
//          练习:是否所有的员工的年龄都大于18boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);System.out.println(allMatch);//        anyMatch(Predicate p)——检查是否至少匹配一个元素。
//         练习:是否存在员工的工资大于 10000boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 10000);System.out.println(anyMatch);//        noneMatch(Predicate p)——检查是否没有匹配的元素。
//          练习:是否存在员工姓“雷”boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("雷"));//startsWith以这个开头的System.out.println(noneMatch);//        findFirst——返回第一个元素Optional<Employee> employee = employees.stream().findFirst();System.out.println(employee);//        findAny——返回当前流中的任意元素Optional<Employee> employee1 = employees.parallelStream().findAny();System.out.println(employee1);}@Testpublic void test2(){List<Employee> employees = EmployeeData.getEmployees();// count——返回流中元素的总个数long count = employees.stream().filter(e -> e.getSalary() > 5000).count();System.out.println(count);
//        max(Comparator c)——返回流中最大值
//        练习:返回最高的工资:Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());Optional<Double> maxSalary = salaryStream.max(Double::compare);System.out.println(maxSalary);
//        min(Comparator c)——返回流中最小值
//        练习:返回最低工资的员工Optional<Employee> employee = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));System.out.println(employee);System.out.println();
//        forEach(Consumer c)——内部迭代employees.stream().forEach(System.out::println);//使用集合的遍历操作employees.forEach(System.out::println);}    
}

683.Stream的终止操作:归约

在这里插入图片描述

	//2-归约@Testpublic void test3(){//reduce(T identity, BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回 T//练习1:计算1-10的自然数的和List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);Integer sum = list.stream().reduce(0, Integer::sum);//参数1为初始值,设置为0System.out.println(sum);//reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。返回 Optional<T>//练习2:计算公司所有员工工资的总和List<Employee> employees = EmployeeData.getEmployees();Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);//Optional<Double> sumMoney = salaryStream.reduce(Double::sum);Optional<Double> sumMoney = salaryStream.reduce((d1,d2) -> d1 + d2);System.out.println(sumMoney.get());}

684.Stream的终止操作:收集

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

	//3-收集@Testpublic void test4(){//collect(Collector c)——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法//练习1:查找工资大于6000的员工,结果返回为一个List或SetList<Employee> employees = EmployeeData.getEmployees();List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());employeeList.forEach(System.out::println);System.out.println();Set<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());employeeSet.forEach(System.out::println);}

685.Optional类的介绍

到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。
以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,
Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代 码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。

Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表 这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不 存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在 则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

创建Optional类对象的方法:
Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
Optional.empty() : 创建一个空的 Optional 实例
Optional.ofNullable(T t):t可以为null
判断Optional容器中是否包含对象:
boolean isPresent() : 判断是否包含对象
void ifPresent(Consumer<? super T> consumer) :如果有值,就执行Consumer 接口的实现代码,并且该值会作为参数传给它。
获取Optional容器的对象:
T get(): 如果调用对象包含值,返回该值,否则抛异常
T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。
T orElseGet(Supplier<? extends T> other) :如果有值则将其返回,否则返回由Supplier接口实现提供的对象。
T orElseThrow(Supplier<? extends X> exceptionSupplier) :如果有值则将其返 回,否则抛出由Supplier接口实现提供的异常。

package com.atguigu.java4;
import org.junit.Test;
import java.util.Optional;/*** Optional类:为了在程序中避免出现空指针异常而创建的。** 常用的方法:ofNullable(T t)*            orElse(T t)*/
public class OptionalTest {/*
Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
Optional.empty() : 创建一个空的 Optional 实例
Optional.ofNullable(T t):t可以为null*/@Testpublic void test1(){Girl girl = new Girl();
//        girl = null;//of(T t):保证t是非空的Optional<Girl> optionalGirl = Optional.of(girl);}@Testpublic void test2(){Girl girl = new Girl();
//        girl = null;//ofNullable(T t):t可以为nullOptional<Girl> optionalGirl = Optional.ofNullable(girl);System.out.println(optionalGirl);//orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t.//如果内部的t是空的,则返回orElse()方法中的参数t1.Girl girl1 = optionalGirl.orElse(new Girl("赵丽颖"));System.out.println(girl1);}    
}

686.Optional类的使用举例

	public String getGirlName(Boy boy){return boy.getGirl().getName();}@Testpublic void test3(){Boy boy = new Boy();boy = null;String girlName = getGirlName(boy);System.out.println(girlName);}//优化以后的getGirlName():public String getGirlName1(Boy boy){//传统写法if(boy != null){Girl girl = boy.getGirl();if(girl != null){return girl.getName();}}return null;}@Testpublic void test4(){Boy boy = new Boy();boy = null;String girlName = getGirlName1(boy);System.out.println(girlName);}//使用Optional类的getGirlName():public String getGirlName2(Boy boy){Optional<Boy> boyOptional = Optional.ofNullable(boy);//此时的boy1一定非空Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴")));Girl girl = boy1.getGirl();Optional<Girl> girlOptional = Optional.ofNullable(girl);//girl1一定非空Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));return girl1.getName();}@Testpublic void test5(){Boy boy = null;boy = new Boy();boy = new Boy(new Girl("张老师"));String girlName = getGirlName2(boy);System.out.println(girlName);}

相关文章:

【JavaSE】Lambda、Stream(659~686)

659.每天一考 1.写出获取Class实例的三种常见方式 Class clazz1 String.class; Class clazz2 person.getClass(); //sout(person); //xxx.yyy.zzz.Person... Class clazz3 Class.forName(String classPath);//体现反射的动态性2.谈谈你对Class类的理解 Class实例对应着加载…...

有限差法(Finite Difference)求梯度和Hessian Matrix(海森矩阵)的python实现

数学参考 有限差方法求导&#xff0c;Finite Difference Approximations of Derivatives&#xff0c;是数值计算中常用的求导方法。数学上也比较简单易用。本文主要针对的是向量值函数&#xff0c;也就是f(x):Rn→Rf(x):\mathbb{R^n}\rightarrow \mathbb{R}f(x):Rn→R当然&…...

day33 贪心算法 | 1005、K次取反后最大化的数组和 134、加油站 135、分发糖果

题目 1005、K次取反后最大化的数组和 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&#xff09; 以这种方式修改…...

《蓝桥杯每日一题》递推·AcWing 3777. 砖块

1.题目描述n 个砖块排成一排&#xff0c;从左到右编号依次为 1∼n。每个砖块要么是黑色的&#xff0c;要么是白色的。现在你可以进行以下操作若干次&#xff08;可以是 0 次&#xff09;&#xff1a;选择两个相邻的砖块&#xff0c;反转它们的颜色。&#xff08;黑变白&#xf…...

mysql读写分离(maxscale)

1. 环境架构 需要三台服务器。192.168.2.10&#xff08;master&#xff09;192.168.2.20&#xff08;slave&#xff09;192.168.2.30&#xff08;maxscale&#xff09; 2. 部署mysql主从同步 mysql主从同步可以参考mysql主从同步 3. 部署maxscale服务 MaxScale中间件软件 …...

第八章 - 数据分组( group by , having , select语句顺序)

第八章 - 数据分组 group by数据分组过滤分组 having分组排序groub by语句的一些规定select语句顺序数据分组 在使用group by进行分组时&#xff0c;一般都会配合聚合函数一起使用&#xff0c;实现统计数据的功能。比如下面例子&#xff0c;需要按性别计算人数。按性别进行分组…...

Git(GitHub,Gitee 码云,GitLab)详细讲解

目录第一章 Git 概述1.1 何为版本控制1.2 为什么需要版本控制1.3 版本控制工具1.4 Git 简史1.5 Git 工作机制1.6 Git 和代码托管中心第二章 Git 安装第三章 Git 常用命令3.1 设置用户签名3.2 初始化本地库3.3 查看本地库状态3.3.1 首次查看&#xff08;工作区没有任何文件&…...

策略模式(Strategy Pattern)

编写鸭子项目&#xff0c;具体要求如下&#xff1a; 1&#xff09; 有各种鸭子&#xff08;比如 野鸭、北京鸭&#xff0c;水鸭等&#xff0c;鸭子有各种行为&#xff0c;比如 叫&#xff0c;飞行等&#xff09; 2&#xff09;显示鸭子的信息 传统方案解决鸭子问题 1&#xff0…...

《Qt6开发及实例》6-2 Qt6基础图形的绘制

目录 一、绘图框架设计 二、绘图区的实现 2.1 PaintArea类 2.2 PaintArea类讲解 三、主窗口的实现 3.1 MainWidget类 3.2 MainWidget类讲解 3.3 槽函数编写 3.5 其他内容 一、绘图框架设计 界面 两个类 ​ 二、绘图区的实现 2.1 PaintArea类 ​paintarea.h #ifndef…...

LeetCode 382. 链表随机节点

原题链接 难度&#xff1a;middle\color{orange}{middle}middle 题目描述 给你一个单链表&#xff0c;随机选择链表的一个节点&#xff0c;并返回相应的节点值。每个节点 被选中的概率一样 。 实现 SolutionSolutionSolution 类&#xff1a; Solution(ListNodehead)Solution…...

iOS开发AppleDeveloper中给别人授权开发者权限后,对方一直显示不了我的开发账号team

在iOS开发经常出现多人协作开发的情况。这时我们通常要发邮件邀请别的用户为开发者或者app管理就可以开发我们自己的项目了。但是这次我给别人授权开发者权限后&#xff0c;发现别人权限中没有证书相关权限如图&#xff1a;并且别人登录该账号后&#xff0c;在xcode中只有一个看…...

FreeRTOS数据类型和编程规范

目录 数据类型 变量名 函数名 宏的名 数据类型 每个移植的版本都含有自己的portmacro.h头文件&#xff0c;里面定义了2个数据类型 TickType_t FreeRTOS配置了一个周期性的时钟中断&#xff1a;Tick Interrupt每发生一次中断&#xff0c;中断次数累加&#xff0c;这被称为t…...

【python知识】win10下如何用python将网页转成pdf文件

一、说明 本篇记录一个自己享用的简单工具。在大量阅读网上文章中&#xff0c;常常遇到一个专题对应多篇文章&#xff0c;用浏览器的收藏根本不够。能否见到一篇文章具有搜藏价值&#xff0c;就转到线下&#xff0c;以备日后慢慢消化吸收。这里终于找到一个办法&#xff0c;将在…...

C语言常见关键字

写在前面 这个博客是结合C语言深度解剖这本书和我以前学的知识综合而成的,我希望可以更见详细的谈一下C语言的关键字,内容有点多,有错误还请斧正. 常见关键字 下面我们说下C语言的关键字,所谓的关键字是指具有特定功能的单词,我们可以使用关键字来帮助我们完成不同的事物.C语…...

【MT7628】固件开发-SDK4320添加MT7612E WiFi驱动操作说明

解压5G WiFi MT7612E驱动1.1解压指令 tar -xvf MT76x2E_MT7620_LinuxAP_V3.0.4.0_P2_DPA_20160308.tar.bz2 1.2解压之后会出现以下两个目录 rlt_wifi rlt_wifi_ap 1.3将解压后的文件拷贝到系统下 拷贝路径 RT288x_SDK/source/linux-2.6.36.x/drivers/net/wireless 内核中打开驱…...

如何从手工测试进阶自动化测试?阿里10年测开经验分享...

随着行业的竞争加剧&#xff0c;互联网产品迭代速度越来越快&#xff0c;QA 与测试工程师都需要在越来越短的测试周期内充分保证质量。可是&#xff0c;App 测试面临着很多挑战&#xff0c;比如多端发布、多版本发布、多机型发布等等&#xff0c;导致了手工测试很难完全胜任。因…...

C++复习笔记11

1. vector是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它的大小会被…...

【MT7628】固件开发-SDK4320添加MT7628 WiFi驱动操作说明

解压2.4G WiFi MT7628驱动1.1解压指令 tar -xvf MT7628_LinuxAP_V4.1.0.0_DPA_20160310.tar.bz2 1.2解压之后会出现以下两个目录 mt_wifi mt_wifi_ap 1.3将解压后的文件拷贝到系统下 拷贝路径 RT288x_SDK/source/linux-2.6.36.x/drivers/net/wireless 内核中打开驱动编译修改R…...

C#开发的OpenRA游戏加载界面的实现

C#开发的OpenRA游戏加载界面的实现 游戏的UI是一个游戏必备, 但是游戏的UI都是自己处理的,不能使用像Windows自带的UI。 这样游戏的UI,其实也是使用游戏的方式来显示的, 只不过使用了低帧率的方式来显示。 比如OpenRA游戏界面,就会显示如下: 游戏的界面有很多,先从一个简…...

渲染农场优势是什么_云渲染农场怎么用?

在回答渲染农场的优势这个问题之前&#xff0c;我先申明一下本文中提到的渲染农场/云渲染平台/云渲染农场&#xff0c;都特指CG领域内的专业3D渲染平台&#xff0c;有一些文章会强调这个叫法的区别&#xff0c;但是业内一般都不会分这么细&#xff0c;所以也就不赘述了。渲染农…...

SoapUI、Jmeter、Postman三种接口测试工具的比较分析

目录 前言 1. 用例组织方式 2. 支持的接口类型与测试类型 3. 配置不同接口类型 4. 自定义变量以及变量的作用域 5. 数据源、生成器&#xff0c;进行参数化 6. 流程控制 7. 结果解析、展示 8. 断言 9. 脚本扩展能力 10. 团队协作 总结 重点&#xff1a;配…...

Python内置函数 — sort,sorted

1、sort 列表的属性方法&#xff0c;对列表进行排序&#xff0c;默认升序&#xff0c;返回None值。 源码注释&#xff1a; """ Sort the list in ascending order and return None.The sort is in-place (i.e. the list itself is modified) and stable (i.e.…...

mysql事务隔离级别

mysql锁机制及原理1.隔离级别2.实践2.1查看事务隔离级别2.2 设置隔离级别2.3 不可重复读2.4 幻读3.幻读怎么解决3.1 Record Lock3.2 Gap Lock3.3 Next-Key Lock引用&#xff1a;https://blog.csdn.net/xinyuan_java/article/details/1284932051.隔离级别 SERIALIZABLE(序列化)…...

【C++】string类(下)

文章目录1.迭代器(正向遍历)begin有两个版本2.反向迭代器(反向遍历)rbegin由两个版本3. at4. insert ——头插在pos位置前插入一个字符串在pos位置前插入n个字符在迭代器前插入一个字符5. erase从pos位置开始删除len个字符从迭代器位置开始删除6. replace——替换从pos位置开始…...

Elasticsearch: Prefix queries - 前缀查询

Prefix queries 被用于在查询时返回在提供的字段中包含特定前缀的文档。有时我们可能想使用前缀查询单词&#xff0c;例如 Leonardo 的 Leo 或 Marlon Brando、Mark Hamill 或 Martin Balsam 的 Mar。 Elasticsearch 提供了一个前缀查询&#xff0c;用于获取匹配单词开头部分&a…...

GEE学习笔记 七十七:GEE学习方法简介

这是一篇关于学习方法的思考探索&#xff0c;当然我不会大篇文章介绍什么学习方法&#xff08;因为我也不是这方面的专家?&#xff09;&#xff0c;这个只是总结一下我是如何学习GEE以及在学习中遇到问题时如何解决问题的。我写这篇文章的目的就是在和一些学习GEE的新同学接触…...

20基于主从博弈的智能小区代理商定价策略及电动汽车充电管理MATLAB程序

参考文档&#xff1a;《基于主从博弈的智能小区代理商定价策略及电动汽车充电管理》基本复现仿真平台&#xff1a;MATLABCPLEX/gurobi平台优势&#xff1a;代码具有一定的深度和创新性&#xff0c;注释清晰&#xff0c;非烂大街的代码&#xff0c;非常精品&#xff01;主要内容…...

长按power键,点击重启按钮,系统重启流程一

1.有可能会涉及到如下文件 2.文件流程...

数据的TCP分段和IP分片

本文简述下TCP分段和IP分片的区别与联系。 我们知道&#xff0c;用户空间的数据拷贝到内核空间的TCP发送缓冲区&#xff08;这个是一个结构体&#xff0c;叫sk_buffer&#xff0c;简称skb&#xff09;后就由内核网络协议栈做后续的封装和发送处理了&#xff0c;用户无需考虑下…...

HTML中嵌入B站视频

HTML中嵌入B站视频 在网页中实现一个HTML播放器需要先从b站获取视频嵌入代码, 以前嵌入代码可以从视频分享那里拿到, 现在好像不行了 必须是自己投稿的视频, 从投稿管理页面才能找到 复制嵌入代码 建一个.html文件, 放入下面代码 <!DOCTYPE html> <html><head…...

烟台网站推广效果好/百度平台投诉人工电话

文档下载地址&#xff1a;Django_2.0_中文教程 http://download.csdn.net/detail/julius_lee/6620099 在线地址&#xff1a;http://djangobook.py3k.cn/2.0/ Django 2.0 Book 关键内容记录&#xff0c;主要是为了帮助记忆和理清整个框架&#xff0c;同时以后忘了可以查看&a…...

台州网站制作服务/sem 优化软件

目录在 netmiko 中使用 TextFSM安装模板查看安装完成使用如何编写自定义TextFSM模板示例TextFSM 在线解析&#xff1a; http://textfsm.xdai.vip/ 在 netmiko 中使用 TextFSM 安装模板 $ cd ~ $ git clone https://github.com/networktocode/ntc-templates.git查看安装完成 …...

上海做淘宝网站建设/百度一下百度首页官网

Rubinius团队刚刚宣布&#xff0c;Rubinius 2.0发布。Rubinius的上一个版本&#xff08;1.2.4&#xff09;已经发布两年多了&#xff0c;支持Ruby 1.8.7。其后&#xff0c;Ruby 1.8被弃用&#xff0c;Ruby开发人员强烈要求从1.9升级到2.0。\u0026#xD;按照计划&#xff0c;Rubin…...

接收新网站如何做诊断/seo网络推广培训

不管金蝶公司如何&#xff0c;其下面的代理商的技术素质真的很差&#xff0c;下面列出几个明显存在的问题&#xff1a; 1、服务器尽管有raid&#xff0c;但是根本没有做raid&#xff0c;因为技术人员不清楚raid是做什么的。 2、数据库的sa密码为空&#xff0c;也就是说公司内部…...

濮阳住房和城乡建设部网站/网络营销工程师

也许是龙芯名称中的“龙”字&#xff0c;承载着太多国人的希望&#xff0c;自诞生之初就处于社会舆论的风口浪尖。有人说龙芯是骗经费的项目&#xff0c;也有人说龙芯的科研人员是为理想而奋斗的志士&#xff0c;还有人说龙芯的科研人员“太天真”&#xff0c;是土八路斗美械师…...

网站上的qq如何做悬浮/百度app下载安装官方免费下载

目录 1. 保持好奇&#xff0c;勤于在项目中发现问题 2.带着问题去深度思考、查各种资料 4. 将你的成果用起来&#xff0c;提升项目效果 1. 精力高度专注 2. 规律时间投入 很多同学都和我说过一个问题&#xff0c;有心想扎实地提高技术能力&#xff0c;但无奈工作太忙没有时…...