功能介面

目录

1.简介 2.理由 3. Lambda表达式 4.谓词<T> 5. BiPredicate <T,U> 6.函数<T,R> 7. BiFunction <T,U,R> 8.消费者<T> 9. BiConsumer <T,U> 10.供应商<T> 11.一元运算符<T> 12. BinaryOperator <T>

1.简介

函数接口是Java 8提供的强大机制,使我们可以将函数作为参数传递给其他方法。 实际上,此选项在Java的早期版本中已经存在,例如,具有接口Comparator。

什么是功能接口? 功能接口定义了“对象”,它们不像传统对象那样存储值,而仅存储“功能”。 请注意,“对象”和“功能”都在引号之间,这是因为功能接口不是实际的对象或功能,而只是一种机制,该机制具有一种方法来接收功能元素作为参数。 让我们回顾一下Comparator界面:Comparator定义了什么? 定义了自然排序标准,以使compare方法告诉我们两个给定对象中的哪个可以视为较小对象。 如果将Comparator对象传递给方法,则我们将为该方法提供能够告知对象顺序的函数。 该方法相对于此排序是“通用的”,并且必须准备好接收任何条件并根据输入的排序执行其功能。

这样,例如,来自Collections类的sort方法可以接收Comparator类型的对象。 以前,必须已经实现了Comparator类型的类来定义要比较的类的对象的顺序。

例。 根据价格从大到小的顺序排列航班的Comparator类是:

public class ComparatorFlightPrice implements Comparator<Flight> {public int compare(Flight v1, Flight v2){return v1.getPrice().compareTo(v2.getPrice());}
}

调用可能是:

Collections.sort(flightList, new ComparatorFlightPrice());

可以看出,由于接收到的Comparator对象告诉sort必须如何对flightList中的值进行排序,因此sort方法将接收一个函数类型参数。 很明显,必须准备Collections类的sort方法的代码以在不同条件下进行排序。 为此,sort方法在其代码行中具有对其作为参数接收的对象的compare方法的一般调用。 这样,如果它收到按价格定购的比较器,它将按航班价格定购输入清单,而如果按乘客号传递通过的比较器定单,则这将成为订购标准。

Java 8的作用是扩展功能接口的数量及其可用性,以定义一组参数为这些接口的方法。

2.理由

让我们研究不同于Comparator的功能接口的另一种可能的应用。 有很多算法在其方案中使用布尔条件。 最简单的例子之一是计数器算法模式,该模式返回满足一定条件的集合中元素的数量:今天有多少次完整航班起飞? 本周有几班飞往马德里的航班? 等。我们知道此算法的方案如下:

Scheme counterInitiate counterFor each element in collection If conditionIncrement counterEndIfEndForReturn counter}

该方案将元素集合和必须验证的条件作为输入,并将计数器作为输出。 例如,让我们看一下来自Airport的方法,该方法计算了前往特定目的地的航班数量以及特定日期之后的航班数量。

public Integer counterFlightsDate(Date f){Integer counter=0;for(Flight v:flights){if (v.getDate().compareTo(f)>0){counter++;}}return counter;}public Integer counterFlightsDestination(String d){Integer counter =0;for(Flight v:flights){if (v.getDestination().equals(d)){counter ++;}}return counter;}

显然,除了条件和参数类型外,这两种方法的代码完全相同:第一种情况的Date f和第二种情况的目标String d。 此代码将按以下方式调用:

Integer cont1 = SVQairport.counterFlightsDate("Madrid");
System.out.println("The number of flights to Madrid is "+cont1);
Integer cont2 = SVQairport.counterFlightsDestination(new Date(16,07,2014));
System.out.println("The number of flights later than 16th of July is "+cont2);

让我们假设我们可以通过在“ if”上指定的条件作为参数。 然后,方法代码可以推广为以下内容:

public Integer genericalFlightCount(Condition<Flight> filter){Integer counter=0;for (Flight v:flights){if (condition of filter over v){counter ++;}}return counter;}

第1行:稍后,此假设类型的Condition实际上将是谓词类型
第4行:此表达式实际上是filter.test(v),因为这是Predicate中实现的方法

