About the Guava collection package

Guava provides a rich collection package, which is very friendly for business operations. This article compares using Guava collection package and not using Guava collection package to see what convenience Guava collection package brings to our collection operation.

Application in collection processing

Group List< object >

There is an order list, which contains multiple orders from multiple users. We need to group the order list by user

Application class

ArrayListMultimap, of course Guava also provides LinkedList multimap, the API is similar, but the collection of values is replaced by LinkedList

To achieve contrast

/** * order entity */
public class Order {
    private String userId;
    private String orderId;
    private Double price; 
    private Date createTime;
    private Date updateTime;
}

public class Test {

    /** * implements grouping by itself */
    public void group(List<Order> orderList) {
        Map<String, List<Order>> userOrdersMap = new HashMap<>();
        for(Order order: orderList) {
            String userId = order.getUserId();
            if(userOrdersMap.containsKey(userId)) {
                userOrdersMap.get(userId).add(order);
            } else {
                List<Order> orders = newArrayList<>(); orders.add(order); userOrdersMap.put(user, orders); }}}/** * Use Guava to group groups */
    public void guavaGroup(List<Order> orderList) {
        ArrayListMultimap<String, Order> arrayListMultimap = ArrayListMultimap.create();
        orderList.forech(e -> arrayListMultimap.put(e.getUserId(), e));
        // ArrayListMultimap asMap() get(key) return List
      }}Copy the code

conclusion

If you look at Guava’s source code, you will find that the put method of ArrayListMultimap is similar to the code logic of our own implementation of grouping. ArrayListMultimap is a kind of encapsulation of our common list business operations. Introducing Guava allowed us to reduce code complexity and focus more on core business implementation.

Store the scores of multiple students in multiple subjects, calculate the total score of students and class subject comments

The database has a table to store the test scores of all students in all subjects in the class, read all results information, and calculate the total score of each student and the average score of the class subjects

The sample data

The name subjects score semester The class
Zhang SAN Chinese language and literature 95 On the 2021 Three years class two
Zhang SAN mathematics 80 On the 2021 Three years class two
Cathy Chinese language and literature 90 On the 2021 Three years class two
Cathy mathematics 75 On the 2021 Three years class two

Table structure

CREATE TABLE `test_score` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `student_name` varchar(255) NOT NULL COMMENT 'Student name',
  `subject` varchar(255) NOT NULL COMMENT 'subjects',
  `semester` varchar(255) NOT NULL COMMENT A 'term',
  `score` double NOT NULL COMMENT 'scores',
  `class_grade` varchar(255) NOT NULL COMMENT 'class'.PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Copy the code

The business scenario

Statistics of class test results statistics, statistics of each student’s total score, class subject average score, class total score average score, summary into statistical information

Business analysis

If such a statistical service is processed using SQL, each service needs to perform SQL query separately and then summarize, as follows:

  • Total score per student
select student_name, sum(score) gross_score from test_score where semester = '2021' and class_grade = Class 3 Class 2 group by student_name;
Copy the code
  • The average score of the class subjects
select subject,avg(score) as avg from test_score where semester = '2021' and class_grade = Class 3 Class 2 group by subject;
Copy the code
  • The average score of the class
SELECT avg(t.sum) avg FROM (SELECT sum(score) AS sum FROM test_score WHERE semester = '2021' AND class_grade = Class 3 Class 2 GROUP BY  student_name) AS t
Copy the code

Such SQL is relatively simple, but for a business, it needs to conduct three database interactions, and design multiple SQL function operations and groups, and the final result still needs to be aggregated. No matter at the database level or the code level, it is relatively complex and not conducive to maintenance. I will use Guava’s HashBasedTable to solve this business, reducing SQL operations and SQL complexity, and reducing code complexity.

Code implementation

  • Conduct a general query to obtain the scores of all students in class 2, Grade 3, the first semester of 2021, and the returned results are mapped as List
SELECT student_name, subject,semester,score,class_grade FROM test_score  WHERE semester = '2021' AND class_grade = Class 3 Class 2 
Copy the code
/** ** Student subject score entity */
public class TestScore {
    private String studentName;
    
