Java SE 8新功能介绍:使用Streams API处理集合

使用Java SE 8 Streams的代码更干净,易读且功能强大.....

“ Java SE 8新功能介绍”系列的这篇文章中,我们将深入解释和探索代码,以了解如何使用流遍历集合,从集合和数组创建流,聚合流值。

在上一篇文章“ Lambda的遍历,过滤,处理集合和方法增强 ”中; 我已深入探讨和探索如何使用lambda表达式和方法引用 遍历集合,使用谓词接口过滤它们,在接口中实现默认方法,最后在接口中实现静态方法

  • 源代码托管在我的Github帐户上:从此处克隆它。

目录

  1. 使用流遍历集合。
  2. 从集合和数组创建流。
  3. 汇总流值。

1.使用流遍历集合

介绍

Java的collections框架使您可以使用ListMap类的接口以及ArraylistHashMap类的类来轻松管理应用程序中数据的有序和无序集合。 自从首次引入以来, 收藏框架一直在不断发展。 在Java SE 8中,我们现在有了一种使用流API 管理遍历聚合集合的新方法。 基于集合的流与输入或输出流不同。

怎么运行的

相反,这是处理整个数据而不是单独处理每个项目的新方法。 使用流时,无需担心循环或遍历的细节。 您直接从集合创建流对象。 然后,您可以使用它进行各种操作,包括遍历,过滤和汇总其值。 我将从eg.com.tm.java8.features.stream.traversing项目的Java8Features包中的该示例开始。 在类代码SequentialStream ,在Java SE 8中,有两种收集流,称为顺序流和并行流。

List<person> people = new ArrayList<>();people.add(new Person("Mohamed", 69));
people.add(new Person("Doaa", 25));
people.add(new Person("Malik", 6));Predicate<person> pred = (p) -> p.getAge() > 65;displayPeople(people, pred);...........private static void displayPeople(List<person> people, Predicate<person> pred) {System.out.println("Selected:");people.forEach(p -> {if (pred.test(p)) {System.out.println(p.getName());}});
}

顺序流是两者中较简单的一种,就像迭代器一样,它使您可以一次处理一个集合中的每个项目。 但是语法比以前少了。 在这段代码中,我创建了一个人数组列表,并转换为列表。 它具有一个复杂对象的三个实例,一个名为Person的类。 然后,我使用Predicate声明条件,并显示仅满足条件的人员。 在displayPeople()方法的第48至52行中,我遍历集合,遍历数据,并一次测试一项。 运行代码,您应该得到以下结果:

Selected:
Mohamed

我将向您展示如何使用流对象重构该代码。 首先,我将注释掉这些代码行。 现在,在注释的代码下面,我将从集合对象开始。 人。 然后,我将调用一个名为stream的新方法。 与集合本身一样,流对象也具有通用声明。 如果从集合中获取流,则该流中的项目与集合本身的类型相同。 我的集合具有person类的实例,因此流使用相同的泛型类型。

System.out.println("Selected:");//        people.forEach(p -> {//            if (pred.test(p)) {//                System.out.println(p.getName());//            }//        });people.stream().forEach(p -> System.out.println(p.getName()));
}

您将流作为方法调用,现在有了一个可以处理的流对象。 我将从对每个方法的四个简单调用开始,这将需要一个Lamda表达式。 我将传递参数。 这就是我这次通过迭代处理的列表中的项目。 然后是Lambda运算符,然后执行该方法。 我将使用简单的系统输出,并输出此人的姓名。 我将保存并运行代码,并得到结果。 由于不再过滤,因此我将显示列表中的所有人员。

Selected:
Mohamed
Doaa
Malik

现在,一旦有了流,就可以轻松地使用谓词对象。 当我为每种方法使用并一次处理每个项目时。 我必须显式调用谓词的测试方法。 但是,使用流可以调用名为filter的方法。 那需要一个谓词对象,并且所有谓词都有一个测试方法,因此它已经知道如何调用该方法。 因此,我将对此代码进行一些分解。 我将对.forEach()方法的调用向下移动几行,然后在中间的空行上调用新的filter方法。

people.stream().filter(pred).forEach(p -> System.out.println(p.getName()));

filter方法需要谓词接口的实例。 然后我将传入谓词对象。filter方法返回流,但现在返回过滤后的版本,从那里我可以调用forEach()方法。 我将运行代码,现在我只显示满足谓词条件的集合中的项目。 您可以在流中做更多的事情。 查看Java SE 8 API文档中有关流的文档。

