借鉴之:https://blog.csdn.net/qq_28410283/article/details/80601495

Lambda 表达式:

//1.Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
//2.Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
//3.使用 Lambda 表达式可以使代码变的更加简洁紧凑。
/*以下是lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。*/

1.   左侧:lambda表达式的参数列表
    2.   右侧:lambda表达式中所需要执行的功能,即lambda函数体
    3   .lambda表达式语法格式有三种:

1).无参数,无返回值的用法 :( ) -> System.out.println("hello lambda");

2). 有一个参数,无返回值的用法: (x) -> System.out.println(x); 或者 x -> System.out.println(x);  一个参数,可以省略参数的小括号

3)有两个参数,有返回值的:(x, y) -> x + y

public void test4() {
// 无返回值lambda函数体中用法
//多行的,只需要用大括号{}把语句包含起来就可以了
//只有一条语句的,大括号可以不用写;
Runnable r1 = () -> {
System.out.println("hello lambda1");
System.out.println("hello lambda2");
System.out.println("hello lambda3");
};
r1.run(); // 有返回值lambda函数体中用法
//有返回值和无返回值的,只有一个return的区别
//只有一条语句的,renturn都可以不用写;
BinaryOperator<Integer> binary = (x, y) -> {
int a = x * 2;
int b = y + 2;
return a + b;
};
System.out.println(binary.apply(1, 2));// 6
}

2.方法的引用的语法,主要有三类

1.指向静态方法的方法引用,例如Integer的parseInt方法 ,可以写成 Integer::parseInt

类::静态方法名

2.指向任意类型实例方法的方法引用,例如String的length方法,写成 String::length;

类::实例方法名

3.指向现有对象的实例方法的方法引用

对象::实例方法名

构造器的引用:对于一个现有构造函数,你可以利用它的名称和关键字new来创建它的一个引用ClassName::new;

public static void main(String args[]){

        /*************** 方法的引用 ****************/
// 类::静态方法名
Comparator<Integer> cam1 = (x, y) -> x.compareTo(y);
System.out.println(cam1.compare(2, 4));
Comparator<Integer> cam = Integer::compareTo;
System.out.println(cam.compare(3, 2));
// 类::实例方法名
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
System.out.println(bp.test("a", "b"));
BiPredicate<String, String> bp1 = String::equals;
System.out.println(bp1.test("a", "b")); // 对象::实例方法名
Consumer<String> con1 = x -> System.out.println(x);
con1.accept("abc");
Consumer<String> con = System.out::println;
con.accept("abc"); Emp emp = new Emp("上海", "xiaoMIng", 18);
Supplier<String> supper1 = () -> emp.getAddress();
System.out.println(supper1.get());
Supplier<String> supper = emp::getAddress;
System.out.println(supper.get()); /*************** 构造器的引用 ****************/
// 无参构造函数,创建实例
Supplier<Emp> supper2 = () -> new Emp();
Supplier<Emp> supper3 = Emp::new;
Emp emp1 = supper3.get();
emp1.setAddress("上海");
System.out.println("emp1="+emp1.toString()); // 一个参数
Function<String, Emp> fun = address -> new Emp(address);
Function<String, Emp> fun1 = Emp::new;
System.out.println("beijing="+fun1.apply("beijing")); // 两个参数
BiFunction<String, Integer, Emp> bFun = (name, age) -> new Emp(name, age);
BiFunction<String, Integer, Emp> bFun1 = Emp::new;
System.out.println("xiaohong="+bFun1.apply("xiaohong", 18)); }

3、java8 函数式接口简介:https://blog.csdn.net/qq_28410283/article/details/80962325

4、Stream接口简介:   流是java API中的新的成员,它可以让你用声明式的方式处理集合,简单点说,可以看成遍历数据的一个高级点的迭代器。

1.Arrays.stream,我们可以通过Arrays的静态方法,传入一个泛型数组,创建一个流。

2.Stream.of,我们可以通过Stream的静态方法,传入一个泛型数组,或者多个参数,创建一个流,这个静态方法,也是调用了Arrays的stream静态方法,如下

System.out.println(Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3));

通过stream里面抽象方法的定义,我们可以看到,这个方法,可以分成两种类型,一种返回类型为接口本身的Stream<T>,另外一种是返回其他对象类型的,返回接口类型的,我们称这些方法为中间操作,返回其他具体类型的,我们称为终端操作;

5、Stream接口之

