Это первый день моего участия в ноябрьском испытании обновлений, подробности о мероприятии:Вызов последнего обновления 2021 г.
Несколько дней назад при реализации пакетной вставки MyBatis я столкнулся с проблемой: когда объем данных, вставляемых в пакеты, относительно велик, это приводит к тому, что выполнение программы сообщает об ошибке, как показано на следующем рисунке:Причина в том, что MySQL может выполнять операторы SQL только определенной длины, но когда вставляется большой объем данных, будет сгенерирован очень длинный SQL, так что программа сообщит об ошибке во время выполнения.
Чтобы решить эту проблему, есть два способа: во-первых, установить максимальную длину SQL, которую может выполнить MySQL, во-вторых, разделить большой список на N маленьких списков. Поскольку точно определить максимальную длину SQL в программе невозможно, оптимальное решение — второе, поэтому сегодняшняя статья здесь.
Введение
Процесс разделения списка на несколько небольших списков называется шардингом, конечно, его также можно назвать "разделением списков". Просто выберите имя, которое вам нравится и понятно.
В Java общие методы реализации шардинга следующие:
- Разделение с использованием фреймворка Google Guava;
- Разделение реализовано с использованием общедоступной среды Apache;
- Используйте отечественный фреймворк уровня бога Hutool для шардинга;
- Разделение реализовано с использованием Stream, предоставленного в JDK 8;
- Пользовательский функционал шардинга.
Далее мы рассмотрим их отдельно.
1.Google Guava
Сначала добавьте поддержку фреймворка в pom.xml проекта и добавьте следующую конфигурацию:
<!-- google guava 工具类 -->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
В среде Guava вам нужно только использовать метод Lists.partition для реализации сегментирования, как показано в следующем коде:
import com.google.common.collect.Lists;
import java.util.Arrays;
import java.util.List;
/**
* Guava 分片
*/
public class PartitionByGuavaExample {
// 原集合
private static final List<String> OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 集合分片
List<List<String>> newList = Lists.partition(OLD_LIST, 3);
// 打印分片集合
newList.forEach(i -> {
System.out.println("集合长度:" + i.size());
});
}
}
Результат выполнения приведенного выше кода показан на следующем рисунке:
2.apache commons
Сначала добавьте поддержку фреймворка в pom.xml проекта и добавьте следующую конфигурацию:
<!-- apache 集合工具类 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
В среде Commons вам нужно использовать только метод ListUtils.partition для реализации сегментирования, как показано в следующем коде:
import org.apache.commons.collections4.ListUtils;
import java.util.Arrays;
import java.util.List;
/**
* commons.collections4 集合分片
*/
public class PartitionExample {
// 原集合
private static final List<String> OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 集合分片
List<List<String>> newList = ListUtils.partition(OLD_LIST, 3);
newList.forEach(i -> {
System.out.println("集合长度:" + i.size());
});
}
}
Результат выполнения приведенного выше кода показан на следующем рисунке:
3.Hutool
Сначала добавьте поддержку фреймворка в pom.xml проекта и добавьте следующую конфигурацию:
<!-- 工具类 hutool -->
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.14</version>
</dependency>
В среде Hutool вам нужно использовать только метод ListUtil.partition для реализации сегментирования, как показано в следующем коде:
import cn.hutool.core.collection.ListUtil;
import java.util.Arrays;
import java.util.List;
public class PartitionByHutoolExample {
// 原集合
private static final List<String> OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 分片处理
List<List<String>> newList = ListUtil.partition(OLD_LIST, 3);
newList.forEach(i -> {
System.out.println("集合长度:" + i.size());
});
}
}
Результат выполнения приведенного выше кода показан на следующем рисунке:
4.JDK
Ручей Нет необходимости добавлять какой-либо фреймворк для реализации сегментирования через Stream в JDK 8. Конкретный код реализации выглядит следующим образом:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* JDK Stream Partition
*/
public class PartitionByStreamExample {
// 原集合
private static final List<Integer> OLD_LIST = Arrays.asList(
1, 2, 3, 4, 5, 6);
public static void main(String[] args) {
// 集合分片:将大于 3 和小于等于 3 的数据分别分为两组
Map<Boolean, List<Integer>> newMap = OLD_LIST.stream().collect(
Collectors.partitioningBy(i -> i > 3)
);
// 打印结果
System.out.println(newMap);
}
}
Результат выполнения приведенного выше кода показан на следующем рисунке:Преимущество этого метода в том, что не нужно добавлять фреймворк, а недостаток в том, что можно добиться только простого шардинга (разделения списка на два), и должны быть четкие условия шардинга. Например, заданное условие шардинга в этом случае — массив больше 3. Если больше 3, то он будет сгруппирован в одну группу, иначе — в другую группу.
5. Пользовательский шардинг
Если вы не хотите внедрять стороннюю платформу и использование Stream не может удовлетворить ваши потребности, вы можете рассмотреть возможность написания собственного кода для реализации функции сегментирования. Поскольку этот метод обычно не используется, мы приводим здесь только основные методы.
Ключевым методом реализации пользовательской функции сегментирования является метод subList, поставляемый с JDK, как показано на следующем рисунке:Пример использования следующий:
import java.util.Arrays;
import java.util.List;
public class App {
private static final List<String> _OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 集合分隔
List<String> list = _OLD_LIST.subList(0, 3);
// 打印集合中的元素
list.forEach(i -> {
System.out.println(i);
});
}
}
Результат выполнения приведенного выше кода показан на следующем рисунке:
Суммировать
В этой статье представлены 5 способов реализации сегментирования списков. Наиболее удобный способ — внедрить сторонние фреймворки, такие как Google Guava, Apache Commons или отечественный Hutool с открытым исходным кодом. Конечно, если ваш проект уже включает в себя вышеперечисленное, можно использовать любой из них. напрямую. Если это простое сегментирование, вы можете рассмотреть возможность использования Stream JDK или встроенного метода subList в List для реализации функции сегментирования.
Подпишитесь на официальный аккаунт «Сообщество китайского языка Java», чтобы увидеть больше статей из серии сводок по Java.