Selected:
Mohamed

您将看到,除了过滤之外,您还可以对流进行聚合并执行各种其他操作。 在结束本演示之前,我想向您展示顺序流和并行流之间的非常重要的区别。 Java SE 8中的流API的目标之一是让您分拆具有多个CPU的系统上的处理。 Java运行时会自动处理这种多CPU处理。 您需要做的就是将顺序流转换为并行流。

有两种语法上的实现方式。 我将复制我的顺序流类。 我将转到程序包浏览器,然后将其复制并粘贴。 我将命名新类ParallelStream 。 我将开设新班。 在此版本中,我将删除注释的代码。 我不再需要了 现在,这里有两种创建并行流的方法。 一种方法是从集合中调用另一种方法。 代替流,我将调用parallelStream() 。 现在,我有了一个流,该流将自动分解并分配给不同的处理器。

private static void displayPeople(List<person> people, Predicate<person> pred) {System.out.println("Selected:");people.parallelStream().filter(pred).forEach(p -> System.out.println(p.getName()));}

我将运行代码,然后看到它在做同样的事情,过滤并返回数据。

Selected:
Mohamed

这是创建并行流的另一种方法。 我将再次调用此stream()方法。 然后从流方法中,我将调用一个名为parallel()的方法,该方法完全相同。 我从顺序流开始,最后以并行流结束。 它仍然是一条小溪。 它仍然可以过滤,仍然可以按照与以前完全相同的方式进行处理。 但是现在它将在可能的情况下分解。

people.stream().parallel().filter(pred).forEach(p -> System.out.println(p.getName()));

结论

对于何时在顺序流上使用并行流没有明确的规定。 它取决于数据的大小和复杂性以及硬件的功能。 您正在运行的多CPU系统。 我唯一可以给您的建议是尝试使用您的应用程序和数据。 设置基准,确定运行时间。 使用顺序流和并行流,看看哪种效果更好。

2.从集合和数组创建流

介绍

Java SE 8的流API旨在帮助您管理数据集合,即集合框架的成员,例如数组列表或哈希图。 但是您也可以直接从数组创建流。

怎么运行的

Java8Features这个项目中,在例如eg.com.tm.java8.features.stream.creating包中,我有一个名为ArrayToStream的类。 在其主要方法中,我创建了一个包含三个项目的数组。 它们分别是我的复杂对象Person类的实例。

public static void main(String args[]) {Person[] people = {new Person("Mohamed", 69),new Person("Doaa", 25),new Person("Malik", 6)};for (int i = 0; i < people.length; i++) {System.out.println(people[i].getInfo());}
}

此类具有专用字段的setter和getter以及新的getInfo()方法,以返回串联的字符串。

public String getInfo() {return name + " (" + age + ")";
}

现在,如果您想使用流来处理此数组,您可能会认为可能需要将其转换为数组列表,然后再从那里创建该流。 但是事实证明,有两种方法可以直接从数组转换为流。 这是第一种方法。 我将不需要这三行代码来处理数据。 因此,我将其注释掉。 然后在这里,我将声明一个对象,其类型为流。

Stream是接口,它是java.util.stream的成员。 当我按Ctrl + Space并从列表中选择它时,系统会询问我该流将管理的项目的通用类型。 这些将是Person类型的项目,就像数组本身中的项目一样。 我将用小写字母命名新的流对象stream。 这是创建流的第一种方法。 再次使用流接口,并调用名为of()的方法。 请注意,有几个不同的版本。

一个带有单个对象,另一个带有一系列对象。 我将使用带有一个参数的参数,然后将其传递给数组people ,这就是我需要做的所有事情。 Stream.of()表示接受此数组并将其包装在流中。 现在,我可以使用lambda表达式,过滤器,方法引用和对Stream对象起作用的其他东西。 我将为每个方法调用流对象,我将传递一个lambda表达式,我将传递当前人,然后在lambda运算符之后,我将输出该人的信息。 使用对象的getInfo()方法。

Person[] people = {new Person("Mohamed", 69),new Person("Doaa", 25),new Person("Malik", 6)};//        for (int i = 0; i < people.length; i++) {
//            System.out.println(people[i].getInfo());
//        }Stream<Person> stream = Stream.of(people);stream.forEach(p -> System.out.println(p.getInfo()));