    private String subject;
    
    private String semester;
    
    private Double score;
    
    private classGrade;
    
    // omit get set toString...
}
Copy the code
/** ** Statistics service implementation example */
public class TestScoreService {
    
    /** * Use false data to test the real scenario testScoreList by executing the above SQL */
    public static void main(String[] args) {
        TestScore t1 = new TestScore("Zhang"."Chinese"."Class two, Three".80D."2021");
        TestScore t2 = new TestScore("Zhang"."Mathematics"."Class two, Three".80D."2021");
        TestScore t3 = new TestScore("Bill"."Chinese"."Class two, Three".100D."2021");
        TestScore t4 = new TestScore("Bill"."Mathematics"."Class two, Three".90D."2021");
        ArrayList<TestScore> testScoreList = Lists.newArrayList(t1, t2, t3, t4);
        // initialize HashBasedTable HashBasedTable
      
        R
      ,>
        HashBasedTable<String, String, Double> table = HashBasedTable.create();
        for (TestScore testScore : testScoreList) {
            table.put(testScore.getStudentName(), testScore.getSubject(), testScore.getScore());
        }
        //3. Calculate the total score of each student
        Map<String, Map<String, Double>> studentSubjectScoreMap = table.rowMap();
        Map<String, Double> studentGrossScoreMap = Maps.newHashMap();
        for (Map.Entry<String, Map<String, Double>> entry : studentSubjectScoreMap.entrySet()) {
            String studentName = entry.getKey();
            / / total score
            double grossScore = entry.getValue().values().stream().mapToDouble(e -> e).sum();
            studentGrossScoreMap.put(studentName, grossScore);
        }
        // 4. Calculate the average score of the class total score
        double grossScoreAvg = studentGrossScoreMap.values().stream().mapToDouble(e -> e).average().orElse(-1);
        // 5. Calculate the average score of subjects
        Map<String, Map<String, Double>> subjectStudentScoreMap = table.columnMap();
        Map<Object, Object> subjectScoreAvgMap = Maps.newHashMap();
        for (Map.Entry<String, Map<String, Double>> entry : subjectStudentScoreMap.entrySet()) {
            String subject = entry.getKey();
            // Average scores of subjects
            double subjectScoreAvg = entry.getValue().values().stream().mapToDouble(e -> e).average().orElse(-1);
            subjectScoreAvgMap.put(subject, subjectScoreAvg);
        }
        // Total score of students
        System.out.println(studentGrossScoreMap);
        // The average score of the class subjects
        System.out.println(subjectScoreAvgMap);
        // The average score of the classSystem.out.println(grossScoreAvg); }}Copy the code

The execution result

{Li Si =190.0, Zhang SAN =160.0} {Math =85.0, Chinese =90.0} 175.0Copy the code

Use HashBasedTable to summarize

According to the above business scenario, the use of HashBasedTable is to encapsulate our data structure into a similar excel table, with its own rows and columns. We put students’ scores of each subject in the same row and the scores of the same subject in the same column. Using the provided rowMap(),columnMap() API helps us quickly extract row or column data for computational processing

BiMap

BiMap maintains bidirectional mapping and can find values by key

The sample

public class Demo {
    public static void main(String[] args) {
        BiMap<String, Integer> biMap = HashBiMap.create();
        biMap.put("Zhang".28);
        String name = biMap.inverse().get(28);
        // put raises an exception for an existing value
        // bimap. put(" lI si ", 28); / / throw IllegalArgumentExceptionvalue: already present: 28
        // Use forcePut() to avoid exceptions
        biMap.forcePut("Bill".28); }}Copy the code

conclusion

Bimap provides bidirectional relationship maintenance, but the business needs to ensure that the value is unique. If not, use forcePut

conclusion

Guava provides rich collections to assist us in solving business problems. We are familiar with the characteristics of various collections, understand their data structures, and can quickly choose the right collection for our business to process data once we are familiar with the requirements