⑥对对象的操作:peek
⑥统计个数:count
⑦取用前几个:limit
⑧跳过前几个:skip
⑨组合数组:concat
⑩排序:sorted:
  sorted()   自然排序
  sorted(Comparator com)   定制排序
  allMatch   检查是否匹配所有元素
  anyMatch   检查是否至少匹配一个元素
  noneMatch   检查是否没有匹配所有元素
  findFirst   返回第一个元素
  findAny   返回当前流中的任意元素
  count   返回流中元素的总个数
  max   返回流中最大值
  min   返回流中最小值

⑪Collect:  将流转换为其他形式。接收一个Collector的实现,用于给stream中元素做汇总的方法。
⑪map映射,  用来归类,结果一般是一组数据,比如可以将list中的学生分数映射到一个新的stream中。
⑪reduce规约, 用来计算值,结果是一个值,比如计算最高分。
④flatMap    接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。即对流扁平化处理,浅显一点解释就是把几个小的list转换到一个大的list

6.并行流和顺序流:
并行流是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
通过parallel()与sequential()可以实现并行流和顺序流之间的切换。

7、流的实例用法demo:

package jdk18meths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream; public class TestJava8 {
public static List<Emp> list = new ArrayList<>();
static {
list.add(new Emp("xiaoHong1", 20, 1000.0));
list.add(new Emp("xiaoHong2", 25, 2000.0));
list.add(new Emp("xiaoHong3", 30, 3000.0));
list.add(new Emp("xiaoHong4", 35, 4000.0));
list.add(new Emp("xiaoHong5", 38, 5000.0));
list.add(new Emp("xiaoHong6", 45, 9000.0));
list.add(new Emp("xiaoHong7", 55, 10000.0));
list.add(new Emp("xiaoHong8", 42, 15000.0));
} public static void main(String[] args) {
// 对数组流,先过滤重复,在排序,再控制台输出 1,2,3
List arr =Arrays.asList(3, 1, 2, 1).stream().distinct().sorted().collect(Collectors.toList());
System.out.println(arr); // 对list里的emp对象,取出薪水,并对薪水进行排序,然后输出薪水的内容,map操作,改变了Strenm的泛型对象
List list2= list.stream().map(emp -> emp.getSalary()).sorted().collect(Collectors.toList());
System.out.println(list2); //peek 给年纪大于30岁的人,薪水提升1.5倍,并输出结果
List<Emp> stream = list.stream().filter(emp -> {
return emp.getAge() > 30;
}).peek(emp -> {
emp.setSalary(emp.getSalary() * 1.5);
}).collect(Collectors.toList()); stream.forEach(s -> System.out.println(s.getName()));
System.out.println("stream="+stream.toString()); //peek
List list = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> e.equals("four"))
.map(String::toUpperCase).collect(Collectors.toList());
System.out.println(list); //把2个数组组合在一起
Stream<String> stream1 = Stream.of("陈奕迅", "陈伟霆", "陈七", "钟汉良");
String[] arr2 = {"1","2","3"};
Stream<String> stream2 = Stream.of(arr2);
Stream<String> concatStream = Stream.concat(stream1, stream2);
concatStream.forEach(str-> System.out.println(str));
System.out.println(concatStream);
//另一种方法:flatMap
//接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。即对流扁平化处理,浅显一点解释就是把几个小的list转换到一个大的list
} public static class Emp {
@Override
public String toString() {
return "Emp [name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
private String name;
private Integer age;
private Double salary;
public Emp(String name, Integer age, Double salary) {
super();
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
}
判断list非空:
CollectionUtils.isNotEmpty(accountList)
合并;list:
List<MemberPreference> preferenceTotal = Stream.of(memberPreferences, memberPreferences2).flatMap(Collection::stream).distinct().collect(Collectors.toList()); list 去null :
List<String> result = listStrings.stream().filter(x -> x!=null).collect(Collectors.toList());
List<String> result2 = listStrings.stream().filter(Objects::nonNull).collect(Collectors.toList());
//list对象赋值给另一个list对象

  List a = list.stream().map(it ->{
    MemberCard mcard = new MemberCard();
    BeanUtils.copyProperties(it, mcard);
    return mcard;
  }).collect(Collectors.toList());
    System.out.println(a);
 }

package jdk180reduce;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.stream.Collectors;
import java.util.stream.IntStream; public class StreamTest01 {
public static void main(String[] args) {
List<Student> stuList = new ArrayList<>(10);
stuList.add(new Student("刘一", 85));
stuList.add(new Student("陈二", 90));
stuList.add(new Student("张三", 98));
stuList.add(new Student("李四", 88));
stuList.add(new Student("王五", 83));
stuList.add(new Student("赵六", 95));
stuList.add(new Student("孙七", 87));
stuList.add(new Student("周八", 84));
stuList.add(new Student("吴九", 100)); //需求:列出90分以上的学生姓名,并按照分数降序排序
List<Student> result1 = new ArrayList<>(10);
result1 = stuList.stream().filter(s -> s.getScore()>=90)
.sorted(Comparator.comparing(Student :: getScore).reversed())
.collect(Collectors.toList());
System.out.println(result1); //list.stream().sorted(Comparator.reverseOrder()); //计算学生总分 2个参数:初始值(即0+a[1]+a[2]+...)开始一直相加, //reduce用来计算值,结果是一个值,比如计算最高分。
Integer totalScore1 = stuList.stream().map(Student::getScore).reduce(0,(a,b) -> a + b);
System.out.println("totalScore1="+totalScore1); //计算学生总分,一个参数忽略a[0] 返回Optional类型的数据,改类型是java8中新增的,主要用来避免空指针异常
Optional<Integer> totalScore2 = stuList.stream().map(Student::getScore).reduce((a,b) -> a + b);
System.out.println("totalScore2="+totalScore2.get()); //计算最高分和最低分(总分Integer ::sum)
Optional<Integer> max = stuList.stream().map(Student::getScore).reduce(Integer::max);
Optional<Integer> min = stuList.stream().map(Student::getScore).reduce(Integer::min);
System.out.println("max="+max.get());
System.out.println("min="+min.get()); //stream没有sum求和的方法,但是有别的。
//将stream转换为IntStream求和
int totalScoreInt = stuList.stream().mapToInt(Student::getScore).sum();
System.out.println("Int_totalScore="+totalScoreInt);
//计算平均分
OptionalDouble avgScore = stuList.stream().mapToInt(Student::getScore).average();
System.out.println("avgScore="+avgScore.getAsDouble());
//生成1~100之间的数字
IntStream num = IntStream.rangeClosed(1, 100);
System.out.println("num="+num.toString()); List<String> lists = new ArrayList<>();
lists.add("li");
lists.add("zhang");
lists.add("chen");
//Match匹配
boolean a = lists.stream().anyMatch(s -> s.startsWith("li"));
System.out.println("li = " + a);
//判断是否全为li开头的
System.out.println(lists.stream().allMatch(s -> s.startsWith("li")));
//判断一个字符在该集合中不存在
System.out.println(lists.stream().noneMatch(s -> s.startsWith("li2"))); //filter: filter方法的作用,是对这个boolean做判断,返回true判断之后的对象
//返回字符串为a的值
String[] dd = { "a", "b", "c" };
java.util.stream.Stream<String> stream = Arrays.stream(dd);
stream.filter(str -> str.equals("c")).forEach(System.out::println);
} }
package jdk180reduce;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors; public class TestJava8 {
public static List<Emp> list = new ArrayList<>();
static {
list.add(new Emp("上海", "小名", 17));
list.add(new Emp("北京", "小红", 18));
list.add(new Emp("深圳", "小蓝", 19));
list.add(new Emp("广州", "小灰", 20));
list.add(new Emp("杭州", "小黄", 21));
list.add(new Emp("贵阳", "小白", 22));
} public static void main(String[] args) {

      //groupingBy返回 userId:List<User>
      Map<Integer, List<User>> map = userList.stream().collect(Collectors.groupingBy(User::getUserId));
      System.out.println("map=" + map);
      //groupingBy返回 userId:每组个数
      Map<Integer, Long> mapCount = userList.stream().collect(Collectors.groupingBy(User::getGender,Collectors.counting()));
      System.out.println("mapCount个数=" + mapCount);  

// 转list
List<String> names = list.stream().map(e -> e.getName()).collect(Collectors.toList());
System.out.println("names="+names); // 转set
Set<String> address = list.stream().map(emp -> emp.getName()).collect(Collectors.toSet());
System.out.println("address="+address); // 转map,需要指定key和value,Function.identity()表示当前的Emp对象本身
Map<String, Emp> map = list.stream().collect(Collectors.toMap(Emp::getName, Function.identity()));
System.out.println("转map="+map); // 计算元素中的个数
Long count = list.stream().collect(Collectors.counting()); // 数据求和 summingInt summingLong,summingDouble
Integer sumAges = list.stream().collect(Collectors.summingInt(Emp::getAge));
int totalScoreInt = list.stream().mapToInt(Emp::getAge).sum();
System.out.println("求和="+sumAges);
System.out.println("求和2="+totalScoreInt); // 平均值 averagingInt,averagingDouble,averagingLong
Double aveAges = list.stream().collect(Collectors.averagingInt(Emp::getAge));
OptionalDouble avgScore = list.stream().mapToInt(Emp::getAge).average();
System.out.println("平均值 1="+aveAges);
System.out.println("平均值 2="+avgScore); // 综合处理的,求最大值,最小值,平均值,求和操作
// summarizingInt,summarizingLong,summarizingDouble
IntSummaryStatistics intSummary = list.stream().collect(Collectors.summarizingInt(Emp::getAge));
System.out.println(intSummary.getAverage());// 19.5
System.out.println(intSummary.getMax());// 22
System.out.println(intSummary.getMin());// 17
System.out.println(intSummary.getSum());// 117 // 连接字符串,当然也可以使用重载的方法,加上一些前缀,后缀和中间分隔符
String strEmp = list.stream().map(emp -> emp.getName()).collect(Collectors.joining());
String strEmp1 = list.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中间的分隔符-"));
String strEmp2 = list.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中间的分隔符-", "前缀*", "&后缀"));
// 小名小红小蓝小灰小黄小白
// 小名-中间的分隔符-小红-中间的分隔符-小蓝-中间的分隔符-小灰-中间的分隔符-小黄-中间的分隔符-小白
// 前缀*小名-中间的分隔符-小红-中间的分隔符-小蓝-中间的分隔符-小灰-中间的分隔符-小黄-中间的分隔符-小白&后缀
System.out.println(strEmp);
System.out.println(strEmp1);
System.out.println(strEmp2); // maxBy 按照比较器中的比较结果刷选 最大值
Optional<Integer> maxAge = list.stream().map(emp -> emp.getAge()).collect(Collectors.maxBy(Comparator.comparing(Function.identity())));
// 最小值
Optional<Integer> minAge = list.stream().map(emp -> emp.getAge()).collect(Collectors.minBy(Comparator.comparing(Function.identity())));
System.out.println("max:" + maxAge);
System.out.println("min:" + minAge); // 归约操作
list.stream().map(emp -> emp.getAge()).collect(Collectors.reducing((x, y) -> x + y));
list.stream().map(emp -> emp.getAge()).collect(Collectors.reducing(0, (x, y) -> x + y));
// 分操作 groupingBy 根据地址,把原list进行分组
Map<String, List<Emp>> mapGroup = list.stream().collect(Collectors.groupingBy(Emp::getAddress));

    //根据accountNum分组,再把QtyEarn相加,得到一个新的map。
        Map<String, Integer> waitingPoints = customerLoyOrderTxns.stream().
            collect(Collectors.groupingBy(CustomerLoyOrderTxnPO::getAccountNum,Collectors.summingInt(x -> x.getQtyEarn())));  

        System.out.println("mapGroup:" + mapGroup);
// partitioningBy 分区操作 需要根据类型指定判断分区
Map<Boolean, List<Integer>> partitioningMap = list.stream().map(emp -> emp.getAge()).collect(Collectors.partitioningBy(emp -> emp > 20));
System.out.println("partitioningMap:" + partitioningMap);
} static class Emp {
private String address; private String name; private Integer age; public Emp() { } public Emp(String address) {
this.address = address;
} public Emp(String name, Integer age) {
this.name = name;
this.age = age;
} public Emp(String address, String name, Integer age) {
super();
this.address = address;
this.name = name;
this.age = age;
} //get set 方法 }
   //Collectors.groupingBy()的写法:
public static void main(String[] args) {
//3 apple, 2 banana, others 1
List<Item> items = Arrays.asList(
new Item("apple", 10, new BigDecimal("9.99")),
new Item("banana", 20, new BigDecimal("19.99")),
new Item("orang", 10, new BigDecimal("29.99")),
new Item("watermelon", 10, new BigDecimal("29.99")),
new Item("papaya", 20, new BigDecimal("9.99")),
new Item("apple", 10, new BigDecimal("9.99")),
new Item("banana", 10, new BigDecimal("19.99")),
new Item("apple", 20, new BigDecimal("9.99"))
);
//Group by + Count
Map<String, Long> counting = items.stream().collect(Collectors.groupingBy(Item::getName, Collectors.counting()));
System.out.println(counting); //求和//Group by + Sum qty
Map<String, Integer> sum = items.stream().collect(Collectors.groupingBy(Item::getName, Collectors.summingInt(Item::getQty)));
System.out.println(sum); Map<String, List<Item>> env = items.stream().collect(Collectors.groupingBy(Item::getName));
System.out.println(env);
}

jdk1.8(java8)新特性的更多相关文章

  1. java8新特性全面解析

    在Java Code Geeks上有大量的关于Java 8 的教程了,像玩转Java 8--lambda与并发,Java 8 Date Time API 教程: LocalDateTime和在Java ...

  2. JAVA8新特性——Lamda表达式

    JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ Lamda表达式,读作λ表达式,它实质属于函数式编程的概念,要理解函数式编程的产生目的,就要先理解匿名内部类. 先来看看传统的匿名 ...

  3. java8新特性——Lambda表达式

    上文中简单介绍了一下java8得一些新特性,与优点,也是为本次学习java8新特性制定一个学习的方向,后面几篇会根据上文中得新特性一一展开学习.本文就从java8新特性中比较重要的Lambda表达式开 ...

  4. JAVA8新特性——接口定义增强

    JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ 接口定义增强 在JDK1.8以前,接口是定义的: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法 ...

  5. java8 新特性精心整理

    前言 越来越多的项目已经使用 Java 8 了,毫无疑问,Java 8 是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和 JVM 等方面的十多个新特 ...

  6. java8 新特性精心整理(全)

    前言 越来越多的项目已经使用 Java 8 了,毫无疑问,Java 8 是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和 JVM 等方面的十多个新特 ...

  7. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  8. 【Java8新特性】重复注解与类型注解,你真的学会了吗?

    写在前面 在Java8之前,在某个类或者方法,字段或者参数上标注注解时,同一个注解只能标注一次.但是在Java8中,新增了重复注解和类型注解,也就是说,从Java8开始,支持在某个类或者方法,字段或者 ...

  9. javaSE高级篇5 — java8新特性详解———更新完毕

    java8新特性 在前面已经见过一些东西了,但是:挖得有坑儿 1.lambda表达式 lambda表达式是jdk1.8引入的全新语法特性 它支持的是:只有单个抽象方法的函数式接口.什么意思? 就是说: ...

  10. Java8新特性—四大内置函数式接口

    Java8新特性--四大内置函数式接口 预备知识 背景 Lambda 的设计者们为了让现有的功能与 Lambda 表达式良好兼容,考虑了很多方法,于是产生了函数接口这个概念. 什么是函数式接口? 函数 ...

随机推荐

  1. MySQL 有哪些常见的面试题

    MySQL 是一种常用的关系型数据库管理系统,在面试过程中经常会涉及与 MySQL 相关的问题.以下是一些常见的 MySQL 面试题: 1. 介绍一下 MySQL 和其他数据库管理系统的区别. - M ...

  2. 本地部署modelscope-agent

    本地部署modelscope-agent 部署流程 在modelscope社区创建一个自己的空间(假设name是LocalAgent),clone空间到本地(或云服务器如魔搭Notebook) git ...

  3. 解决报错:Java 8 date/time type `java.time.Duration` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling

    1.错误信息: Java 8 date/time type java.time.Duration not supported by default: add Module "com.fast ...

  4. 使用代码生成工具快速开发应用-结合后端Web API提供接口和前端页面快速生成,实现通用的业务编码规则管理

    在前面随笔<在Winform应用中增加通用的业务编码规则生成>,我介绍了基于Winform和WPF的一个通用的业务编码规则的管理功能,本篇随笔介绍基于后端Web API接口,实现快速的Vu ...

  5. 整一个工具类【根据URL地址获取file文件对象】

    整一个工具类[根据URL地址获取file文件对象] 直接将网络url文件转换为file对象 import java.io.*; import java.net.URL; public class Im ...

  6. 告别复杂排版:Markdown语法指南

    导语:Markdown作为一种轻量级的标记语言,以其简洁.易学的语法和强大的兼容性赢得了广泛的应用.本文将为您详细介绍Markdown的起源.基本语法及其在写作.博客.项目管理等场景的应用,带您领略这 ...

  7. Android学习--Intent

    Intent : Intent 是一个动作的完整描述,一种运行时的绑定机制,Intent中包含对Intent有兴趣的组件信息,如对动作的产生组件.接受组件和传递的数据信息.Android根据此Inte ...

  8. OpenCV计算机视觉学习(15)——浅谈图像处理的饱和运算和取模运算

    如果需要其他图像处理的文章及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractic ...

  9. 从热爱到深耕,全国Top10开源软件出品人探索“开源云上行”

    本文分享自华为云社区<[先锋开发者云上说]从热爱到深耕,全国Top10开源软件出品人探索"开源云上行">,作者:华为云社区精选. <2022-2023 中国开源开 ...

  10. 聚焦企业开放OpenAPI痛难点,华为云API Explorer助力构建API门户

    本文分享自华为云社区<聚焦企业开放OpenAPI痛难点,华为云API Explorer助力伙伴构建API门户>,作者:华为云PaaS服务小智. 当前,IT研发的主流架构已从单体架构向微服务 ...