我将保存并运行代码,并得到结果。 我以将它们放在数组中的相同顺序输出项目。 因此,这是使用Stream.of()的一种方法。

Mohamed (69)
Doaa (25)
Malik (6)

还有另一种方法可以做完全相同的事情。 我将复制该行代码,并注释掉一个版本。 这次使用Stream.of() ,我将使用一个名为Arrays的类,该类是包java.util的成员。

从那里,我将调用一个名为stream的方法。 注意,stream方法可以包装在各种类型的数组周围。 包括基本体和复杂对象。

//      Stream<person> stream = Stream.of(people);Stream<person> stream = Arrays.stream(people);stream.forEach(p -> System.out.println(p.getInfo()));

我将保存并运行该版本,流将执行与以前完全相同的操作。

Mohamed (69)
Doaa (25)
Malik (6)

结论

因此, Stream.of()Arrays.stream()会做完全相同的事情。 取一个原始值或复杂对象的数组,然后将它们转换为流,然后可以将其与lambda,过滤器和方法引用一起使用。

3.汇总流值

介绍

前面已经描述了如何使用流来迭代集合。 但是,您也可以使用流来聚合集合中的项目。 也就是说,计算求和平均值计数等。 当您执行此类操作时,了解并行流的本质很重要。

怎么运行的

所以我要在项目启动这个示范Java8Features ,在包eg.com.tm.java8.features.stream.aggregating 。 我将首先使用ParallelStreams类。 在此类的main方法中,我创建了一个包含字符串项目的数组列表。

我正在使用一个简单的for循环,已将10,000个项目添加到列表中。 然后在第35和36行上,我创建一个流,并为每种方法使用,并一次输出一个流。

public static void main(String args[]) {System.out.println("Creating list");List<string> strings = new ArrayList<>();for (int i = 0; i < 10000; i++) {strings.add("Item " + i);}strings.stream().forEach(str -> System.out.println(str));
}

当我运行此代码时,我得到了预期的结果。 这些项目按照添加到列表的顺序输出到屏幕。

.........
Item 9982
Item 9983
Item 9984
Item 9985
Item 9986
Item 9987
Item 9988
Item 9989
Item 9990
Item 9991
Item 9992
Item 9993
Item 9994
Item 9995
Item 9996
Item 9997
Item 9998
Item 9999

现在,让我们看看将其转换为并行流时会发生什么。 如前所述,我可以通过调用并行流方法或通过获取流的结果并将其传递给并行来实现。

我会做后者。 现在,我正在使用并行流,该流可以分解并且工作负载可以在多个处理器之间分配。

strings.stream().parallel().forEach(str -> System.out.println(str));

我将再次运行代码并观察会发生什么,请注意,打印的最后一项不是列表中的最后一项。 那将是9,999。 而且,如果我在输出中滚动,我会看到处理以某种方式跳跃。 发生的事情是运行时将数据任意拆分为多个块。

.........
Item 5292
Item 5293
Item 5294
Item 5295
Item 5296
Item 5297
Item 5298
Item 5299
Item 5300
Item 5301
Item 5302
Item 5303
Item 5304
Item 5305
Item 5306
Item 5307
Item 5308
Item 5309
Item 5310
Item 5311

然后将每个块交给可用的处理器。 只有在处理完所有块之后,才会执行我的下一部分Java代码。 但是在内部,在对forEach()方法的调用中,所有这些工作都根据需要进行了拆分。 现在,这可能会或可能不会带来性能上的好处。 这取决于数据集的大小。 以及您的硬件的性质。 但是,此示例向您展示的一件事是,如果需要顺序处理项目,即一次将它们添加到集合中的顺序相同,那么并行流可能不是这样做的方法。它。

顺序流可以确保每次都以相同的顺序工作。 但是,按照定义,并行流将以最有效的方式处理事务。 因此,并行流在聚合操作时特别有用。 您要考虑集合中的所有项目,然后从中创建某种总价值。 我将向您展示一些示例,这些示例包括对集合中的项目进行计数,取平均值并使用字符串对其求和。

在此类main方法中的CountItems中,我从相同的基本代码开始。 在列表中创建10,000个字符串。 然后,每种方法都有一个循环遍历并一次处理它们的方法。

public static void main(String args[]) {System.out.println("Creating list");List<string> strings = new ArrayList<>();for (int i = 0; i < 10000; i++) {strings.add("Item " + i);}strings.stream().forEach(str -> System.out.println(str));
}

