How do you write in Scala that was written in Java? (List → Map)

It's a functional and object-oriented Scala, but I don't think it's a problem to use it if it's a code that says "just move" [^ 1]. If you are too particular about writing functionally and give a feeling of intimidation to those who see the code, I think that even if you try to broaden the base of developers, it will often not work. That said, writing Java-like in Scala has some benefits, but I think it's better if you can avoid using vars and mutables.

Personally, I'm trying to apply a pattern of writing a Java implementation in Scala, but I thought it would be useful for someone, so I'll write it every time I think of it. I thought. Please go out with me if you like.

1. Pattern from List [element] to Map [key, element]

For example, I often use master data in a Map with an id value as a key like a cache.

For Java

element(client)


public class Customer {
  /**Customer ID. */
  public Long id;
  /**Customer name. */
  public String name;
  /**age. */
  public Integer age;
}

Target List


//Originally, the customerList is a haze to get from DB etc.
List<Customer> customerList = new ArrayList<Customer>(){{
    add(new Customer(){{
      this.id = 5L;this.name = "Kataoka";this.age = 39;
    }});
    add(new Customer(){{
      this.id = 3L;this.name = "Aoyama";this.age = 60;
    }});
    add(new Customer(){{
      this.id = 1L;this.name = "Fujishima";this.age = 23;
    }});
}};

List → Map conversion process


Map<Long, Customer> customerMap = new HashMap<>();
for(Customer customer : customerList) {
  customerMap.put(customer.id, customer);
}

This will create a customerMap where key is the customer ID and value is the Customer instance.

For Scala

element(client)


/**
  *client.
  * @param id customer ID
  * @param name customer name
  * @param age age
  */
case class Customer(id:Long, name:String, age:Int)

Target List


//Originally, the customerList is a haze to get from DB etc.
val customerList = Seq(
  Customer(id=5L, name="Kataoka", age=39),
  Customer(id=3L, name="Aoyama", age=60),
  Customer(id=1L, name="Fujishima", age=23)
)

List → Map conversion process


val customerMap = (customerList map (t => t.id -> t)).toMap

Seq [(Long, Customer)] [^ 2] is created by map operation from Seq [Customer], Furthermore, it is an image that is converted to Map [Long, Customer] by toMap. The generated Map is an immutable Map, so don't worry about it changing.

Of course, it is possible to write like Java by using a mutable Map, but I think it is easier to understand that this is generating a Map from a List. Since it is not necessary to describe the process of creating an empty Map instance and the process of adding an element to the Map, it is thought that coding mistakes can be reduced [^ 3].

2. Pattern from List [element] to Map [key, List [element]]

For example, based on the billing statement list linked to multiple billing IDs acquired by one SQL, key: Billing ID value: Billing details list associated with billing ID It looks like this when generating a Map of.

For Java

element(billing statement)


/**
 *billing statement.
 */
public class BillingStatement {
  /**Billing line ID(PK). */
  public Long id;
  /**Billing ID(FK). */
  public Long billingId;
  /**Product name. */
  public String itemName;

  //I think there are quantities and unit prices, but they are omitted.
}

Target List


//Originally, billingStatementList is a haze to get from DB etc.
List<BillingStatement> billingStatementList = new ArrayList<BillingStatement>(){{
    add(new BillingStatement(){{
      this.id = 1L;this.billingId = 1L;
      this.itemName = "Billing 1 Product 1";
    }});
    add(new BillingStatement(){{
      this.id = 2L;this.billingId = 1L;
      this.itemName = "Billing 1 Product 2";
    }});
    add(new BillingStatement(){{
      this.id = 3L;this.billingId = 2L;
      this.itemName = "Billing 2 Product 1";
    }});
    add(new BillingStatement(){{
      this.id = 4L;this.billingId = 3L;
      this.itemName = "Billing 3 Product 1";
    }});
    add(new BillingStatement(){{
      this.id = 5L;this.billingId = 3L;
      this.itemName = "Billing 3 Product 2";
    }});
    add(new BillingStatement(){{
      this.id = 6L;this.billingId = 3L;
      this.itemName = "Billing 3 Product 3";
    }});
}};

List → Map conversion process


