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;
	}
}

四、总结

注意: 拆分后的每个子集合的数据,必须是可以执行的独立业务单元数据。

发布了158 篇原创文章 · 获赞 147 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/weixin_39723544/article/details/103524154