在此示例中,我不是要单独处理每个字符串,而是要对它们进行计数。 因此,我将注释掉该代码,这是我将使用的代码。 由于我不知道确切要收集多少物品。 我将兑现要创建的结果作为一个长整数。

我将其命名为count ,并通过调用strings获得它的值。 那是我的集合.stream() .count() ,并且返回一个长值。 然后,我将使用系统输出并报告结果。 用count:然后附加结果。

//      strings.stream()
//             .forEach(str -> System.out.println(str));long count = strings.stream().count();System.out.println("Count: " + count);

我将保存更改并运行代码,并得到结果。 集合中项目的计数几乎是瞬时的。

Creating list
Count: 10000

现在,为了使它更具戏剧性,我将在此处添加几个零,现在我要处理1,000,000,000个字符串。 我将再次运行代码,结果几乎立即又返回。

Creating list
Count: 1000000

现在看看如果我并行化字符串会发生什么。 我将在此处平行添加点:

//      strings.stream()
//             .forEach(str -> System.out.println(str));long count = strings.stream().parallel().count();System.out.println("Count: " + count);

然后我将运行代码,这将花费更长的时间。 现在,我可以通过捕获操作前后的当前时间戳来确定执行这些操作需要多长时间。 然后做一点数学。 它将显示的内容可能因一个系统而异。 但是以我的经验,当处理包含简单值的这类简单集合时,并行流并没有太大的好处。 您的里程可能会很高。 我鼓励您做自己的基准测试。 但这就是您要计数的方式。

让我们看一下求和和平均值 。 我去上课SumAndAverage 。 这次,我列出了三个人对象,每个对象的年龄不同。 我的目标是获得三个年龄的总和,以及三个年龄的平均值。 在person类的所有实例都添加到列表之后,我将添加一行新代码。 然后创建一个整数变量,命名为sum

我将从使用people.stream().获得流开始people.stream(). 从那里,我将调用一个名为mapToInt()的方法。 注意,这里有一个Map方法。 mapToDouble()mapToLong()也是如此。 这些方法的目的是获取复杂的对象并从中提取简单的原始值,并创建这些值的流,然后使用Lambda表达式执行此操作。 因此,我将选择mapToInt()因为每个人的年龄都是整数。

对于Lambda表达式,我将从代表当前人的变量开始。 然后是Lambda运算符,然后是一个返回整数的表达式。 我将使用p.getAge() 。 这将返回称为int字符串或整数字符串的内容。 还有一个双字符串类和其他一些类。 现在从这个流中开始,因为我已经知道它是一个数值,所以我可以调用一个名为sum()的方法。 就是这样。 现在,我总结了我收藏中所有交友对象的所有陈旧价值。 仅需一条语句,我将使用系统输出输出结果。 我的标签将是年龄的总和,我将在其后加上总和。

List<person> people = new ArrayList<>();people.add(new Person("Mohamed", 69));people.add(new Person("Doaa", 25));people.add(new Person("Malik", 6));int sum = people.stream().mapToInt(p -> p.getAge()).sum();System.out.println("Total of ages " + sum);

我将保存我的代码并运行它。 这三个年龄段的总和为100。

Total of ages 100

平均这些值非常相似。 但是,因为每当进行平均除法运算时,都可能会遇到被零除的问题,因此,当您进行平均时,您会得到称为Optional变量的信息。

您可以使用多种类型。 对于我的平均而言,我期望一个双精度值会回来。 因此,我将创建一个名为OptionalDouble的变量。 注意,还有可选的Int和可选的日志。 我将Avg命名为变量Avg 。 我将使用刚才用来获取总和的相同类型的代码,从people.stream() 。 然后从那里,我将再次使用mapToInt() 。 然后,我将传递上次使用的相同的lambda表达式,然后从那里调用average方法。

现在有了OptionalDouble对象,在处理它之前,应始终确保它实际上具有一个double值,并使用名为isPresent()的方法来执行此操作。 因此,我将从一个if else代码模板开始。 然后将条件设置为avg.isPresent() 。 如果条件成立,我将使用系统输出。 我将其标记为“平均”。 然后我将附加平均变量。 在else子句中,我将简单地说平均数未计算出来。

OptionalDouble avg = people.stream().mapToInt(p -> p.getAge()).average();
if (avg.isPresent()) {System.out.println("Average: " + avg);
} else {System.out.println("average wasn't calculated");
}

