如何在Java中使用Lambdas操纵对象

93 阅读6分钟

如何在Java中使用Lambdas操纵对象

Java是一种面向对象的编程语言。Lambdas允许程序员使他们的代码更短、更有效、更有功能。

一个对象可以是物理的,也可以是想象的,它只是与我们一般看待事物的方式有关。

例如,一个钱包是一个对象,它有一个存储钱、赚钱、添加卡、获得卡的方法;这是物理的。

另一方面,一个账户也可以存储金钱和检查余额;但这是想象的。

例子2:一个水桶是一个物体,它有一个方法来存储固体、液体或气体。

现在,当你有一个集合了不同物品的钱包,而你想进入那个有红卡的钱包,里面有3万多美元的时候,情况就变得有趣了。

这时,lambdas就出现了。它们可以帮助人们在一个对象集合中进行迭代,避免许多错误。

前提条件

要继续学习,你应该对Java OOP(面向对象的编程)概念和lambdas有基本的了解。

学习目的

本教程将帮助你理解。

  • lambdas如何工作。
  • 如何使用lambdas对对象进行排序。
  • 如何计算一个对象的值。
  • 如何对一个对象的集合进行分组。
  • 如何检查一个唯一的对象。

lambdas的重要性

使用lambdas是编写代码的一种有效方式。一些批评者认为lambdas并不清晰,但从真正意义上讲,它们是高效的,并将错误降到最低。

让我们用我们的钱包对象作为一个案例研究。

你将根据颜色和金钱来创建不同的钱包。然后我们将使用这两个变量(颜色或金钱)来操作这些对象。

请注意,这种操作是很耗时的,可能会导致很高的时间复杂性。

开始工作

首先,我们要创建以下类或对象。

  1. 卡(AtM卡)
  2. 钱包
  3. 作为驱动类的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 接下来,我们创建了一个cardwallet ,然后是一个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 coloramount ,选择一个对象。

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功能接口对对象进行分组,该接口需要两个参数CardLong