Пример приложения общего пакета сбора Guava

задняя часть Natural Language Toolkit
Пример приложения общего пакета сбора Guava

О наборе «Коллекция гуавы»

Guava предоставляет множество пакетов сбора, которые очень удобны для бизнес-операций.В этой статье сравнивается использование пакета сбора Guava и неприменимого пакета сбора Guava, чтобы увидеть, какое удобство пакет сбора Guava обеспечивает нашим операциям сбора.

Приложения в обработке коллекции

Список групп

Введение в бизнес: Существует список заказов, который содержит несколько заказов от нескольких пользователей.Нам нужно сгруппировать список заказов в соответствии с пользователями.

Класс приложения

ArrayListMultimap, конечно, Гуава тоже предоставляет LinkedListMultimap, апи аналогично, но коллекция хранимых значений заменена на LinkedList

добиться контраста

/**
 * 订单实体
 */
public class Order {
    private String userId;
    private String orderId;
    private Double price; 
    private Date createTime;
    private Date updateTime;
}

public class Test {

    /**
     * 自己实现分组
     */
    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 = new ArrayList<>();
                orders.add(order);
                userOrdersMap.put(user, orders);
            }
        }
    }
    /**
     * 使用Guava进行分组分组
     */
    public void guavaGroup(List<Order> orderList) {
        ArrayListMultimap<String, Order> arrayListMultimap = ArrayListMultimap.create();
        orderList.forech(e -> arrayListMultimap.put(e.getUserId(), e));
        // ArrayListMultimap 常用API asMap() get(key)返回值为List<T>
    }
}

В заключение

Глядя на исходный код Guava, вы обнаружите, что метод put ArrayListMultimap похож на нашу собственную логику кода для реализации группировки. ArrayListMultimap эквивалентен инкапсуляции наших общих бизнес-операций со списками. При работе с проектами со многими бизнес-списками введение Guava может уменьшить сложность нашего кода. , более ориентированный на реализацию основного бизнеса.

Храните баллы нескольких студентов и нескольких предметов, подсчитывайте общий балл студентов и оценку комментариев по предмету класса.

В базе данных есть таблица, в которой хранятся результаты тестов по всем предметам всех учащихся в классе, считывается вся информация о баллах и вычисляется общий балл каждого учащегося и средний балл по предметам в классе.

образец данных

Имя предмет Доля семестр сорт
Чжан Сан язык 95 на 2021 год Второй класс за три года
Чжан Сан математика 80 на 2021 год Второй класс за три года
Ван Ву язык 90 на 2021 год Второй класс за три года
Ван Ву математика 75 на 2021 год Второй класс за три года

Структура таблицы

CREATE TABLE `test_score` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `student_name` varchar(255) NOT NULL COMMENT '学生姓名',
  `subject` varchar(255) NOT NULL COMMENT '科目',
  `semester` varchar(255) NOT NULL COMMENT '学期',
  `score` double NOT NULL COMMENT '分数',
  `class_grade` varchar(255) NOT NULL COMMENT '班级',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Деловая сцена

Статистика результатов тестов класса, статистика общего балла каждого учащегося, средний балл по предмету в классе, средний балл общего балла в классе и обобщение в статистическую информацию.

бизнес-анализ

Если такой статистический бизнес обрабатывается sql, каждый бизнес должен быть sql-запросом и агрегирован отдельно, как показано ниже:

  • Общий балл для каждого ученика
select student_name, sum(score) gross_score from test_score where semester = '2021上' and class_grade = '三年二班' group by student_name;
  • Средний предмет класса
select subject,avg(score) as avg from test_score where semester = '2021上' and class_grade = '三年二班' group by subject;
  • средний класс
SELECT avg(t.sum) avg FROM (SELECT sum(score) AS sum FROM test_score WHERE semester = '2021上' AND class_grade = '三年二班' GROUP BY  student_name) AS t

Такой SQL относительно прост, но для бизнеса требуется три взаимодействия с базой данных, а также разработаны несколько операций и групп функций SQL.Конечный результат все еще необходимо агрегировать, будь то на уровне базы данных или на уровне кода, это относительно Это сложен и не способствует обслуживанию.Далее я буду использовать HashBasedTable от Guava, чтобы решить эту проблему, уменьшить операции SQL и сложность SQL, а сложность кода низкая.