现在,在这个示例中,我知道它将成功,因为我已经为所有三个人提供了年龄,但情况并非总是如此。 就像我说的那样,如果最终遇到被零除的情况,则可能无法获得双倍的价值。 我将保存并运行代码,并注意使用可选的double类,它是一个复杂的对象。

Total of ages 100
Average: OptionalDouble[33.333333333333336]

因此,类型将包裹在实际值周围。 我将转到此代码,直接在其中引用该对象,并将其getAsDouble()方法。

if (avg.isPresent()) {System.out.println("Average: " + avg.getAsDouble());
} else {System.out.println("average wasn't calculated");
}

现在,我将返回原始的double值。 我将再次运行代码,现在结果就是我想要的。

Total of ages 100
Average: 33.333333333333336

结论

因此,使用流和lambda表达式,您可以使用少量代码轻松地从集合中计算聚合值。

资源资源

  1. Java教程,聚合操作
  2. Java流接口API
  3. Java教程,Lambda表达式
  4. JSR 310:日期和时间API
  5. JSR 337:Java SE 8发行内容
  6. OpenJDK网站
  7. Java平台,标准版8,API规范

我希望您喜欢阅读它,就像我喜欢编写它一样,如果您喜欢它,请分享,传播信息。

翻译自: https://www.javacodegeeks.com/2015/07/java-se-8-new-features-tour-processing-collections-with-streams-api.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357888.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在HTML中使用css3实现雪人动画效果

背景:圣诞节又到了,拿什么来哄女朋友开心? 项目结构: html: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xht…

mysql 释放内存_mysql查询后释放内存

