前言:
list是开发过程中使用比较频繁的,今天记一篇List使用中的三种形式,并区分之。
要求:
合并两个list中的元素(均为整数),返回一个不重复且非降序的list;
输入:list_1=[1,2,3,4,-1,2,2],list_2=[-1,1,2,3,4,5]
输出:result=[-1,1,2,3,4,5]
HashSet:
可以去重,但不能排序
TreeSet:
既可去重,又可以排序(默认为升序)
Stream:
既可去重,又可以排序(代码简洁且高效)
代码示例:
package com.tensquare.recruit.service;
import com.google.common.collect.Lists;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author Adam
* @description 合并两个List去重并排升序
* @date 2020/11/18
*/
public class ListTest {
public static void main(String[] args) {
//java中可以使用Arrays.asList()方法进行插入List元素
//Integer[] arr1 = {1, 2, 3, 4, -1, 2, -2};
//ArrayList list_1 = new ArrayList<>(Arrays.asList(arr1));
//Integer[] arr2 = {6, 4, 2, 1, 5};
//ArrayList list_2 = new ArrayList<>(Arrays.asList(arr2));
//google封装的Lists可以直接插入List元素 下面的方式,代码更简洁
List<Integer> list_1 = Lists.newArrayList(1, 2,-3,3, 4, -1, 2, -2);
List<Integer> list_2 = Lists.newArrayList(6, 5, 2, 1, -5);
//hashSet合并两个list
methodByHashSet(list_1, list_2, "HashSet方式:");
//TreeSet合并两个list
methodByTreeSet(list_1, list_2, "TreeSet方式:");
//调用merge方法使用java8stream流进行合并去重排序
methodByStream(list_1, list_2,"Stream流方式:");
}
/**
* 调用merge方法使用java8stream流进行合并去重排序
* @param list_1
* @param list_2
* @param s
*/
private static void methodByStream(List list_1, List list_2,String s) {
List<Integer> result3 = new ArrayList<>(streamMerge(list_1, list_2));
System.out.println(s + result3);
}
/**
* //TreeSet合并两个list
* @param list_1
* @param list_2
* @param s
*/
private static void methodByTreeSet(List list_1, List list_2, String s) {
//使用TreeSet进行去重后排序
Set<Integer> treeSet = treeSetMerge(list_1, list_2);
List<Integer> result2 = new ArrayList<>(treeSet);
System.out.println(s + result2);
}
/**
* 使用TreeSet进行去重后排序
* @param list_1
* @param list_2
* @return
*/
private static Set<Integer> treeSetMerge(List list_1, List list_2) {
Set<Integer> treeSet = new TreeSet<>(list_1);
treeSet.addAll(list_2);
return treeSet;
}
/**
* hashSet合并两个list
* @param list_1
* @param list_2
* @param s
*/
private static void methodByHashSet(List list_1, List list_2, String s) {
//使用HashSet进行去重
Set<Integer> hashSet = hashSetMerge(list_1, list_2);
List<Integer> result1 = new ArrayList<>(hashSet);
System.out.println(s + result1);
}
/**
* 使用HashSet进行去重
* @param list_1
* @param list_2
* @return
*/
private static Set<Integer> hashSetMerge(List list_1, List list_2) {
Set<Integer> hashSet = new HashSet<>(list_1);
hashSet.addAll(list_2);
return hashSet;
}
/**
* stream去重排序转list
* @param list_1
* @param list_2
* @return
*/
public static List<Integer> streamMerge(List<Integer> list_1, List<Integer> list_2) {
List<Integer> result = Stream.of(list_1, list_2)
.flatMap(Collection::stream)
.distinct()//去重
.sorted()//排序
.collect(Collectors.toList());//转List
return result;
}
}
输出结果:
总结:
1.虽然HashSet输出的结果看起来也是有序的,但是深入源码发现HashSet并没有给list进行排序
故使用Collections.sort()方法进行排序;
2.TreeSet中的通过源码我们可以发现,存入元素的时候,它创建了一个树,第一个元素就是树的根节点,后面的元素依次从树的根节点开始向后比较(创建比较器,利用comparator()方法进行比较),小的就往左边放,大的就往右边放,而相同的就不放进去(实现了唯一性)。取出元素的时候,它采用前序遍历的方法(根节点 左子树 右子树)遍历整个树,达到有序。
当然,我们也可以定制排序规则,如果需要定制排序,比如降序排列,可通过Comparator接口的帮助。需要重写compare()方法。
3.三种方式的执行效率又如何呢?
当元素很少的时候:Stream<TreeSet<HashSet(元素小于100)
当元素很多的时候:TreeSet<Stream<HashSet(元素小于10000000)