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循环删除元素,如果用正序删除元素,你在遍历的时候漏会掉某些元素。比如当你删除第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<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 异常
}
}
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
里面还有其他很多方法,这里就不一一讲解了。
@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;
}
}
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);
List<Student> res = students.stream()
.sorted(
Comparator.comparing(Student::getName)
// 默认是升序排序,调用reversed() 方法降序
// 可以调用多个thenComparing(),进行排序
.thenComparing(Student::getSource))
.collect(Collectors.toList());
// 打印结果集
res.stream().forEach(System.out::println);