这样,我们将拥有一个针对Airport的通用计数器方法,该方法一旦编码,便可以使用不同的布尔表达式调用并具有不同的功能。 为了能够将布尔表达式作为参数传递,我们需要一个类型(接口)条件,该条件将实现方法的接收和所涉及类型的对象(在这种情况下为Flight),并返回布尔类型的值符合要求的条件。 功能接口谓词就是这种可能性,它将是下一部分要研究的第一个示例。

该通用方法的调用为:

Integer cont1 = SVQairport.genericalFlightCount(v-> v.getDestination.equals("Madrid"));
System.out.println("The number of flights from Madrid is "+cont1);Date f = new Date(16,07,2014)
Integer cont2 = SVQairport.genericalFlightCount(v->v.getDate().compareTo(f)>0);
System.out.println("The number of flights later than 16th of July is "+cont2);

第1行:这是一个lambda表达式(请参阅下一部分),它表示作为参数传递的“条件”或“过滤器”表示每个Flight v返回有关其目的地是否为Madrid的条件
第6行:这是另一个lambda表达式,对于每个Flight v,如果出发日期晚于7月14日,则返回true

3. Lambda表达式

Java 8还有一点变化,那就是将功能接口作为方法的参数提供的方式。 如上例所示,为了在Java7中使用Comparator,定义了一个包含compare方法的外部类,并且该类的对象在调用时或通过先前创建的方法传递给需要它的方法宾语。 Java 8还有其他更灵活的机制来定义功能接口:lambda表达式和方法引用。

Lambda表达式是一种方法的简化,其中输入参数和输出表达式由箭头运算符'->'分隔。 输入参数写在方括号之间,并用逗号分隔。 如果接口具有单个输入参数,则不需要括号。 因此,lambda表达式的第一部分的形状将类似于()->如果没有输入参数,则x->如果只有一个或(x,y)->两个参数。 通常,不必定义参数的类型,因为Java 8可以从上下文中推断出它们。 在箭头运算符->之后,我们必须编写表达式,该表达式将成为我们声明的接口的返回值。

示例1.接收航班并返回价格的功能接口为:

x-> x.getPrice();

例子2.一个接收代表一个数字的String并返回一个带有相应值的Integer的功能接口将写为:

x -> new Integer(x);

示例3.让我们再举一个接口Comparator的示例。 可以通过直接在调用代码上使用lambda表达式构造所需的Comparator来执行对Collections的sort方法的调用:

Collections.sort(flightList,(x,y)->x.getPrice().compareTo(y.getPrice()));

lambda表达式由其参数形成,在这种情况下为两个:括号之间的x和y,并用逗号分隔。 有两个参数,因为接口Comparator中的compare方法也需要两个参数。 正如我们可以看到的,即使我们不需要正式指定x和y都是对Flight类型的引用,因为Java 8编译器能够从上下文中“理解”它,因为既然我们要订购List <Flight> ,比较器必须为Flight类型,因此compare方法的参数也必须为该类型。 然后,在箭头符号“->”之后,我们编写表达式,compare方法应返回; 在我们的例子中,是一个类型为int的表达式,其中包含航班价格之间的比较。

引用比较器的另一种方法是调用返回我们要比较的属性的方法。 例如,Java 8允许以下其他调用:

Collections.sort(flights,Comparator.comparing(Flight::getPrice));

在第二次调用时,Comparator接口调用静态方法compare,其参数是Function类型的功能接口,可以仅通过引用返回我们要比较的属性的方法来定义它。

Lambda表达式最直接在需要功能接口的方法调用时直接使用,但是如果某个Lambda表达式将要使用多次,则可以使用标识符声明它。

例。 为了定义一个航班是否满载,我们将编写:

Predicate<Flight> flightFull = x-> x.getNumPassengers().equals(x.getNumSeats());

这样,标识符flightFull可以在所有具有Predicate类型参数的调用上替换Predicate接口。

如果功能接口需要输入的参数类型不同于为接口本身指定的类型,则更好的定义方法就好像它是方法一样。

例。 如果我们需要定义一个飞行谓词,以接收日期类型的参数,并告诉飞行是否在给定日期之后起飞,则我们定义:

Predicate<Flight> laterDate(Date f){return x -> x.getDate().compareTo(f)>0;}

4.谓词<T>

