超大集合數據分片策略
一、實際場景
實際項目開發中常常爲遇到超大數據量的集合,比如說一個size爲100w的List。而往往實際應用中,我們不可能把這麼大的數據量進行發送或傳遞,除了傳遞耗時過長,還有可能造成服務器內存溢出。所以我們往往將大集合進行數據分片,多次發送來提高靈活性和性能。
二、解決思路
將大集合拆分成若干個集合,然後分別發送或處理這些子集合。
三、實現方法
3.1 Guava
public class Main {
public static List<String> ids;
static {
// 構造測試數據
ids = new ArrayList<>(1500000);
for (int i = 0; i < 1335810; i++) {
ids.add(UUID.randomUUID().toString());
}
}
/**
* 1. 使用Guava工具包中Lists.partition()方法
* 下面的操作就是將ids按照每個集合10000個的大小進行分割。(注意,最後一個集合可能元素不足10000個)
*
*/
@Test
public void testGuavaTools() {
List<List<String>> partitionList = Lists.partition(ids, 10000);
System.out.println(partitionList.size());
}
}
3.2 Common-Collections
public class Main {
public static List<String> ids;
static {
// 構造測試數據
ids = new ArrayList<>(1500000);
for (int i = 0; i < 1335810; i++) {
ids.add(UUID.randomUUID().toString());
}
}
/**
* 2. 使用Apache Common Collections工具包中ListUtils.partition()方法
* 下面的操作就是將ids按照每個集合10000個的大小進行分割。(注意,最後一個集合可能元素不足10000個)
*
*/
@Test
public void testCommonCollections() {
List<List<String>> partitionList = ListUtils.partition(ids, 10000);
System.out.println(partitionList.size());
}
}
3.3 手動編碼實現
public class Main {
public static List<String> ids;
static {
// 構造測試數據
ids = new ArrayList<>(1500000);
for (int i = 0; i < 1335810; i++) {
ids.add(UUID.randomUUID().toString());
}
}
/**
* 4. 手動實現集合的數據分片
* 下面的操作就是將ids按照每個集合10000個的大小進行分割。(注意,最後一個集合可能元素不足10000個)
*
*/
@Test
public void testByMe() {
List<List<String>> partitionList = partition(ids, 10000);
System.out.println(partitionList.size());
System.out.println(partitionList.get(partitionList.size() - 1).size());
}
public static <T> List<List<T>> partition(List<T> source, int size) {
List<List<T>> result = new ArrayList<>();
// 1. 先計算出餘數
int remainder = source.size() % size;
// 2. 商
int number = (int) Math.ceil((double) source.size() / (double) size);
// 3. 初始偏移量默認爲0
int offset = 0;
List<T> value;
for (int i = 0; i < number; i++) {
if (i == number - 1) {
value = source.subList(i * number + offset, i * number + offset + remainder);
} else {
value = source.subList(i * number + offset, (i + 1) * number + offset);
}
result.add(value);
}
return result;
}
}
四、總結
注意: 拆分後的每個子集合的數據,必須是可以執行的獨立業務單元數據。