我正在使用CodeIgniter从远程服务器导入大表.我一次将查询分成1000行.这将是一个在后台运行的cron脚本.$userDB是本地数据库对象,而$remoteDB是远程数据库对象private function fetch_remote_db_table($remoteDB, $remoteTable, $localTable FALSE){$success FALSE;$returnOb…

linux线程池简单实例

linux线程池简单实例转载于:https://www.cnblogs.com/adong7639/p/5044685.html

圣诞节又到了,作为程序猿的我用代码给女朋友送了一个礼物

圣诞节又到了&#xff0c;拿什么来哄女朋友开心&#xff1f;我们先来做一个简单的雪人动画&#xff1a;项目结构&#xff1a;html:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.d…

【Linux】权限篇(二)

权限目录 1. 前言2. 权限2.1 修改权限2.2 有无权限的对比2.3 另外一个修改权限的方法2.3.1 更改用户角色2.3.2 修改文件权限属性 3. 第一个属性列4. 目录权限5. 默认权限 1. 前言 在之前的一篇博客中分享了关于权限的一些知识&#xff0c;这次紧接上次的进行&#xff0c;有需要…

mysql 替代like_mysql用instr替代like查询

使用内部函数INSTR&#xff0c;代替传统的LIKE方式查询&#xff0c;不仅速度更快&#xff0c;而且省去了通配符检查&#xff0c;因此更加安全。INSTR()函数返回字符串中子字符串第一次出现的位置。如果在str中找不到子字符串&#xff0c;则INSTR()函数返回零(0)。下面说明了INS…

项目实战:小米商城官网及秒杀高仿(html+css+js)

导读:秒杀的检索结果,小米官方网站包含秒杀价格及秒杀适配机型,官方推荐秒杀产品,帮助米粉挑选合适自己的秒杀商品。 仿小米手机商城的全套页面。包含首页,订单页,列表页,商品详情页,个人中心,购物车,等等几十个页面。 有轮播的实现,demo 基于html css 实现小米官网部分内容搭…

Unity3d 配置OpenCV(EmguCV) 周围环境

最近毕业。我们一直在研究如何Unity正在使用EmguCV&#xff0c;最后&#xff0c;有些吃老本的今天。 我的环境&#xff1a;Unity3d 4.3.1f libemgucv-windows-universal-gpu-2.4.9.1847 原文參考&#xff1a;http://forum.unity3d.com/threads/182600-OpenCV-(EMGUC…

Java 8的方法参考进一步限制了重载

方法重载一直是一个充满喜忧参半的话题。 我们已经在博客上介绍了它&#xff0c;并介绍了几次警告&#xff1a; 您会后悔对Lambdas应用重载&#xff01; 保持干燥&#xff1a;方法重载 为什么每个人都讨厌操作员超载 API设计师&#xff0c;请小心 重载有用的主要原因有两个…

多态性(C#)

在面向对象编程中继承性和多态性是重要机制&#xff0c;前面我为大家分享了我对“类的继承”的理解&#xff0c;哪么今天我就跟大家分享下我对“多态性(C#)”的理解。 首先我们先来看看多态的定义&#xff0c;同一操作作用于不同的对象&#xff0c;可以有不同的解释&#xff0c…

孙叫兽重磅推荐Chrome插件——CSDN浏览器助手

导读:解决你在浏览器上遇到的各种问题,无论你是学生小白、还是职场老鸟,都可以借助这个插件,打造个性化浏览器,提升工作学习效率。 此插件经过多轮迭代,体积小,内存占用少,便于开发者快速安装和使用。 官方地址:https://plugin.csdn.net/ 目录 安装方法:

mysql concat 引号_在MySQL concat里面使用多个单引号,三引号的问题

在动态拼接字符串时&#xff0c;我们常会用到字符拼接&#xff0c;我对拼接的引号不理解&#xff0c;如&#xff1a;1、 id 为什么是3个引号&#xff0c;为什么左边一个加号右边一个加号(能不能着重帮我解释下这个&#xff0c;详细点)SQL codesum(case Leave when id then D…

【APICloud系列|21】使用APICloud敏捷式开发总结,回顾开发一个完整APP过程。

导读:APICloud是柚子(北京)科技有限公司创建的低代码开发平台,总部位于北京, 通过生产力工具与混合开发技术,为企业与开发者构建高效的IT环境;在APICloud平台已有80万注册用户,平台每日生成安装包超6000个。业务团队延伸至上海、深圳、重庆、青岛等10余个城市。 APICloud是…

mysql 存储过程 记录是否存在_如何检查MySQL中是否存在存储过程?

让我们首先创建一个存储过程-mysql> DELIMITER //mysql> CREATE PROCEDURE ExtenddatesWithMonthdemo(IN date1 datetime, IN NumberOfMonth int )-> BEGIN-> SELECT DATE_ADD(date1,INTERVAL NumberOfMonth MONTH) AS ExtendDate;-> END;-> //mysql> DEL…

[ExtJS5学习笔记]第三十五条 sencha extjs 5 组件查询方法

一UI前部组件势必更加&#xff0c;我们通常习惯性使用ID获取部件操作的需要。但是&#xff0c;这种方法是extjs推荐么&#xff1f;你有吗extjs利用它来获取组件的推荐方法&#xff1f; 夹 文件夹extjs的查询组件的API查询实例主要的组件查询组件树查询通过组件的属性检索属性匹…

数据湖 多维数据集_按汇总分组/多维数据集

数据湖 多维数据集时不时地&#xff0c;您会遇到一个使您达到SQL限制的要求。 我们中的许多人可能会早早放弃并使用Java / [或您的语言]计算内容。 相反&#xff0c;使用SQL可能是如此简单快捷。 如果您使用的是高级数据库&#xff0c;例如DB2 &#xff0c; Oracle &#xff0c…

【APICloud系列|22】 videoPlayer模块(视频播放)的实现

导读:videoPlayer 封装了视频播放功能(不支持音频播放)。可快进、快退设置播放位置等操作,亦可设置屏幕亮度和系统声音大小。通过监听接口可获取模块上的各种手势操作事件。 模块详情:http://www.apicloud.com/mod_detail/35792 index.html <html><head>&l…

mysql数据库突然连不上了_mysql数据库突然连接不上去

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

FlexyPool如何同时支持连接代理和装饰器

代理人 FlexyPool监视连接池使用情况&#xff0c;因此需要拦截连接关闭方法调用。 为了简单起见&#xff0c;第一个版本为此目的依赖动态代理&#xff1a; private static class ConnectionInvocationHandler implements InvocationHandler {public static final String CLOS…

集合视图控制器(CollectionViewController) 、 标签控制器(TabBarController) 、 高级控件介绍...

1 创建集合视图&#xff0c;设置相关属性以满足要求 1.1 问题 集合视图控制器UIConllectionViewController是一个展示大量数据的控制器&#xff0c;系统默认管理着一个集合视图UICollectionView&#xff0c;功能几乎和UITableViewController差不多&#xff0c;能够以多行多列的…