如前所述,谓词接口为需要某种过滤器或条件的方法实现了逻辑条件。 谓词实现了一种称为test的方法,该方法从类型T的对象返回布尔值。因此,谓词类型用于根据类型T的对象是否满足特定属性对其进行分类。 例如,给一个Flight告诉它是否完成,给一个Book告诉它的标题是否包含某个特定单词,给一个Song告诉它是否持续超过x秒,或者给一个String告诉它是否以某个字符开头。

示例1.判断航班是否已满的谓词是:

Predicate<Flight> flightFull = x-> x.getNumPassengers().equals(x.getNumSeats());

示例2.如果需要基于参数定义条件,则可以为功能接口提供输入参数。 例如,如果我们需要确定某个航班是否是从确定的日期开始的,则可以定义:

Predicate<Flight> equalDate(Date f){return x -> x.getDate().equals(f);}

此外,还可以使用专用接口(例如DoublePredicate,IntPredicate和LongPredicate)从基本数据类型的对象获取逻辑值。

默认方法

谓词接口还具有实现逻辑操作的三种方法:negate()和(Predicate)和or(Predicate)。 例如,如果我们需要Predicate类型的参数来判断Flight是否对应于某个日期且已满,则将其写为:

equalDate(f).and(flightFull)

5. BiPredicate <T,U>

BiPredicate接口从两个不同类型的参数生成逻辑值。 例如,给定一个代表目的地和航班的字符串,它将返回该航班是否去往该目的地,给定一首歌曲和一段持续时间,它将判断歌曲的持续时间是否小于指定的持续时间,等等。

例。 如果某个航班在指定日期起飞,则返回的界面为:

BiPredicate<Flight, Date> getCoincidence = (x,y)-> y.equals(x.getFecha());

6.函数<T,R>

函数是带有apply方法的接口,该接口接收T类型的参数并返回R类型的对象。它主要用于从另一种派生或组合的类型转换对象。 例如,书籍的作者,歌曲的持续时间,航班的乘客人数等。Java 8提供了一组专用接口,这些接口的输入或输出参数类型不同。 例如,ToDoubleFunction <T>,ToIntFunction <T>,ToLongFunction <T>专门用于接收类型T的对象并返回接口名称上指定的类型。 这些接口实现了一个称为applyAsX的方法,其中X将根据情况区分为Double,Int或Long。 相反,函数LongFunction <R>,IntFunction <R>和DoubleFunction <R>接收名称上指定的类型的值,并使用apply方法返回另一种类型R。 最后,还有六个名为XToYFunction的接口,其中X,Y取值Double,Int或Long,X为输入参数类型,Y为返回值类型。 他们实现的方法是ApplyAsY,其中Y是返回值类型。

示例1:给定飞行确定其持续时间的功能可以定义为:

Function<Flight, Duration> functionDuration = x->x.getDuration();

在这种情况下,如果Flight类型定义了getDuration方法,则可以在将使用Function类型作为输入参数的方法的调用上使用运算符:::

Flight::getDuration

当然,如果Function的表达式将不只使用一次,则lambda表达式x-> x.getDuration()可以作为需要此函数的方法的输入参数。

示例2.给定一个航班,返回其占用率的函数为:

Function<Flight,Double>functOccRatio=x-> 1.*x.getNumPasengers()/x.getNumSeats();

这种情况是专门功能的一个明显例子:

ToDoubleFunction<Flight> functOccRatio(){return x->1.*x.getNumPassengers()/x.getNumSeats();}

默认方法

Function接口有两种方法,可以让我们操作带有组合的函数:compose(Function)和andThen(Function)。 它们之间的区别在于所涉及功能的应用顺序。 应用方法f.compose(g)产生的函数首先应用g然后应用f,而f.andThen(g)是先应用f然后应用g的结果。

例。 让我们假设我们有一个函数,给定类型为Duration的对象,它将返回其转换为分钟:

Function<Duration,Integer> inMinutes=x->x.getMinutes()+x.getHours()*60;

另一个返回飞行时间的函数:

Function<Flight,Duration> getDuration = Flight::getDuration;

然后,以分钟为单位返回飞行时间的函数将是:

Function<Flight,Integer> getDurationInMinutes=inMinutes.compose(getDuration);

或者:

Function<Flight,Integer> getDurationInMinutes =getDuration.andThen(inMinutes);

