如何在Java中使用Lambdas操纵对象
Java是一种面向对象的编程语言。Lambdas允许程序员使他们的代码更短、更有效、更有功能。
一个对象可以是物理的,也可以是想象的,它只是与我们一般看待事物的方式有关。
例如,一个钱包是一个对象,它有一个存储钱、赚钱、添加卡、获得卡的方法;这是物理的。
另一方面,一个账户也可以存储金钱和检查余额;但这是想象的。
例子2:一个水桶是一个物体,它有一个方法来存储固体、液体或气体。
现在,当你有一个集合了不同物品的钱包,而你想进入那个有红卡的钱包,里面有3万多美元的时候,情况就变得有趣了。
这时,lambdas就出现了。它们可以帮助人们在一个对象集合中进行迭代,避免许多错误。
前提条件
要继续学习,你应该对Java OOP(面向对象的编程)概念和lambdas有基本的了解。
学习目的
本教程将帮助你理解。
- lambdas如何工作。
- 如何使用lambdas对对象进行排序。
- 如何计算一个对象的值。
- 如何对一个对象的集合进行分组。
- 如何检查一个唯一的对象。
lambdas的重要性
使用lambdas是编写代码的一种有效方式。一些批评者认为lambdas并不清晰,但从真正意义上讲,它们是高效的,并将错误降到最低。
让我们用我们的钱包对象作为一个案例研究。
你将根据颜色和金钱来创建不同的钱包。然后我们将使用这两个变量(颜色或金钱)来操作这些对象。
请注意,这种操作是很耗时的,可能会导致很高的时间复杂性。
开始工作
首先,我们要创建以下类或对象。
- 卡(AtM卡)
- 钱包
- 作为驱动类的Collection_Wallet
创建一个文件夹并将其命名为Lambda_Collection 。它将存储我们的三个类(包)。
下面是Card, Wallet, 和Collection_Wallet类的代码。
卡片。
package Lambda_Collection;
public enum Card {
Red, Black, Green, Blue //card colors
}
钱包。
package Lambda_Collection;
import java.util.LinkedList;
import java.util.List;
public class Wallet {
private double money;
private Card card;//card is a variable of Card object and this phenomenon is called Composition.
int counter=0;
public Wallet(double money, Card card ) {
this.money = money;
addCards(card);
}
//creating methods that store money and Card
public void storeMoney(double money){
this.money+=money;
}
public double takeMoney(){
return money;
}
public void addCards(Card card){
this.card=card;
counter++;
}
public Card getCards(){
return card;
}
@Override
public String toString() {
return String.format("%s%.2f %s ",
"#",takeMoney(), getCards());
}
}
在上面的代码中,我们已经创建了一个文件夹或包来存储我们的代码。
object 接下来,我们创建了一个card ,wallet ,然后是一个Enum 的类,其中包含了各个类的颜色。
toString方法允许我们使该对象可见。
下面的代码显示了在我们使用lambdas之前,wallet 集合的样子。
package Lambda_Collection;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class Collection_Wallet {
public static void main(String[] args) {
Wallet[] walletsGroups={
new Wallet(4000,Card.Blue),
new Wallet(14000,Card.Black),
new Wallet(34000,Card.Red),
new Wallet(24000,Card.Red),
new Wallet(44000,Card.Green),
new Wallet(44000,Card.Black),
new Wallet(44000,Card.Green),
new Wallet(54000,Card.Black),
new Wallet(34000,Card.Blue),
new Wallet(74000,Card.Black),
new Wallet(64000,Card.Black),
};
// The above is a collection of wallet objects, after this, we then save it as a list
List<Wallet> list = Arrays.asList(walletsGroups);
System.out.println("Completes Display Of Wallets");
//this is use to display the collections using lambdas
list.stream().forEach(System.out::println);
}
}
list.stream() 方法创建一个Wallet流。换句话说,它可以帮助我们识别集合中的一个特定对象。
筛选钱包
为了访问特定的字段,我们使用filter 方法。这个函数接收一个谓词表达式并返回一个布尔值。
帮助使用lambdas操作集合的两个主要接口是Functions<T, R> 和Predicate<T> 。
Predicate 接收一个参数并返回一个boolean 值(真或假)。
然后,返回的值被用来检查一个特定的参数是否符合定义的条件。
Function 读取两个参数并返回所需的数据类型。Customer输入了一个参数,但没有返回任何东西。
最后,Supplier<T> 没有接受任何参数,并返回一个T的值。
我们使用Predicate 接口来检查管道是否满足某个条件。它与filter 函数一起使用,该函数与Predicate 方法相关。
在你的Collection_Wallet 类中添加以下代码。
例1
根据card color 和amount ,选择一个对象。
Predicate<Wallet> takeMoneyAndBlackCard=
e -> (e.takeMoney() >= 30000 && e.getCards().equals(Card.Black));
System.out.printf("%n Display of your sorted list: %n");
list.stream()
.filter(takeMoneyAndBlackCard)
.sorted(Comparator.comparing(Wallet::getCards))
.forEach(System.out::println);
Comparator 接口基于实例方法对两个钱包对象进行比较,如果第一个元素小于第二个元素,则返回一个负值。
当第一元素大于时,返回一个正值。当两个元素相同时,则返回零。forEach 函数然后终止整个管道。
输出。
Displaying the sorted list by Card:
'#44000.00 Black
#54000.00 Black
#74000.00 Black
#64000.00 Black'
例2
Predicate<Wallet> takeMoneyAndBlackCard=
e -> (e.takeMoney() >= 30000 && e.getCards().equals(Card.Black));
System.out.printf("%n Display of your sorted list: %n");
list.stream()
.filter(takeMoneyAndBlackCard)
.sorted(Comparator.comparing(Wallet::takeMoney))
.forEach(System.out::println);
输出。
根据资金数额显示排序后的列表。
$44000.00 Black
$54000.00 Black
$64000.00 Black
$74000.00 Black
如果我们想找到一个金额高于30,000美元的单个钱包怎么办?在这种情况下,我们使用findFirst() 中间的方法。
Predicate<Wallet> takeMoneyAndBlackCard=
e -> (e.takeMoney() >= 30000 );
System.out.printf("%n Display of your sorted list: %n");
System.out.println( list.stream()
.filter(takeMoneyAndBlackCard)
.findFirst())
.get();
输出。
$34000.00 Red
确保每次调用
Predicate interface,一定要使用不同的变量。
使用Function<T, R> 方法。
Function<Wallet, Double> byTakeMoney = Wallet::takeMoney;
Function<Wallet, Card> byGetCard = Wallet::getCards;
Comparator<Wallet> byMoneyThenByCard=Comparator.comparing(byTakeMoney).thenComparing(byGetCard);
System.out.println("Display by money then by card");
list.stream()
.sorted(byMoneyThenByCard)
.forEach(System.out::println);
输出。
$4000.00 Blue
$14000.00 Black
$24000.00 Red
$34000.00 Red
$34000.00 Blue
$44000.00 Black
$44000.00 Green
$44000.00 Green
$54000.00 Black
$64000.00 Black
$74000.00 Black
让我们看看如何使用lambdas根据集合中的值来反转元素。
System.out.println("Display by money then by card in reserve order)
list.stream()
.sorted(byMoneyThenByCard.reversed())
.forEach(System.out::println);`
输出。
按钱显示,然后按卡显示。
$74000.00 Black
$64000.00 Black
$54000.00 Black
$44000.00 Green
$44000.00 Green
$44000.00 Black
$34000.00 Blue
$34000.00 Red
$24000.00 Red
$14000.00 Black
$4000.00 Blue
分组
我们使用下面的代码将一个钱包映射到一张卡的唯一颜色。
System.out.println("Printing out distinctive amount in the wallet");
list.stream()
.map(Wallet::takeMoney)
.distinct()
.sorted()
.forEach(System.out::println);
System.out.println("Printing out distinctive card in the wallet");
list.stream()
.map(Wallet::getCards)
.distinct()
.sorted()
.forEach(System.out::println);
输出。
在钱包集合中打印出与众不同的金额。
4000.0
14000.0
24000.0
34000.0
44000.0
54000.0
64000.0
74000.0
打印出钱包集合中与众不同的卡片。
Red
Black
Green
Blue
我们可以使用lambdas根据对象的实例方法来分组。collect 参数指定了如何以一种有意义的方式总结数据。
map接收两个参数,指示JVM(Java虚拟机)如何对Card 对象进行分组。
Map<Card, Long> walletCountByCard =
list.stream()
.collect(Collectors.groupingBy(Wallet::getCards,Collectors.counting()));
walletCountByCard.forEach(
(getCards, count) -> System.out.printf(
"%s has %d wallet(s)%n", getCards, count));
}
输出。
Blue has 2 wallet(s)
Red has 2 wallet(s)
Green has 2 wallet(s)
Black has 5 wallet(s)
计算钱包中所有金额的总和。
System.out.printf(
"%nSum of Wallet' salaries (via sum method): %.2f%n",
list.stream()
.mapToDouble(Wallet::takeMoney)
.sum());
输出。
Sum of Wallet' money (via sum method): 434000.00
Average of Wallet' money (via average method): 39454.55
计算特定颜色卡片的总金额。
Predicate<Wallet> takeMoneyAndBlackCard1=
e -> (e.getCards().equals(Card.Black) );
System.out.printf(
"%nSum of Black Card wallet(via average method): %.2f%n",
list.stream()
.filter(takeMoneyAndBlackCard1)
.mapToDouble(Wallet::takeMoney)
.sum());
请注意,我使用了
Predicate接口,同时将其嵌入到filter方法中。
输出:计算一个特定颜色卡片的总金额。
Sum of Black Card wallet via average method: 250000.00
总结
在本教程中,我们学习了如何迭代一个对象集合,并使用功能接口(如Functions<T, R> ,和Predicate<T> )对其进行操作。
我们还使用map功能接口对对象进行分组,该接口需要两个参数Card 和Long 。