一、自定义函数式接口
函数式接口(Functional Interface):函数式接口是一种只包含一个抽象方法的 Java 接口。
函数式接口定义要点
- 必需是 Java 接口。
- 有且只有一个抽象方法(函数式方法),但不一定只有一个方法(可包含多个非抽象方法)
@FunctionalInterface
是可选的,但加上该标注编译器会帮你检查接口是否符合函数接口规范。就像加入@Override
标注会检查是否重载了函数一样。- 定义的函数式接口用于帮助实现 Lambda 函数。
示例
// 自定义函数接口
@FunctionalInterface
public interface ConsumerInterface<T> {
//自定义的抽象方法
void accept(T t);
//其他非抽象方法
default int method1(){
return 1;
}
default void method2(){
//代码逻辑
}
}
二、常见的函数式接口
概览
类型 | 说明 |
| 用于实现一个没有返回值的任务。通常用于多线程实现,线程执行后无返回值 |
| 用于定义对象的比较规则。通过定义不同的比较规则来对对象进行排序,而不需要修改对象本身。 |
| 用于实现一个具有返回值的任务。通常用于多线程实现,线程执行后有返回值。 |
| (将当前对象设为消费者)接受一个参数并且不返回结果的操作。 |
| 不接受参数但返回结果的操作。 |
| 接受一个参数并返回一个结果的操作。 |
| 一个接受参数并返回布尔值的操作,用于判断某个条件是否成立。 |
| 一个接受单一参数并返回相同类型的操作。 |
| 一个接受两个参数并返回一个相同类型结果的操作。 |
Runnable
用途:用于实现一个没有返回值的任务。通常用于多线程实现,线程执行后无返回值。
Runnable
接口应由其实例打算由线程执行的任何类实现。该类必须定义一个名为run
的无参数方法。
该接口旨在为希望在活动状态下执行代码的对象提供一个通用协议。例如,Runnable
就是由Thread
类实现的。处于活动状态仅仅意味着线程已经启动,尚未停止。
此外,Runnable
还提供了一种方法,使一个类在不子类Thread
的情况下也能处于活动状态。实现了Runnable
的类可以通过实例化一个线程实例并将自己作为目标传入,从而在不子类化线程的情况下运行。在大多数情况下,如果只打算重载run()
方法而不使用其他线程方法,则应使用Runnable
接口。这一点很重要,因为除非程序员打算修改或增强类的基本行为,否则不应子类化类。
函数方法:void run()
其他方法:无
源码:
package java.lang;
/**
* The {@code Runnable} interface should be implemented by any
* class whose instances are intended to be executed by a thread. The
* class must define a method of no arguments called {@code run}.
* <p>
* This interface is designed to provide a common protocol for objects that
* wish to execute code while they are active. For example,
* {@code Runnable} is implemented by class {@code Thread}.
* Being active simply means that a thread has been started and has not
* yet been stopped.
* <p>
* In addition, {@code Runnable} provides the means for a class to be
* active while not subclassing {@code Thread}. A class that implements
* {@code Runnable} can run without subclassing {@code Thread}
* by instantiating a {@code Thread} instance and passing itself in
* as the target. In most cases, the {@code Runnable} interface should
* be used if you are only planning to override the {@code run()}
* method and no other {@code Thread} methods.
* This is important because classes should not be subclassed
* unless the programmer intends on modifying or enhancing the fundamental
* behavior of the class.
*
* @author Arthur van Hoff
* @see java.lang.Thread
* @see java.util.concurrent.Callable
* @since 1.0
*/
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface {@code Runnable} is used
* to create a thread, starting the thread causes the object's
* {@code run} method to be called in that separately executing
* thread.
* <p>
* The general contract of the method {@code run} is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
示例:
可以使用 java.lang.Runnable
接口来进行函数式编程,代表一个没有返回值的任务。下面是一个示例,展示如何使用 Runnable
接口进行函数式编程:
public class Main {
public static void main(String[] args) {
Runnable greetTask = () -> {
String message = "Hello, world!";
System.out.println(message);
};
greetTask.run();
}
}
在这个示例中,我们创建了一个 Runnable
类型的变量 greetTask
,它代表一个没有返回值的任务。在这个任务中,我们定义了一个简单的函数式块,用于打印出 "Hello, world!"。然后我们通过调用 run()
方法来执行这个任务。
Runnable
接口通常在多线程编程中使用,用于描述需要在一个线程中执行的任务。您可以在函数式编程中使用它,将需要执行的代码块传递给 Runnable
,然后调用 run()
方法来执行代码块中的逻辑。
请注意,与 Callable
接口一样,Runnable
接口在 Java 中用于表示一种任务,但是它没有返回值。
Comparator
用途:用于定义对象的比较规则。通过定义不同的比较规则来对对象进行排序,而不需要修改对象本身。
比较函数,用于对某些对象集合进行总排序。比较器可以传递给排序方法(如Collections.sort
或Arrays.sort
),以便精确控制排序顺序。比较器还可用于控制某些数据结构(如排序集或排序映射)的排序,或为没有自然排序的对象集合提供排序。
对于S
中的每个e1
和e2
,当且仅当c.compare(e1, e2)==0
的布尔值与e1.equals(e2)
的布尔值相同时,比较器c
对元素集合S
所施加的排序被认为与 equals
一致。
在使用能施加与 equals
不一致的排序的比较器对排序集(或排序图)进行排序时,应小心谨慎。假设一个具有显式比较器c的排序集(或排序映射表)的元素(或键)来自一个集合S
,如果c
对S
施加的排序与等式不一致,那么排序集(或排序映射表)就会表现得 "奇怪"。特别是,排序集合(或排序映射)将违反集合(或映射)的一般契约,该契约是根据等式定义的。
例如,假设在一个带有比较器c 的空TreeSet
中添加了两个元素a
和b
,且(a.equals(b) && c.compare(a, b) != 0)
。第二个添加操作将返回 true
(树集的大小将增加),因为从树集的角度来看,a
和b
并不等价,尽管这与Set.add
方法的规范相悖。
注意:比较器最好也实现java.io.Serializable
,因为它们可能会被用作可序列化数据结构(如TreeSet
、TreeMap
)中的排序方法。为了使数据结构成功序列化,比较器(如果提供)必须实现Serializable
。
对于数学爱好者来说,定义给定比较器c
对给定对象集S的强加排序 关系是:
{(x, y) such that c.compare(x, y) <= 0}
这个总排序的商为:
{(x, y) such that c.compare(x, y) == 0}
从 比较的契约中可以立即看出,商是 S
上的等价关系,而施加的排序是 S
上的总排序。当我们说 c
强加给 S
的排序与 equals
一致时,我们的意思是该排序的商是由对象的equals(Object)
方法定义的等价关系:
{(x, y) such that x.equals(y)}
换句话说,当强加的排序与 equals
一致时,由 equals
方法的等价关系定义的等价类和由 比较方法的商定义的等价类是相同的。
与 Comparable
不同,比较器可以选择性地允许对空参数进行比较,同时保持对等价关系的要求。
该接口是 Java
集合框架的成员。
函数方法:int compare(T o1, T o2)
其他方法:
方法名 | 用途 |
| 比较输入对象是否与当前比较器 |
| 返回一个与当前比较器相反的比较器 |
| 返回带有当前比较器和输入比较器的比较器。 如果此 |
| 返回一个比较器,它强加自然顺序的反转。 |
| 返回一个比较器, 它按自然顺序比较 |
| 返回一个空值友好的比较器,该比较器认为空值小于非空值 |
| 返回一个空值友好的比较器,该比较器认为空值大于非空值 |
| 返回一个按输入的 P.S. 简单来说就是当我们的排序对象有多个属性,我们想按其中的某一项排序时,可以先创建一个 E.g. 当前存在一个包含数个
|
源码:
package java.util;
import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;
/**
* A comparison function, which imposes a <i>total ordering</i> on
* some collection of objects. Comparators can be passed to a sort
* method (such as {@link Collections#sort(List,Comparator)
* Collections.sort} or {@link Arrays#sort(Object[],Comparator)
* Arrays.sort}) to allow precise control over the sort order.
* Comparators can also be used to control the order of certain data
* structures (such as {@linkplain SortedSet sorted sets} or
* {@linkplain SortedMap sorted maps}), or to provide an ordering for
* collections of objects that don't have a {@linkplain Comparable
* natural ordering}.<p>
*
* The ordering imposed by a comparator {@code c} on a set of elements
* {@code S} is said to be <i>consistent with equals</i> if and only if
* {@code c.compare(e1, e2)==0} has the same boolean value as
* {@code e1.equals(e2)} for every {@code e1} and {@code e2} in
* {@code S}.<p>
*
* Caution should be exercised when using a comparator capable of imposing an
* ordering inconsistent with equals to order a sorted set (or sorted map).
* Suppose a sorted set (or sorted map) with an explicit comparator {@code c}
* is used with elements (or keys) drawn from a set {@code S}. If the
* ordering imposed by {@code c} on {@code S} is inconsistent with equals,
* the sorted set (or sorted map) will behave "strangely." In particular the
* sorted set (or sorted map) will violate the general contract for set (or
* map), which is defined in terms of {@code equals}.<p>
*
* For example, suppose one adds two elements {@code a} and {@code b} such that
* {@code (a.equals(b) && c.compare(a, b) != 0)}
* to an empty {@code TreeSet} with comparator {@code c}.
* The second {@code add} operation will return
* true (and the size of the tree set will increase) because {@code a} and
* {@code b} are not equivalent from the tree set's perspective, even though
* this is contrary to the specification of the
* {@link Set#add Set.add} method.<p>
*
* Note: It is generally a good idea for comparators to also implement
* {@code java.io.Serializable}, as they may be used as ordering methods in
* serializable data structures (like {@link TreeSet}, {@link TreeMap}). In
* order for the data structure to serialize successfully, the comparator (if
* provided) must implement {@code Serializable}.<p>
*
* For the mathematically inclined, the <i>relation</i> that defines the
* <i>imposed ordering</i> that a given comparator {@code c} imposes on a
* given set of objects {@code S} is:<pre>
* {(x, y) such that c.compare(x, y) <= 0}.
* </pre> The <i>quotient</i> for this total order is:<pre>
* {(x, y) such that c.compare(x, y) == 0}.
* </pre>
*
* It follows immediately from the contract for {@code compare} that the
* quotient is an <i>equivalence relation</i> on {@code S}, and that the
* imposed ordering is a <i>total order</i> on {@code S}. When we say that
* the ordering imposed by {@code c} on {@code S} is <i>consistent with
* equals</i>, we mean that the quotient for the ordering is the equivalence
* relation defined by the objects' {@link Object#equals(Object)
* equals(Object)} method(s):<pre>
* {(x, y) such that x.equals(y)}. </pre>
*
* In other words, when the imposed ordering is consistent with
* equals, the equivalence classes defined by the equivalence relation
* of the {@code equals} method and the equivalence classes defined by
* the quotient of the {@code compare} method are the same.
* <p>Unlike {@code Comparable}, a comparator may optionally permit
* comparison of null arguments, while maintaining the requirements for
* an equivalence relation.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <T> the type of objects that may be compared by this comparator
*
* @author Josh Bloch
* @author Neal Gafter
* @see Comparable
* @see java.io.Serializable
* @since 1.2
*/
@FunctionalInterface
public interface Comparator<T> {
/**
* Compares its two arguments for order. Returns a negative integer,
* zero, or a positive integer as the first argument is less than, equal
* to, or greater than the second.<p>
*
* The implementor must ensure that {@link Integer#signum
* signum}{@code (compare(x, y)) == -signum(compare(y, x))} for
* all {@code x} and {@code y}. (This implies that {@code
* compare(x, y)} must throw an exception if and only if {@code
* compare(y, x)} throws an exception.)<p>
*
* The implementor must also ensure that the relation is transitive:
* {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
* {@code compare(x, z)>0}.<p>
*
* Finally, the implementor must ensure that {@code compare(x,
* y)==0} implies that {@code signum(compare(x,
* z))==signum(compare(y, z))} for all {@code z}.
*
* @apiNote
* It is generally the case, but <i>not</i> strictly required that
* {@code (compare(x, y)==0) == (x.equals(y))}. Generally speaking,
* any comparator that violates this condition should clearly indicate
* this fact. The recommended language is "Note: this comparator
* imposes orderings that are inconsistent with equals."
*
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*/
int compare(T o1, T o2);
/**
* Indicates whether some other object is "equal to"
* this comparator. This method must obey the general contract of
* {@link Object#equals(Object)}. Additionally, this method can
* return {@code true} <i>only</i> if the specified object is also
* a comparator and it imposes the same ordering as this
* comparator. Thus, {@code comp1.equals(comp2)} implies that
* {@link Integer#signum signum}{@code (comp1.compare(o1,
* o2))==signum(comp2.compare(o1, o2))} for every object reference
* {@code o1} and {@code o2}.<p>
*
* Note that it is <i>always</i> safe <i>not</i> to override
* {@code Object.equals(Object)}. However, overriding this method may,
* in some cases, improve performance by allowing programs to determine
* that two distinct comparators impose the same order.
*
* @param obj the reference object with which to compare.
* @return {@code true} only if the specified object is also
* a comparator and it imposes the same ordering as this
* comparator.
* @see Object#equals(Object)
* @see Object#hashCode()
*/
boolean equals(Object obj);
/**
* Returns a comparator that imposes the reverse ordering of this
* comparator.
*
* @return a comparator that imposes the reverse ordering of this
* comparator.
* @since 1.8
*/
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
/**
* Returns a lexicographic-order comparator with another comparator.
* If this {@code Comparator} considers two elements equal, i.e.
* {@code compare(a, b) == 0}, {@code other} is used to determine the order.
*
* <p>The returned comparator is serializable if the specified comparator
* is also serializable.
*
* @apiNote
* For example, to sort a collection of {@code String} based on the length
* and then case-insensitive natural ordering, the comparator can be
* composed using following code,
*
* <pre>{@code
* Comparator<String> cmp = Comparator.comparingInt(String::length)
* .thenComparing(String.CASE_INSENSITIVE_ORDER);
* }</pre>
*
* @param other the other comparator to be used when this comparator
* compares two objects that are equal.
* @return a lexicographic-order comparator composed of this and then the
* other comparator
* @throws NullPointerException if the argument is null.
* @since 1.8
*/
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a key to be compared with the given {@code Comparator}.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor, cmp))}.
*
* @param <U> the type of the sort key
* @param keyExtractor the function used to extract the sort key
* @param keyComparator the {@code Comparator} used to compare the sort key
* @return a lexicographic-order comparator composed of this comparator
* and then comparing on the key extracted by the keyExtractor function
* @throws NullPointerException if either argument is null.
* @see #comparing(Function, Comparator)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code Comparable} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
*
* @param <U> the type of the {@link Comparable} sort key
* @param keyExtractor the function used to extract the {@link
* Comparable} sort key
* @return a lexicographic-order comparator composed of this and then the
* {@link Comparable} sort key.
* @throws NullPointerException if the argument is null.
* @see #comparing(Function)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts an {@code int} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparingInt(keyExtractor))}.
*
* @param keyExtractor the function used to extract the integer sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code int} sort key
* @throws NullPointerException if the argument is null.
* @see #comparingInt(ToIntFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code long} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparingLong(keyExtractor))}.
*
* @param keyExtractor the function used to extract the long sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code long} sort key
* @throws NullPointerException if the argument is null.
* @see #comparingLong(ToLongFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code double} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparingDouble(keyExtractor))}.
*
* @param keyExtractor the function used to extract the double sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code double} sort key
* @throws NullPointerException if the argument is null.
* @see #comparingDouble(ToDoubleFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
/**
* Returns a comparator that imposes the reverse of the <em>natural
* ordering</em>.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing {@code null}.
*
* @param <T> the {@link Comparable} type of element to be compared
* @return a comparator that imposes the reverse of the <i>natural
* ordering</i> on {@code Comparable} objects.
* @see Comparable
* @since 1.8
*/
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
/**
* Returns a comparator that compares {@link Comparable} objects in natural
* order.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing {@code null}.
*
* @param <T> the {@link Comparable} type of element to be compared
* @return a comparator that imposes the <i>natural ordering</i> on {@code
* Comparable} objects.
* @see Comparable
* @since 1.8
*/
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
/**
* Returns a null-friendly comparator that considers {@code null} to be
* less than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be less than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
/**
* Returns a null-friendly comparator that considers {@code null} to be
* greater than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be greater than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}
/**
* Accepts a function that extracts a sort key from a type {@code T}, and
* returns a {@code Comparator<T>} that compares by that sort key using
* the specified {@link Comparator}.
*
* <p>The returned comparator is serializable if the specified function
* and comparator are both serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name ignoring case differences,
*
* <pre>{@code
* Comparator<Person> cmp = Comparator.comparing(
* Person::getLastName,
* String.CASE_INSENSITIVE_ORDER);
* }</pre>
*
* @param <T> the type of element to be compared
* @param <U> the type of the sort key
* @param keyExtractor the function used to extract the sort key
* @param keyComparator the {@code Comparator} used to compare the sort key
* @return a comparator that compares by an extracted key using the
* specified {@code Comparator}
* @throws NullPointerException if either argument is null
* @since 1.8
*/
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
/**
* Accepts a function that extracts a {@link java.lang.Comparable
* Comparable} sort key from a type {@code T}, and returns a {@code
* Comparator<T>} that compares by that sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name,
*
* <pre>{@code
* Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
* }</pre>
*
* @param <T> the type of element to be compared
* @param <U> the type of the {@code Comparable} sort key
* @param keyExtractor the function used to extract the {@link
* Comparable} sort key
* @return a comparator that compares by an extracted key
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
/**
* Accepts a function that extracts an {@code int} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the integer sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
/**
* Accepts a function that extracts a {@code long} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function is
* also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the long sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}
/**
* Accepts a function that extracts a {@code double} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the double sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}
示例:
可以使用 java.util.Comparator
接口来进行函数式编程,用于定义对象的比较规则。下面是一个示例,展示如何使用 Comparator
接口进行函数式编程:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 28));
people.add(new Person("Bob", 22));
people.add(new Person("Charlie", 35));
// Using Comparator to sort by age
Comparator<Person> ageComparator = Comparator.comparingInt(Person::getAge);
people.sort(ageComparator);
// Printing sorted list
for (Person person : people) {
System.out.println(person.getName() + " - " + person.getAge());
}
}
}
在这个示例中,我们创建了一个 Person
类来表示人员,具有姓名和年龄属性。然后,我们使用 Comparator.comparingInt()
静态方法创建了一个 Comparator
对象,以 Person
对象的年龄进行比较。接下来,我们使用 people.sort()
方法来根据年龄对人员列表进行排序。
Comparator
接口允许您通过定义不同的比较规则来对对象进行排序,而不需要修改对象本身。这使得您可以更灵活地实现不同的排序需求,同时也符合函数式编程的风格。
Callable
用途:用于实现一个具有返回值的任务。通常用于多线程实现,线程执行后有返回值。
返回结果并可能抛出异常的任务。实现者定义一个不带参数的方法,称为call
。
Callable
接口与Runnable
类似,都是为实例可能被另一个线程执行的类设计的。不过,Runnable
不会返回结果,也不会抛出经过检查的异常。
Executors
类包含一些实用方法,用于将其他常见形式转换为Callable
类。
函数方法:V call()
其他方法:无
源码:
package java.util.concurrent;
/**
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
* {@code call}.
*
* <p>The {@code Callable} interface is similar to {@link
* java.lang.Runnable}, in that both are designed for classes whose
* instances are potentially executed by another thread. A
* {@code Runnable}, however, does not return a result and cannot
* throw a checked exception.
*
* <p>The {@link Executors} class contains utility methods to
* convert from other common forms to {@code Callable} classes.
*
* @see Executor
* @since 1.5
* @author Doug Lea
* @param <V> the result type of method {@code call}
*/
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
示例:
可以使用java.util.concurrent.Callable
接口进行函数式编程。Callable
接口代表具有返回值的任务,类似于带有返回类型的函数。以下是一个简单的示例,展示如何使用Callable
进行函数式编程:
import java.util.concurrent.Callable;
public class Main {
public static void main(String[] args) {
Callable<Integer> addFunction = () -> {
int a = 5;
int b = 3;
return a + b;
};
try {
Integer result = addFunction.call();
System.out.println("Result: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在这个示例中,我们创建了一个Callable<Integer>
类型的变量addFunction
,它代表了一个可以执行的带有返回值的任务。在call()
方法中,我们定义了一个简单的函数,将两个整数相加并返回结果。在main
方法中,我们调用了addFunction.call()
来执行这个任务,并获取返回的结果。
请注意,Callable
接口在Java中用于表示带有返回值的任务,而如果您需要执行没有返回值的任务,可以使用java.lang.Runnable
接口。
Consumer
用途:(将当前对象设为消费者)接受一个参数并且不返回结果的操作。
代表接受单一输入参数且不返回结果的操作。与大多数其他功能接口不同,消费者接口(Consumer
)需要通过副作用(side-effects
)进行操作。
这是一个功能接口,其功能方法是accept(Object)
。
函数方法:void accept(T t)
其他方法:
方法名 | 用途 |
| 返回一个先执行当前对象再执行输入对象的 |
源码:
package java.util.function;
import java.util.Objects;
/**
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
示例:
可以使用 java.util.function.Consumer
接口来进行函数式编程,用于表示接受一个参数并且不返回结果的操作。下面是一个示例,展示如何使用 Consumer
接口进行函数式编程:
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 28));
people.add(new Person("Bob", 22));
people.add(new Person("Charlie", 35));
// Using Consumer to print the person's information
Consumer<Person> printInfo = person -> {
System.out.println("Name: " + person.getName() + ", Age: " + person.getAge());
};
// Applying the Consumer to each person in the list
for (Person person : people) {
printInfo.accept(person);
}
}
}
在这个示例中,我们创建了一个 Person
类来表示人员,具有姓名和年龄属性。然后,我们使用 Consumer
接口创建了一个表示打印人员信息的函数式块 printInfo
。接下来,我们通过调用 printInfo.accept(person)
来应用这个函数式块到每个人员对象,以打印其信息。
Consumer
接口允许您定义一个操作,然后将这个操作应用到输入参数上。这种方式在处理集合、流等情况下非常有用,可以将操作与数据分离,使代码更加模块化和可维护。
Supplier
用途:不接受参数但返回结果的操作。
代表结果供应商。
不要求每次调用时都返回新的或独特的结果。
这是一个功能接口,其功能方法是get()
。
函数方法:T get()
其他方法:无
源码:
package java.util.function;
/**
* Represents a supplier of results.
*
* <p>There is no requirement that a new or distinct result be returned each
* time the supplier is invoked.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #get()}.
*
* @param <T> the type of results supplied by this supplier
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
示例:
可以使用 java.util.function.Supplier
接口来进行函数式编程,用于表示一个不接受参数但返回结果的操作。下面是一个示例,展示如何使用 Supplier
接口进行函数式编程:
import java.util.function.Supplier;
class RandomNumberGenerator {
public int generate() {
return (int) (Math.random() * 100);
}
}
public class Main {
public static void main(String[] args) {
// Using Supplier to create an instance of RandomNumberGenerator
Supplier<RandomNumberGenerator> rngSupplier = RandomNumberGenerator::new;
// Creating instances using the Supplier
RandomNumberGenerator rng1 = rngSupplier.get();
RandomNumberGenerator rng2 = rngSupplier.get();
// Generating random numbers using the instances
int randomNumber1 = rng1.generate();
int randomNumber2 = rng2.generate();
System.out.println("Random Number 1: " + randomNumber1);
System.out.println("Random Number 2: " + randomNumber2);
}
}
在这个示例中,我们创建了一个 RandomNumberGenerator
类来生成随机数。然后,我们使用 Supplier
接口创建了一个表示生成 RandomNumberGenerator
实例的函数式块 rngSupplier
。通过调用 rngSupplier.get()
,我们可以获取不同的随机数生成器实例。
Supplier
接口适用于需要延迟创建对象或产生值的情况,特别是在使用工厂方法或需要惰性计算的场景中。它允许您将对象创建的逻辑与对象使用的逻辑分开,从而提高代码的可维护性和可读性。
Function
用途:接受一个参数并返回一个结果的操作。
代表接受一个参数并产生一个结果的函数。
这是一个功能接口,其功能方法是apply(Object)
。
函数方法:R apply(T t)
其他方法:
方法名 | 用途 |
| 返回一个先执行输入公式再执行当前公式的公式 |
| 返回一个先执行当前公式再执行输入公式的公式 |
| 返回一个固定返回当前公式的输入的公式 |
源码:
package java.util.function;
import java.util.Objects;
/**
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
/**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* Returns a composed function that first applies this function to
* its input, and then applies the {@code after} function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*
* @see #compose(Function)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* Returns a function that always returns its input argument.
*
* @param <T> the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}
示例:
可以使用 java.util.function.Function
接口来进行函数式编程,用于表示接受一个参数并返回一个结果的操作。下面是一个示例,展示如何使用 Function
接口进行函数式编程:
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
// Using Function to convert String to Integer
Function<String, Integer> stringToInt = Integer::parseInt;
// Applying the function
Integer intValue = stringToInt.apply("42");
System.out.println("Integer Value: " + intValue);
// Using Function to concatenate two strings
Function<String, String> addPrefix = prefix -> "Prefix_" + prefix;
// Applying the function
String result = addPrefix.apply("Value");
System.out.println("Result: " + result);
}
}
在这个示例中,我们首先创建了一个 Function
类型的变量 stringToInt
,它表示将字符串转换为整数的操作。然后,我们通过调用 apply()
方法将字符串 "42"
转换为整数值。
接下来,我们创建了另一个 Function
类型的变量 addPrefix
,它表示将给定的字符串添加前缀的操作。我们通过调用 apply()
方法将字符串 "Value"
转换为带有前缀的新字符串。
Function
接口在函数式编程中非常有用,因为它允许您将不同的操作封装成函数,并且可以轻松地进行组合、映射等操作。这有助于使代码更加模块化和可维护。
Predicate
用途:一个接受参数并返回布尔值的操作,用于判断某个条件是否成立。
代表一个参数的谓词(布尔值函数)。
这是一个功能接口,其功能方法是test(Object)
。
函数方法:boolean test(T t)
其他方法:
方法名 | 用途 |
| 返回当前 |
| 返回当前 |
| 返回当前 |
| 返回一个判断当前输入是否与当前实例相等的 |
| 与 |
源码:
package java.util.function;
import java.util.Objects;
/**
* Represents a predicate (boolean-valued function) of one argument.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #test(Object)}.
*
* @param <T> the type of the input to the predicate
*
* @since 1.8
*/
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
/**
* Returns a composed predicate that represents a short-circuiting logical
* AND of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code false}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ANDed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* AND of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* Returns a predicate that represents the logical negation of this
* predicate.
*
* @return a predicate that represents the logical negation of this
* predicate
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
* Returns a composed predicate that represents a short-circuiting logical
* OR of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code true}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ORed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* OR of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
/**
* Returns a predicate that is the negation of the supplied predicate.
* This is accomplished by returning result of the calling
* {@code target.negate()}.
*
* @param <T> the type of arguments to the specified predicate
* @param target predicate to negate
*
* @return a predicate that negates the results of the supplied
* predicate
*
* @throws NullPointerException if target is null
*
* @since 11
*/
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}
示例:
可以使用 java.util.function.Predicate
接口来进行函数式编程,用于表示一个接受参数并返回布尔值的操作,用于判断某个条件是否成立。下面是一个示例,展示如何使用 Predicate
接口进行函数式编程:
import java.util.function.Predicate;
public class Main {
public static void main(String[] args) {
// Using Predicate to check if a number is even
Predicate<Integer> isEven = number -> number % 2 == 0;
// Applying the predicate
int num1 = 10;
System.out.println(num1 + " is even: " + isEven.test(num1));
int num2 = 15;
System.out.println(num2 + " is even: " + isEven.test(num2));
// Using Predicate to check if a string is empty
Predicate<String> isEmptyString = String::isEmpty;
// Applying the predicate
String str1 = "";
System.out.println("Is str1 empty: " + isEmptyString.test(str1));
String str2 = "Hello";
System.out.println("Is str2 empty: " + isEmptyString.test(str2));
}
}
在这个示例中,我们首先创建了一个 Predicate
类型的变量 isEven
,它表示检查一个数字是否为偶数的操作。然后,我们通过调用 test()
方法来应用这个操作,判断给定的数字是否为偶数。
接下来,我们创建了另一个 Predicate
类型的变量 isEmptyString
,它表示检查一个字符串是否为空的操作。我们同样通过调用 test()
方法来应用这个操作,判断给定的字符串是否为空。
Predicate
接口在函数式编程中通常用于过滤、判断和筛选的场景,它允许您将判断逻辑封装成一个函数,从而可以轻松地应用到不同的数据上。这有助于提高代码的可维护性和可读性。
UnaryOperator
用途:一个接受单一参数并返回相同类型的操作。
表示对单个操作数进行操作,产生与其操作数类型相同的结果。这是Function
的特化,用于操作数和结果类型相同的情况。
这是一个函数接口,其函数方法是apply(Object)
。
函数方法:R apply(T t)
其他方法:
方法名 | 用途 |
| 返回输入参数的一元运算符。 |
源码:
package java.util.function;
/**
* Represents an operation on a single operand that produces a result of the
* same type as its operand. This is a specialization of {@code Function} for
* the case where the operand and result are of the same type.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the operand and result of the operator
*
* @see Function
* @since 1.8
*/
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Returns a unary operator that always returns its input argument.
*
* @param <T> the type of the input and output of the operator
* @return a unary operator that always returns its input argument
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
示例:
可以使用 java.util.function.UnaryOperator
接口来进行函数式编程,用于表示一个接受单一参数并返回相同类型的操作。换句话说,UnaryOperator
是一种特殊的 Function
,输入和输出类型相同。下面是一个示例,展示如何使用 UnaryOperator
接口进行函数式编程:
import java.util.function.UnaryOperator;
public class Main {
public static void main(String[] args) {
// Using UnaryOperator to double a number
UnaryOperator<Integer> doubleNumber = number -> number * 2;
// Applying the unary operator
int num = 5;
int doubledNum = doubleNumber.apply(num);
System.out.println("Double of " + num + " is: " + doubledNum);
// Using UnaryOperator to add a prefix to a string
UnaryOperator<String> addPrefix = prefix -> "Prefix_" + prefix;
// Applying the unary operator
String input = "Value";
String result = addPrefix.apply(input);
System.out.println("Result: " + result);
}
}
在这个示例中,我们首先创建了一个 UnaryOperator
类型的变量 doubleNumber
,它表示将一个数字加倍的操作。我们通过调用 apply()
方法将数字 5
加倍。
接下来,我们创建了另一个 UnaryOperator
类型的变量 addPrefix
,它表示将一个前缀添加到字符串的操作。通过调用 apply()
方法将前缀添加到输入字符串上。
UnaryOperator
接口允许您在函数式编程中定义一个接受单一参数并返回相同类型的操作。这有助于将逻辑封装成可重用的函数,提高代码的可维护性和可读性。
BinaryOperator
用途:一个接受两个参数并返回一个相同类型结果的操作。
表示对两个相同类型的操作数进行运算,产生与操作数相同类型的结果。这是BiFunction
的特化,用于操作数和结果类型相同的情况。
这是一个函数接口,其函数方法是apply(Object,Object)
。
函数方法:R apply(T t, U u)
其他方法:
方法名 | 用途 |
| 返回一个组合函数,该函数首先对输入应用此函数,然后对结果应用后函数。如果对其中任一函数进行评估时出现异常,则会将异常转发给组合函数的调用者。 |
| 返回二进制操作符,该操作符根据指定的比较器返回两个元素中的较小值。 |
| 返回二进制操作符,该操作符根据指定的比较器返回两个元素中较大的一个。 |
源码:
package java.util.function;
import java.util.Objects;
import java.util.Comparator;
/**
* Represents an operation upon two operands of the same type, producing a result
* of the same type as the operands. This is a specialization of
* {@link BiFunction} for the case where the operands and the result are all of
* the same type.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object, Object)}.
*
* @param <T> the type of the operands and result of the operator
*
* @see BiFunction
* @see UnaryOperator
* @since 1.8
*/
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
/**
* Returns a {@link BinaryOperator} which returns the lesser of two elements
* according to the specified {@code Comparator}.
*
* @param <T> the type of the input arguments of the comparator
* @param comparator a {@code Comparator} for comparing the two values
* @return a {@code BinaryOperator} which returns the lesser of its operands,
* according to the supplied {@code Comparator}
* @throws NullPointerException if the argument is null
*/
public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
}
/**
* Returns a {@link BinaryOperator} which returns the greater of two elements
* according to the specified {@code Comparator}.
*
* @param <T> the type of the input arguments of the comparator
* @param comparator a {@code Comparator} for comparing the two values
* @return a {@code BinaryOperator} which returns the greater of its operands,
* according to the supplied {@code Comparator}
* @throws NullPointerException if the argument is null
*/
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
}
示例:
可以使用 java.util.function.BinaryOperator
接口来进行函数式编程,用于表示一个接受两个参数并返回一个相同类型结果的操作。换句话说,BinaryOperator
是一种特殊的 BiFunction
,输入和输出类型相同。下面是一个示例,展示如何使用 BinaryOperator
接口进行函数式编程:
import java.util.function.BinaryOperator;
public class Main {
public static void main(String[] args) {
// Using BinaryOperator to add two numbers
BinaryOperator<Integer> addNumbers = (a, b) -> a + b;
// Applying the binary operator
int num1 = 5;
int num2 = 8;
int sum = addNumbers.apply(num1, num2);
System.out.println("Sum of " + num1 + " and " + num2 + " is: " + sum);
// Using BinaryOperator to concatenate two strings
BinaryOperator<String> concatenateStrings = (str1, str2) -> str1 + str2;
// Applying the binary operator
String str1 = "Hello, ";
String str2 = "world!";
String result = concatenateStrings.apply(str1, str2);
System.out.println("Concatenated String: " + result);
}
}
在这个示例中,我们首先创建了一个 BinaryOperator
类型的变量 addNumbers
,它表示将两个数字相加的操作。我们通过调用 apply()
方法来应用这个操作,计算两个数字的和。
接下来,我们创建了另一个 BinaryOperator
类型的变量 concatenateStrings
,它表示将两个字符串连接起来的操作。通过调用 apply()
方法将两个字符串连接在一起。
BinaryOperator
接口允许您在函数式编程中定义一个接受两个参数并返回一个相同类型结果的操作。这有助于将逻辑封装成可重用的函数,提高代码的可维护性和可读性。