Map<Long, List<BillingStatement>> billingStatementsMap = new HashMap<>();
for(BillingStatement billingStatement : billingStatementList) {
  List<BillingStatement> billingStatements = billingStatementsMap.get(billingStatement.billingId);
  if(billingStatements == null) {
    billingStatements = new ArrayList<>();
    billingStatementsMap.put(billingStatement.billingId, billingStatements);
  }

  billingStatements.add(billingStatement);
}

This will create a Map of the billing details list with key associated with the billing ID and value associated with the billing ID. Processing when the List associated with the billing ID does not exist ... Do you feel like you may inadvertently incorporate a bug?

For Scala

element(billing statement)


/**
  *billing statement.
  *I think there are quantities and unit prices, but they are omitted.
  * @param id Billing line ID(PK)
  * @param billingId Billing ID(FK)
  * @param itemName Product name
  */
case class BillingStatement(id:Long, billingId:Long, itemName:String)

Target List


//Originally, billingStatementList is a haze to get from DB etc.
val billingStatementList = Seq(
  BillingStatement(id=1L, billingId=1L, itemName="Billing 1 Product 1"),
  BillingStatement(id=2L, billingId=1L, itemName="Billing 1 Product 2"),
  BillingStatement(id=3L, billingId=2L, itemName="Billing 2 Product 1"),
  BillingStatement(id=4L, billingId=3L, itemName="Billing 3 Product 1"),
  BillingStatement(id=5L, billingId=3L, itemName="Billing 3 Product 2"),
  BillingStatement(id=6L, billingId=3L, itemName="Billing 3 Product 3")
)

List → Map conversion process


val billingStatementsMap = billingStatementList.foldLeft(Map[Long, Seq[BillingStatement]]()){(map,value) => {
  val key = value.billingId
  map.updated(key, map.getOrElse(key, Seq()) :+ value)
}}

The generated Map is an immutable Map. relief. map.getOrElse (key, Seq ()) is If the value associated with the key specified in the map is registered, that value is returned, and if it is not registered, an empty Seq is returned. Add the element value to that Seq and return a new Map with the updated element associated with the key. FoldLeft, which had an image used only for adding elements, can be used to avoid creating bugs [^ 4].

Summary

You can reduce bugs and mistakes by coding carefully. However, people are creatures that make mistakes. I feel that if you combine many variables and operations on them to get the result, you are more likely to "inadvertently" embed a bug. By utilizing the functions provided by the development language, why not spend the time and concentration to "be careful" toward "things that only people can do"?


[^ 1]: Of course, if you're trying to create a FW or a base class for your project, that might be a problem ... [^ 2]: Seq with element Tuple2 [^ 3]: By the way, until a while ago, I wrote a process to add an element to Map.newBuilder and result it in the block scope. [^ 4]: If you want to return multiple results in one loop, you can pass Tuple.

Recommended Posts

How do you write in Scala that was written in Java? (List → Map)
Do Scala Option.or Null in Java
Do you use Stream in Java?
How do you write the ternary operator (? :)
How to do base conversion in Java
Do not declare variables in List in Java
How to write Java String # getBytes in Kotlin?
How to write Scala from the perspective of Java
Write a class that can be ordered in Java
java: How to write a generic type list [Note]
Do not write if (isAdmin == true) code in Java
How to batch initialize arrays in Java that I didn't know when I was a beginner
Filter the Java No. 2 Optional list that was useful in business and get the first value
How do you create foreign key values ​​in FactoryBot ~ (crying
What you write in C # is written in Ruby like this
Java reserved word summary that you do not know unexpectedly
Convenient use of Map that you do not know unexpectedly
How to replace characters that you do not understand [Principle]
For Java beginners: List, Map, Iterator / Array ... How to convert?
[Java] How to use Map
[Java] How to use Map
How to write java comments
Write flyway callbacks in Java
How to use Java Map
Write Java8-like code in Java8
List aggregation in Java (Collectors.groupingBy)
List data structure [Java / Scala]
In Java 10, when you do gradle eclipse and JavaSE-1.10 comes out, ...
Understand how functional programming was introduced to Java in one shot
How to implement a job that uses Java API in JobScheduler
The operator that was born to be born, instanceof (Java) ~ How to use the instanceof operator ~
How to increment the value of Map in one line in Java