7. BiFunction <T,U,R>

BiFunction是一个函数,该函数使用称为apply的方法接收类型T和U的两个参数并返回类型R的结果。 还有三个专门用于返回某种类型的接口:ToDoubleBiFunction,ToIntBiFunction和ToLongBiFunction,它们实现了applyAsX方法,其中X可以是Double,Int或Long。

例。 要获得一个给定日期和航班的函数,该函数返回给定日期与航班起飞之间还剩下多少天,它是:

ToIntBiFunction<Flight, Date> getDays(Flight v, Date f){return (x,y)->y.subtract(x.getDate());}

8.消费者<T>

接口Consumer是Function的变体,其中不返回任何值,这意味着它使用称为accept的方法修改给定对象,该方法接收类型T的对象并返回void。 它们用于定义对对象的操作。 例如,将某个航班的价格增加一定的百分比,将“日期”减去几天,或者在控制台上打印一个值。 Java 8还提供了专门的接口DoubleConsumer,LongConsumer或IntConsumer,它们也实现了accept方法。

例子1.如果我们想将一个航班的价格提高10%,我们将定义一个消费者:

Consumer<Flight> incrementPrice10p = x->x.setPrice(x.getPrice()*1.1);

示例2.如果我们希望在作为参数传递的百分比上执行增量,则可以为Flight类型编写以下方法:

Consumer<Flight> incrementPrice(Double p){return x->x.setPrice(x.getPrice()*(1+p/100.)); }

示例3。找到以下使用者来替换表达式System.out.println是非常常见的:

Consumer<Flight> printFlight = x->System.out.println(x);

例子4.如果我们想要一种Flight方法,该方法可以根据条件对Flight类型的对象执行某种动作,我们可以这样写:

public void applyAction(Predicate<Flight> cond, Consumer<Flight> act){if (cond.test(this)){act.accept(this);}}

一旦我们有了一个类型为Flight的对象v,则调用前一种方法来增加v的价格(如果乘客人数低于50)将是:

v.applyAction(x->x.getNumPassengers()<50, x->x.incrementPrice(10.));

其中增量价格是示例2中定义的使用者。

9. BiConsumer <T,U>

BiConsumer是一个接口,用于定义对两个不同类型的输入参数的操作。 它用于表示修改接收另一个类型对象的对象的操作。 它的专用接口是:ObjDoubleConsumer,ObjIntConsumer和ObjLongConsumer,它们接收类型T的对象和名称上指定的另一类型的对象。 它们都实现了一个称为accept的功能方法。

例。 要更改飞行时间,我们可以编写以下代码:

BiConsumer<Flight, Duration> changeDuration = (x,y)->x.setDuration(y);

10.供应商<T>

Supplier是一个接口,它使用称为get的方法提供T类型的对象而没有任何参数。 此外,还有专门的接口(例如BooleanSupplier,DoubleSupplier,IntSupplier和LongSupplier)提供指定类型的对象。 在这些情况下,他们实现的方法称为getAsX,其中X分别为Boolean,Double,Int或Long。

通常,类型为Supplier的接口只会调用构造函数。 这样,假设FlightImpl具有默认构造函数,则调用Flight构造函数的lambda表达式将是:

Supplier<Flight> giveMeFlight = ()-> new FlightImpl();

如果我们希望供应商有一个争论,我们将不得不写:

Supplier<Flight> giveMeFlight (String s) {return ()->new FlightImpl(s);}

建立供应商的另一种常用方法是使用方法表达式:

Supplier<Set<Integer>> giveMeSet = HashSet::new;

11.一元运算符<T>

UnaryOperator接口表示一个操作,该操作使用apply方法接收一个类型T的单个参数并返回另一个相同类型的对象。 这是Function接口的一种特殊情况,其输入和输出值的类型相同,Java将其实现为Function的子接口。 Java 8还具有专门的接口DoubleUnaryOperator,IntUnaryOperator和LongUnaryOperator,它们分别实现方法applyAsX为X字符链Double,Int或Long。 由于此接口是Function的子接口,因此它也以相同的行为实现默认的方法compose和andThen。

示例1.如果我们需要一个运算符来修改Duration,并添加一个带有参数的特定分钟数,则可以这样写:

public UnaryOperator<Duration> addMinutes(Integer m){return x -> x.sum(new DurationImpl(0,m));}

