代码优化-List集合操作优化,集合对象排序


JDK版本1.8

定义一个简单的对象

// lombok注解
@Data
@AllArgsConstructor
public class Student {
    private String name;
    private int source;
}

初始化一个集合

	List<Student> students = new ArrayList<>();

    @Before
    public void init10() {
        students.add(new Student("小明1", 10));
        students.add(new Student("小明2", 20));
        students.add(new Student("小明3", 30));
        students.add(new Student("小明4", 40));
        students.add(new Student("小明5", 50));
        students.add(new Student("小明6", 60));
        students.add(new Student("小明7", 70));
        students.add(new Student("小明8", 80));
        students.add(new Student("小明9", 90));
        students.add(new Student("小明1", 100));
    }

删除元素

for循环删

用for循环删除元素,如果用正序删除元素,你在遍历的时候漏会掉某些元素。比如当你删除第1个元素后,继续根据索引访问第2个元素时,因为删除的关系后面的元素都往前移动了一位,所以实际访问的是第3个元素。因此,这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用。而用倒叙删除就不会存在这种问题。

for (int i = students.size() - 1; i >= 0; i--) {
	Student stu = students.get(i);
    if (40 < stu.getSource() && stu.getSource() < 70) {
      	students.remove(i);
     }
}

Iterator迭代器删除

Iterator<Student> iter = students.iterator();
while (iter.hasNext()) {
	Student stu = iter.next();
	if (50 < stu.getSource() && stu.getSource() < 70) {
		iter.remove();
		// 如果在迭代里面调用用源集合(students)remove(obj)方法会抛java.util.ConcurrentModificationException 异常
    }
}

用Stream.filter过滤元素

List<Student> list = students.stream().filter(stu -> {
	if (50 < stu.getSource() && stu.getSource() < 70) {
		return false;
	}
	return true;
 }).collect(Collectors.toList());
 // fileter返回的是一个匹配的元素的Stream,原集合没有变化,需调用collect 创建一个新的集合

删除指定下标范围

删除一个集合下标n到m的值
推 荐

// 比如删除students集合下标4到7的元素,前闭后开
students.subList(4, 7).clear();
// list的subList返回的是原集合的镜像副本,对该返回的集合操作,会反应到原集合

性能测试

自用笔记本测试CPU: i5-6300U, 12G内存

测试是上面的方法,生成数据代码如下:

 int num = 1000;
        Random random = new Random();
        for (int i = 0; i < num; i++) {
        	// source随机生成 0-100整数
            students.add(new Student("学生" + i, random.nextInt(100)));
        }

结果如下:
在这里插入图片描述

第一行是数据量,中间是3次平均耗时(毫秒)
在这里插入图片描述
可以看出,当数据量达到一定量级时,for循环和迭代器的性能下降明显,也说明了java8的stream操作集合的强大。

其他操作

处理集合元素,并合并某些元素

例如学生集合里面有名字相同的元素,需要把source*10,再进行合并:

@Test
public void test(){
	//  如果数据量很大,用并行流parallelStream,需用  Collectors.toConcurrentMap
	Map<String, Student> res = students.stream()
	                .collect(Collectors.toMap(Student::getName, valueMapper, mergeFunction));
	 // 打印结果集
	res.values().forEach(System.out::println);
	 
}
/**
 * 对单个元素进行处理.
 */
public UnaryOperator<Student> valueMapper = t -> {
	t.setSource(t.getSource()*10);
	// TODO 其他业务操作
	return t;
};
/**
 * 合并元素,注意必须返回一个对象.
 * 到这里面的元素是keyMapper相同的元素,底层用equals比较
 */
private BinaryOperator<Student> mergeFunction = (t1, t2) ->{
	t1.setSource(t1.getSource() + t2.getSource());
	return t1;
};

Collectors 里面还有其他很多方法,这里就不一一讲解了。

排序

根据集合对象单个属性排序

  1. 实现Comparable 接口,重写compareTo方法
@Data
@AllArgsConstructor
public class Student implements Comparable<Student> {

    private String name;

    private int source;

    @Override
    public int compareTo(Student o) {
        return this.source > o.getSource() ? 1 : this.source < o.getSource() ? -1 : 0;

    }
}
  1. 使用 Collections的sort方法
Collections.sort(students,new Comparator<Student>() {

            @Override
            public int compare(Student o1, Student o2) {
                
                return o1.getSource()>o2.getSource()? 1:o1.getSource()<o2.getSource()?-1:0;
            }
        });
students.stream().forEach(System.out::println);

根据集合对象指定多属性排序

1.创建比较器,需要commons-beanutils.jar 和 commons-collections.jar

ArrayList<Comparator> sortFields = new ArrayList<>();
// 创建一个默认的比较强
Comparator mycmp = ComparableComparator.getInstance();

// 创建一个降序序比较器
mycmp = ComparatorUtils.nullHighComparator(mycmp);
// 按name 降序
sortFields.add(new BeanComparator("name", mycmp));

// 创建一个升序比较器
mycmp = ComparatorUtils.nullLowComparator(mycmp);
// 按source 升序
sortFields.add(new BeanComparator("source", mycmp));
// 它包装了一个依次增加比较器,ComparatorChain依次调用每个比较器
ComparatorChain multiSort = new ComparatorChain(sortFields);
Collections.sort(students, multiSort);
// 打印排序结果
students.stream().forEach(System.out::println);
  1. java8的lambda表达式
List<Student> res = students.stream()
        .sorted(
        Comparator.comparing(Student::getName)
        // 默认是升序排序,调用reversed() 方法降序
        // 可以调用多个thenComparing(),进行排序
        .thenComparing(Student::getSource))
        .collect(Collectors.toList());
 // 打印结果集
res.stream().forEach(System.out::println);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章