Java基礎之超大集合數據分片策略

超大集合數據分片策略

一、實際場景

實際項目開發中常常爲遇到超大數據量的集合,比如說一個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;
	}
}

四、總結

注意: 拆分後的每個子集合的數據,必須是可以執行的獨立業務單元數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章