12. BinaryOperator <T>

接口BinaryOperator表示一个操作,该操作接收两个类型T的操作数,并使用apply方法返回相同类型的结果。 如我们所见,这是BiFunction接口的一种特殊情况,其中三种类型T,U和R相同,Java 8将其实现为BiFunction的子接口。 还可以使用DoubleBinaryOperator,IntBinaryOperator和LongBinaryOperator等专业知识来操作数值。 在这些接口中,它们实现的方法是applyAsX ,其中X可以分别命名为Double,Int或Long。

示例1.我们定义了一个类型为Duration的类型,该类型存储一个Flight的持续时间,以小时和分钟为单位。 如果持续时间类型已经定义了sum方法:

public Duration sum(Duration d) {Integer min = getMinutes() + d.getMinutes();Integer hour = getHours() + d.getHours();return new DurationImpl(hour+min/60,min%60);}

然后我们可以将其重新定义为BinaryOperator:

BinaryOperator<Duration> addDur = (x,y) -> x.sum(y);

等效于其他表达式:

BinaryOperator<Duration> addDur = Duration::sum;

如果未为Duration定义方法sum,我们可以直接定义:

BinaryOperator<Duration> addDur = (x,y)-> {Integer min = x.getMinutes() + y.getMinutes();Integer hour = x.getHours() + y.getHours();return new DurationImpl(hour+min/60,min%60);};

示例2. DoubleBinaryOperator接口允许我们将实函数定义为其他两个函数的组合。 例如,如果我们想将函数h定义为其他两个未知函数f和g的商,我们将编写代码:

public DoubleBinaryOperator functionH(DoubleBinaryOperator f, DoubleBinaryOperator g){return (x,y)->f.applyAsDouble(x,y)/g.applyAsDouble(x,y);}

这样,两个数字的加法与乘积之间的商的可能调用为:

public Double callFunctionH(Double x, Double y){return functionH((a,b)->a+b,(a,b)->a*b).applyAsDouble(x,y);}

翻译自: https://www.javacodegeeks.com/2015/03/functional-interfaces.html

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

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

相关文章

WMI 使用教程_.NET 入门教程

WMI 使用教程_.NET 入门教程 先介绍一下WMI 相关知识: 什么是WMI 呢&#xff1f; Windows 管理规范 (Windows Management Instrumentation ),它的主要功 能包括:访问本地主机的一些信息和服务,可以远程管理计算机(当然你必须拥有足够的权限) 也就是说可以象重起,关机,关闭进程,…

h5输入框提示语 正常文本框提示语

<input id"username" name"username" type"text" placeholder" 请输入用户名/手机号" value"" style"width:100%;height:32px;border-style:none "/> placeholder" 请输入用户名/手机号"&…

研究Java 9 Money and Currency API(JSR 354)

JSR 354定义了一个用于处理货币和货币的新Java API&#xff0c;计划将其包含在Java 9中。在本文中&#xff0c;我们将研究参考实现的当前状态&#xff1a; JavaMoney 。 就像我关于Java 8日期/时间API的帖子一样&#xff0c;该帖子将主要由显示新API的代码驱动。 但是在开始…

jquery css事件编程 尺寸设置

<!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/xhtml"><head><title>jquery css事件编程 尺寸设…

Python2.6 Cx_Oracle Linux下编译安装

分类&#xff1a; python Oracle 2012-06-07 00:04 239人阅读 评论(0) 收藏 举报(一) Python 2.6 安装 1.下载Python2.6.X 版本的源码包&#xff0c;这里采用平台编译安装。 Python-2.6.4.tar.bz2 2.解压缩 ,使用J参数解压bigz2类型的压缩文件 tar -jxvf Python-2.6.4.tar.bz2…

Apache TomEE(和Tomcat)的自签名证书

可能在大多数Java EE项目中&#xff0c;您将拥有具有SSL支持&#xff08; https &#xff09;的部分或整个系统&#xff0c;因此浏览器和服务器可以通过安全连接进行通信。 这意味着在处理数据之前&#xff0c;已发送的数据已加密&#xff0c;传输并最终解密。 问题在于&…

WEB效能测试和负载测试部分截图