Код

  • Выполните общий запрос, чтобы получить оценки всех учащихся во втором семестре третьего курса и во втором классе 2021 года, а возвращенные результаты сопоставляются со списком.
SELECT student_name, subject,semester,score,class_grade FROM test_score  WHERE semester = '2021上' AND class_grade = '三年二班' 
/**
 * 学生科目成绩实体
 */
public class TestScore {
    private String studentName;
    
    private String subject;
    
    private String semester;
    
    private Double score;
    
    private classGrade;
    
    // 省略get set toString ...
}
/**
 * 统计业务实现示例
 */
public class TestScoreService {
    
    /**
     * 使用假数据进行测试 真是场景 testScoreList通过执行上面sql获得
     */
    public static void main(String[] args) {
        TestScore t1 = new TestScore("张三", "语文", "三年二班", 80D, "2021上");
        TestScore t2 = new TestScore("张三", "数学", "三年二班", 80D, "2021上");
        TestScore t3 = new TestScore("李四", "语文", "三年二班", 100D, "2021上");
        TestScore t4 = new TestScore("李四", "数学", "三年二班", 90D, "2021上");
        ArrayList<TestScore> testScoreList = Lists.newArrayList(t1, t2, t3, t4);
        // 2.初始化HashBasedTable HashBasedTable<R, C, V> R相当行 就是学生姓名 C 相当于列 就是科目
        HashBasedTable<String, String, Double> table = HashBasedTable.create();
        for (TestScore testScore : testScoreList) {
            table.put(testScore.getStudentName(), testScore.getSubject(), testScore.getScore());
        }
        //3.计算每个学生的总分
        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();
            // 总分
            double grossScore = entry.getValue().values().stream().mapToDouble(e -> e).sum();
            studentGrossScoreMap.put(studentName, grossScore);
        }
        // 4.计算班级总分平均分
        double grossScoreAvg = studentGrossScoreMap.values().stream().mapToDouble(e -> e).average().orElse(-1);
        // 5.计算科目平均分
        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();
            // 科目平均分
            double subjectScoreAvg = entry.getValue().values().stream().mapToDouble(e -> e).average().orElse(-1);
            subjectScoreAvgMap.put(subject, subjectScoreAvg);
        }
        // 学生总分
        System.out.println(studentGrossScoreMap);
        // 班级科目平均分
        System.out.println(subjectScoreAvgMap);
        // 班级总分平均分
        System.out.println(grossScoreAvg);
    }
}

Результаты

{李四=190.0, 张三=160.0}
{数学=85.0, 语文=90.0}
175.0

Резюме использования HashBasedTable

В соответствии с приведенным выше бизнес-сценарием использование HashBasedTable заключается в инкапсуляции нашей структуры данных в таблицу Excel с собственными строками и столбцами.Мы помещаем оценки по каждому предмету учащихся в одну строку, а оценки по одному и тому же предмету в тот же столбец, используйте предоставленный API rowMap(), columnMap(), чтобы помочь нам быстро получить данные строки или столбца, а затем выполнить расчетную обработку

BiMap

BiMap поддерживает двустороннее сопоставление и может находить значения по ключу.

Пример

public class Demo {
    public static void main(String[] args) {
        BiMap<String, Integer> biMap = HashBiMap.create();
        biMap.put("张三", 28);
        String name = biMap.inverse().get(28);
        // put已经存在的值会抛出异常
        // biMap.put("李四", 28); // 抛出IllegalArgumentExceptionvalue: already present: 28
        // 使用forcePut()可以避免异常
        biMap.forcePut("李四", 28);
    }
}

В заключение

bimap обеспечивает двустороннее обслуживание отношений, но бизнес должен гарантировать, что значение уникально.Если оно не уникально, вам нужно использовать forcePut

Суммировать

Guava предоставляет множество коллекций, которые помогают нам решать бизнес-задачи.Мы знакомы с характеристиками различных коллекций, понимаем их структуры данных и можем быстро выбрать коллекции, подходящие для нашего собственного бизнеса, для обработки данных после ознакомления с требованиями.