效能测试&#xff1a; 负载测试&#xff1a; 转载于:https://www.cnblogs.com/DOOM-scse/archive/2013/01/07/2849110.html

Java8 Lambdas:解释性能缺陷的排序

与Peter Lawrey合作撰写 。 几天前&#xff0c;我对使用新的Java8声明式的排序性能提出了严重的问题。 在这里查看博客文章。 在那篇文章中&#xff0c;我仅指出了问题所在&#xff0c;但在这篇文章中&#xff0c;我将更深入地了解和解释问题的原因。 这将通过使用声明式样式重…

jquery子元素选择器

<!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/xhtml"><head><title>子元素选择器</title>…

Asp.net MVC3.0 基于不同的角色显示不同的菜单

前面提到过用Asp.net MVC3.0正在做一个问答系统性质的论坛。前期把菜单全部显示以方便测试模块功能。现在正在完善&#xff0c;加上角色模块&#xff0c;然后不同的角色登陆系统会看到不同的菜单栏&#xff0c;还有就是游客&#xff08;未登录用户&#xff09;看到的菜单栏。网…

Apache Mesos:编写您自己的分布式框架

在上一篇文章中 &#xff0c;我们了解了mesos是什么&#xff0c;它如何有用&#xff0c;并开始使用它。 在本文中&#xff0c;我们将看到如何在mesos上编写自己的框架。 &#xff08;在mesos中&#xff0c;框架是在其上运行的任何应用程序。&#xff09;本文介绍了一个名为“ m…

jquery可见性选择器(综合)

<!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/xhtml"><head><title>可见性选择器</title>…

LoadRunner如何监控Linux下的系统资源

前一段时间在研究LoadRunner过程中&#xff0c;在进行压力场景测试中通过LoadRunner来实时监控windows的系统资源&#xff0c;在前几节中我已经总结了相关过程&#xff0c;近段时间发现群里有朋友问如何监控Linux下的系统资源&#xff0c;所以我也就此问题搭建了一些的Linux环境…

页面跳转多种方法(加传参)

onclick"javascript:location.href/HelpCenter/HelpCenter/" <a href"/HelpCenter/HelpCenter">帮助中心</a>点击页面返回上一页&#xff1a; onclick"javascript:window.history.go(-1); *********************************************…

log4j的使用

文章出处&#xff1a;http://www.blogjava.net/zJun/archive/2006/06/28/55511.html 首先&#xff0c;要在项目classpath下建立log4j.properties 1. 配置文件 #配置根Logger log4j.rootLogger [level], appenderName1, appenderName2, …#配置日志信息输出目的地Appender log4…

使用@Rule在JUnit中测试文件和目录

多亏了TemporaryFolder Rule在JUnit中使用文件和目录进行测试很容易。 在JUnit中&#xff0c;规则&#xff08; Rule &#xff09;可以替代或设置夹具设置和清除方法&#xff08; org.junit.Before &#xff0c; org.junit.After &#xff0c; org.junit.BeforeClass和org.jun…

jquery简单原则器(匹配索引为指定值的元素)

<!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/xhtml"><head><title>简单选择器</title>&l…

POJ-1664 放苹果 动态规划思想解组合数学

该题说明了状态开设的意义一样,但是从哪个方向去理解推倒状态的转移对解题非常关键.该题扣住是否所有的盘子中有空盘子,就得到了一个非常简单且优美的方程.如果从当前盘子的放置状态或者是当前苹果的放置状态来求解状态转移方程就不能写出来.这和题意中的相同盘子,相同苹果有很…

JCG学院开设了Java设计模式课程!

自从我们推出JCG学院以来&#xff0c;已经有一段时间了。JCG学院是一个基于付费内容的高级订阅网站&#xff0c;提供有关最新技术的课程&#xff0c;涵盖从RedSQL数据库&#xff08;如Redis和CouchDB&#xff09;到使用Android进行移动开发的最新知识。 当然&#xff0c;与Jav…

用友异常清理工具

此类工具网上很多&#xff0c;但&#xff0c;网上的病毒千千万万&#xff0c;还是自己开发使用较为放心。而且具体执行了什么也一清二楚&#xff0c;可以放心。 此工具适用大部份版本&#xff0c;从U821至U871&#xff0c;包括U6系列。 转载于:https://www.cnblogs.com/wuxi15/…