目录
11.关于HashMap和TreeMap的排序问题
众所周知,HashMap是无序的,不能对HashMap进行排序(起码目前还不知道).但是这并不代表Map就一定是无序的! 没错本次提到的排序就是利用了TreeMap进行排序.
11.1.TreeMap特性
转自:https://blog.youkuaiyun.com/qq_32166627/article/details/72773293 源码分析,方法使用等还是看原文链接,这里仅展示概念
前言
TreeMap
的基本概念:
TreeMap集合
是基于红黑树
(Red-Black tree)的 NavigableMap实现。该集合最重要的特点就是可排序,该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法
。这句话是什么意思呢?就是说TreeMap可以对添加进来的元素进行排序,可以按照默认的排序方式,也可以自己指定排序方式。
根据上一条,我们要想使用TreeMap存储并排序我们自定义的类(如User类),那么必须自己定义比较机制:一种方式是User类去实现java.lang.Comparable接口,并实现其compareTo()方法。另一种方式是写一个类(如MyCompatator)去实现java.util.Comparator接口,并实现compare()方法,然后将MyCompatator类实例对象作为TreeMap的构造方法参数进行传参(当然也可以使用匿名内部类),这些比较方法是怎么被调用的将在源码中讲解。
下图是Map集合体系类图。
总结
TreeMap继承了Map的性质,同时其树结构又可以进行元素排序,用处很大。
11.2.java如何对Map进行排序
转自:https://blog.youkuaiyun.com/m0_51051154/article/details/120392110
Map排序(按key排序,按value排序)
主要分两种,按键排序、按值排序。 而且,按key排序主要用于TreeMap,而按value排序则对于Map的子类们都适用。
一、按键排序
按Key排序主要用于TreeMap`,可以实现按照Key值的大小,在对象插入时直接插入到合适的位置,保持Map的顺序性。
来看TreeMap
的构造函数:TreeMap(Comparator<? super K> comparator)
:构造一个新的、空的树映射,该映射根据给定比较器
进行排序。
这里的比较器是key的比较器。所以定义比较器时用于比较的两个参数是Key的数据类型的对象。
实例代码如下:
public class MapSortTest {
public static void main(String[] args) {
Map<String,String> stu=new TreeMap<>(new MyComparator());//传进来一个key的比较器对象来构造treemap
stu.put("apple", "55");
stu.put("boy", "32");
stu.put("cat", "22");
stu.put("dog", "12");
stu.put("egg", "11");
//map的遍历:把key抽取出来用set存放,然后用迭代器遍历keyset,同时用map.get(KEY)获取key所对应的value。
Set<String> keySet=stu.keySet();
Iterator it=keySet.iterator();
while (it.hasNext()) {
String next = (String)it.next();
System.out.println(next+","+stu.get(next));
}
}
}
//定义key的比较器,比较算法根据第一个参数o1,小于、等于或者大于o2分别返回负整数、0或者正整数,来决定二者存放的先后位置:返回负数则o1在前,正数则o2在前。
class MyComparator implements Comparator<String>{
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
}
二、按值排序
与按键排序只使用TreeMap不同,按值排序由于其方法所用到的类型的统一性,所以能用于Map的所有子类。
主要用到的知识点有;
1:map.entrySet()将map里的每一个键值对取出来封装成一个Entry对象并存放到一个Set里面。
2:泛型Map.Entry<type1,type2> 因为Key-value对组成Entry对象,此处指明Entry对象中这两个成员的数据类型。
3:Collections.sort(List list, Comparator<? super T> c) 集合类的排序方法,通过自定义的比较器进行排序。这里的list存放的对象是entry对象。定义比较器对entry对象中的value属性进行比较。
实例代码如下:
public class MapSortTest {
public static void main(String[] args) {
Map<String,String> stu=new TreeMap<>();//用TreeMap储存
// Map<String,String> stu=new HashMap<>();//用HashMap储存
stu.put("apple", "55");
stu.put("boy", "32");
stu.put("cat", "22");
stu.put("dog", "12");
stu.put("egg", "11");
//1:把map转换成entryset,再转换成保存Entry对象的list。
List<Map.Entry<String,String>> entrys=new ArrayList<>(stu.entrySet());
//2:调用Collections.sort(list,comparator)方法把Entry-list排序
Collections.sort(entrys, new MyComparator());
//3:遍历排好序的Entry-list,可得到按顺序输出的结果
for(Map.Entry<String,String> entry:entrys){
System.out.println(entry.getKey()+","+entry.getValue());
}
}
}
//自定义Entry对象的比较器。每个Entry对象可通过getKey()、getValue()获得Key或Value用于比较。换言之:我们也可以通过Entry对象实现按Key排序。
class MyComparator implements Comparator<Map.Entry>{
public int compare(Map.Entry o1, Map.Entry o2) {
return ((String)o1.getValue()).compareTo((String)o2.getValue());
}
}
10.关于在List集合首部插入一条复制的数据
需求分析
1.复制第一条数据,然后插入到第一条数据之后,新插入的数据,有两个字段需要手动置空
2.在第一条的基础上,向后,置空第一条数据之后所有数据中的两个字段
第一种: 这种方法比较笨,且不是正常的写法,但是这种写法有利于入门,并加深对List的理解,实际运用看第二种
List<PastBusiness> pastBusinessList = pastBusinessMapper.selectListByIdAndEId(approval.getApprovalId(),externalId);
// 在集合首部插入复制的第一条数据
for (int i = pastBusinessList.size() - 1; i >= 0; i--) {
PastBusiness pastBusiness = pastBusinessList.get(i);
// 置空第一条数据之后的提交人信息
if (i != 0) {
pastBusiness.setSubmitterTime(null);
pastBusiness.setSubmitter(null);
}
if (i+1 >= pastBusinessList.size()) {
pastBusinessList.add(pastBusiness);
} else {
// 这里存在对象的哈希地址一直的问题,所以后边置空数据的时候,会连带两条数据都置空,
// 所以这里新new一个对象,进行塞值
if (i == 0) {
PastBusiness pastBusiness1 = new PastBusiness();
BeanUtils.copyProperties(pastBusiness,pastBusiness1);
pastBusinessList.set(i + 1,pastBusiness1);
} else {
pastBusinessList.set(i + 1, pastBusiness);
}
}
}
// 置空第二条数据的提交人信息
pastBusinessList.get(1).setSubmitter(null);
pastBusinessList.get(1).setSubmitterTime(null);
return pastBusinessList;
第二种: 经历优化后的解决办法
需求分析
3.这里新增了一条需求: 在上文1. 2.的基础上,如果遇到特定的字段值发生了改变,就执行一下复制当前值并插入到后边
注意代码中,对数据的判断,主要优化 合并的就是这些判断
// 在集合首部插入复制的第一条数据
for (int i = 0; i < pastBusinessList.size(); i++) {
PastBusiness pastBusiness = pastBusinessList.get(i);
if (i == 0 || pastBusiness.getApprovalNumber() != pastBusinessList.get(i - 1).getApprovalNumber()) {
// 处理数据插入
PastBusiness pastBusiness1 = new PastBusiness();
BeanUtils.copyProperties(pastBusiness, pastBusiness1);
pastBusiness1.setSubmitter(null);
pastBusiness1.setSubmitterTime(null);
pastBusinessList.add(i + 1, pastBusiness1);
i++; // 向后挪动一个下标
} else {
// 置空数据
pastBusiness.setSubmitter(null);
pastBusiness.setSubmitterTime(null);
}
}
}
return pastBusinessList;
10.1.原理解析
java ArrayList数组使用add来插入一个元素,新数据下标为,i+1
,实例如下:
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(0);//插入第一个元素
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);//打印list数组
list.add(2, 7);
System.out.println(list);
}
}
运行结果如下:
9.list的forEach用法
List<StatisticsObjectAndDoubleDTO> inStockList = null;
if (inStockList != null && !inStockList.isEmpty()) {
Map<String,Double> inStockMap = new HashMap<>();
inStockList.forEach(inStock -> {
inStockMap.put((String) inStock.getName(),inStock.getNum());
});
statisticsChartVO.setInStockMap(inStockMap);
}
8.lambda – 过滤list中对象的某个属性非空,然后返回一个新的list
package com.example.demo.util;
import com.example.demo.entity.UserPO;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 过滤list中对象的某个属性非空,然后返回一个新的list
*/
public class LambdaForList {
public static void main(String[] args) {
//1. 初始化数据
UserPO user1 = new UserPO(1, "java");
UserPO user2 = new UserPO(2, "C");
UserPO user3 = new UserPO(null, "PHP");
List<UserPO> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
//2. 过滤list中对象的某个属性非空,然后返回一个新的list
List<UserPO> newUsers = users.stream()
.filter((UserPO user) -> user.getId() !=null).collect(Collectors.toList());
newUsers.forEach((UserPO user) ->
System.out.println(user.getName() + "--->" + user.getId()
));
}
}
输出
java--->1
C--->2
7.获取集合中最大值,list中对象的某个属性的最大值最小值平均值以及筛选
获取集合中最大值最小值
一、 普通集合
1、 查询集合中字符串的个数最多和最少
List<String> strs = new ArrayList<String>();
strs.add("a");
strs.add("ab");
strs.add("qwrrrrrrr");
strs.add("qrqw");
strs.add("qweqw");
strs.add("aqw");
System.out.println("最大值: " + Collections.max(strs));
System.out.println("最小值: " + Collections.min(strs));
2、 查询集合中数字的最大值和最小值
List<Integer> inte = new ArrayList<Integer>();
inte.add(1);
inte.add(23);
inte.add(56);
inte.add(2);
inte.add(346);
inte.add(2);
System.out.println("最大值: " + Collections.max(inte));
System.out.println("最小值: " + Collections.min(inte));
二、 集合中存放对象时查询对象中的某个属性的最大值最小值。
1. 创建一个实体类User
package com.list.max.min;
public class User {
private String name;//用户姓名
private Integer age;//用户年龄
public User() {
super();
}
public User(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
2. list中对象的某个属性的最大值最小值平均值以及筛选
package com.list.max.min;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* list中对象的某个属性的最大值最小值平均值以及筛选
* @author Administrator
*
*/
public class ListMaxMinTest {
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
User user01 = new User("张三", 18);
User user02 = new User("李四", 12);
User user03 = new User("王五", 26);
User user04 = new User("赵六", 50);
User user05 = new User("钱七", 37);
users.add(user01);
users.add(user02);
users.add(user03);
users.add(user04);
users.add(user05);
//查询年龄最大的用户
User maxAgeUser = users.stream().max(Comparator.comparing(User::getAge)).get();
//查询年龄最大的用户的年龄方式一
int maxAge01 = users.stream().max(Comparator.comparing(User::getAge)).get().getAge();
System.out.println("最大年龄的人maxAgeUser==="+maxAgeUser);
System.out.println("最大年龄的人的年龄maxAge01方式一==="+maxAge01);
//查询年龄最大的用户的年龄方式二
double maxAge02 = users.stream().mapToDouble(User::getAge).max().getAsDouble();
System.out.println("最大年龄的人的年龄maxAge02方式二==="+maxAge02);
//查询年龄最小的用户
User minAgeUser = users.stream().min(Comparator.comparing(User::getAge)).get();
//查询年龄最小的用户的年龄方式一
int minAge01 = users.stream().min(Comparator.comparing(User::getAge)).get().getAge();
System.out.println("最小年龄的人minAgeUser==="+minAgeUser);
System.out.println("最小年龄的人minAge01==="+minAge01);
//查询年龄最小的用户的年龄方式二
double minAge02 = users.stream().mapToDouble(User::getAge).min().getAsDouble();
System.out.println("最小年龄的人minAge02==="+minAge02);
//获取年龄总和方式一
int sumAge01 = users.stream().collect(Collectors.summingInt(User::getAge));
System.out.println("所有人的年龄总和sumAge01==="+sumAge01);
//获得年龄的总和方式二
int sumAge02 = users.stream().mapToInt(User -> User.getAge()).sum();
System.out.println("所有人的年龄总和sumAge02===="+sumAge02);
//获得年龄的总和方式三
double sumAge03 = users.stream().mapToDouble(User::getAge).sum();
System.out.println("所有人的年龄总和sumAge03===="+sumAge03);
//获得年龄的平均值方式一
double avgAge01 = users.stream().mapToInt(User -> User.getAge()).average().getAsDouble();
System.out.println("所有人的年龄平均值avgAge01===="+avgAge01);
//获得年龄的平均值方式二
double avgAge02 = users.stream().mapToDouble(User::getAge).average().getAsDouble();
System.out.println("所有人的年龄平均值avgAge02===="+avgAge02);
//过滤出年龄是26的user,想过滤出什么条件的都可以
List<User> users1 = users.stream().filter(User -> User.getAge() >= 26).collect(Collectors.toList());
System.out.println("大于等于26岁的人有users1===="+users1);
//过滤出姓名不等于张三user,想过滤出什么条件的都可以
List<User> users2 = users.stream().filter(User -> !User.getName().equals("张三")).collect(Collectors.toList());
System.out.println("姓名不等于张三的人有users2===="+users2);
//统计出年龄大于等于26的个数
long count01 = users.stream().filter(User -> User.getAge() >= 26).count();
System.out.println("大于等于26岁的人有多少个===="+count01);
//统计出姓名等于张三的人的个数
long count02 = users.stream().filter(User -> User.getName().equals("张三")).count();
System.out.println("姓名等于张三的人有多少个===="+count02);
}
}
版权声明:本标题为qq_42570364原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.youkuaiyun.com/qq_42570364/article/details/103643509
6.将List集合用字符串,逗号隔开进行拼接
先上效果:
直接上代码:
public class ArraySplicing {
private static String[] array = {"张三", "李四", "王五", "撒娇", "九点十几分", "没事", "圣诞节"};
private static String str;
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < array.length; i++) {
list.add(array[i]);
}
/**
*
* 将集合用字符串,逗号隔开拼接
* */
//第一种方法(灵活,可以用逗号隔开,用|线隔开)
str = StringUtils.join(list, ","); // 注意导包,import com.sun.deploy.util.StringUtils;
System.out.println("第一种方法" + str);
//第二种方法
str = listToString1(list);
System.out.println("第二种方法" + str);
//第三种方法(灵活,可以用逗号隔开,用|线隔开)
str = listToString2(list, ',');
System.out.println("第三种方法" + str);
//第四种方法
str = listToString3(list, ",");
System.out.println("第四种方法" + str);
Separator separator=new Separator(",");
//第五种方法
str = listToString4(list, separator );
System.out.println("第五种方法"+str);
}
public static String listToString1(List<String> list) {
StringBuilder sb = new StringBuilder();
if (list != null && list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
if (i < list.size() - 1) {
sb.append(list.get(i) + ",");
} else {
sb.append(list.get(i));
}
}
}
return sb.toString();
}
public static String listToString2(List list, char separator) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i)).append(separator);
}
return list.isEmpty() ? "" : sb.toString().substring(0, sb.toString().length() - 1);
}
public static String listToString3(List list, String separator) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i));
if (i < list.size() - 1) {
sb.append(separator);
}
}
return sb.toString();
}
public static class Separator {
private String next = "";
private String separator;
public Separator(String separator) {
this.separator = separator;
}
public String get() {
String result = next;
next = separator;
return result;
}
}
public static String listToString4(List<String> list, Separator separator) {
StringBuilder sb = new StringBuilder();
for (String s : list) {
if (s != null && !"".equals(s)) {
sb.append(separator.get()).append(s);
}
}
return sb.toString();
}
5.java中判断list是否为空的用法
1、如果想判断list是否为空,可以这么判断:
注意这里使用了 || 所以使用这种判断 为空和不为空的位置不能变换(==也不能换成!=),否则存在错误,详情见下坑:
if(null == list || list.size() ==0 ){
//为空的情况
}else{
//不为空的情况
}
关于这个判断非空的坑
if (null != vo.getDocumentsVOList() && vo.getDocumentsVOList().size() > 0) {
和
if (vo.getDocumentsVOList().size() > 0 && null != vo.getDocumentsVOList()) {
- 注意Bug1: 是
不一样的,第二种
会报错,如果字段为空会在判断里报空指针.
这里就涉及到短路与&&的用法,先判断前边,如果不生效,后边的就不会判断。这就有效避免了空指针错误,又能做判断 - 注意Bug2: 第一种在判断空数组的时候,不能使用 || ,否则也会判断错误,因为空数组 [] 不等于null 所以第一种的第一个判断就成立了,因为 || 所以直接就成立了
2、list.isEmpty() 和 list.size()==0 有啥区别呢
没有区别 。isEmpty()判断有没有元素,而size()返回有几个元素, 如果判断一个集合有无元素 建议用isEmpty()方法.比较符合逻辑用法。
3、list!=null 跟 ! list.isEmpty()?
所以一般的判断是
if(list!=null && !list.isEmpty()){
//不为空的情况
}else{
//为空的情况
}
4.List转Map的三种方法
https://blog.youkuaiyun.com/linsongbin1/article/details/79801952
1.for循环
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListToMap {
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
User user1 = new User();
user1.setId(1L);
user1.setAge("12");
User user2 = new User();
user2.setId(2L);
user2.setAge("13");
userList.add(user1);
userList.add(user2);
Map<Long, User> maps = new HashMap<>();
for (User user : userList) {
maps.put(user.getId(), user);
}
System.out.println(maps);
}
public static class User {
private Long id;
private String age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age='" + age + '\'' +
'}';
}
}
}
2.使用guava
Map<Long, User> maps = Maps.uniqueIndex(userList, new Function<User, Long>() {
@Override
public Long apply(User user) {
return user.getId();
}
});
3.使用JDK1.8
Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId,Function.identity()));
看来还是使用JDK 1.8方便一些。另外,转换成map的时候,可能出现key一样的情况,如果不指定一个覆盖规则,上面的代码是会报错的。转成map的时候,最好使用下面的方式:
Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key2));
有时候,希望得到的map的值不是对象,而是对象的某个属性,那么可以用下面的方式:
Map<Long, String> maps = userList.stream().collect(Collectors.toMap(User::getId, User::getAge, (key1, key2) -> key2));
3.List集合移除/删除元素
https://blog.youkuaiyun.com/zhaozuhao110/article/details/88116831.
List 移除某个元素
四种方式:
- 方式一,使用 Iterator ,顺序向下,如果找到元素,则使用 remove 方法进行移除。
- 方式二,倒序遍历 List ,如果找到元素,则使用 remove 方法进行移除。
- 方式三,正序遍历 List ,如果找到元素,则使用 remove 方法进行移除,然后进行索引 “自减”。
- 方式四,使用jdk1.8新增的Stream流操作
1.Iterator 迭代器
@Test
public void fun9(){
List<String> list = new ArrayList<>();
list.add("赵云");
list.add("黄忠");
list.add("马超");
list.add("关羽");
list.add("张飞");
// 获取迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();
if("关羽".equals(str)){
it.remove();
}
}
System.out.println(list);
}
2.倒序遍历
@Test
public void fun10(){
List<String> list = new ArrayList<>();
list.add("赵云");
list.add("黄忠");
list.add("马超");
list.add("关羽");
list.add("张飞");
for (int i = list.size() - 1; i > 0; i--) {
if("关羽".equals(list.get(i))){
list.remove(i);
}
}
System.out.println(list);
}
3.正序遍历
@Test
public void fun11(){
List<String> list = new ArrayList<>();
list.add("赵云");
list.add("黄忠");
list.add("马超");
list.add("关羽");
list.add("张飞");
for (int i = 0; i < list.size(); i++) {
if("关羽".equals(list.get(i))){
list.remove(i);
i--;
}
}
System.out.println(list);
}
4.Stream流操作(JDK 1.8 +)
@Test
public void fun8(){
List<String> list = new ArrayList<>();
list.add("赵云");
list.add("黄忠");
list.add("马超");
list.add("关羽");
list.add("张飞");
// 筛选出不是“关羽” 的集合
list = list.stream().filter(e -> !"关羽".equals(e)).collect(Collectors.toList());
System.out.println("method4|list=" + list);
}
问题:
1.为什么不能使用forEach
@Test
public void fun5(){
List<String> list = new ArrayList<>();
list.add("赵云");
list.add("黄忠");
list.add("马超");
list.add("关羽");
list.add("张飞");
for (String str :list) {
if ("张飞".equals(str)){
list.remove(str);
}
}
System.out.println(list);
}
原因:
foreach方式遍历元素的时候,是生成iterator,然后使用iterator遍历。在生成iterator的时候,会保存一个expectedModCount参数,这个是生成iterator的时候List中修改元素的次数。如果你在遍历过程中删除元素,List中modCount就会变化,如果这个modCount和exceptedModCount不一致,就会抛出异常。这个是为了安全的考虑。如果使用iterator遍历过程中,使用List修改了元素,可能会出现不正常的现象。如果使用iterator的remove方法则会正常,因为iterator的remove方法会在内部调用List的remove方法,但是会修改excepedModCount的值,因此会正常运行。
2.为什么forEach 删除倒数第二元素不会出现异常
@Test
public void fun12() {
List<String> list = new ArrayList<>();
list.add("赵云");
list.add("黄忠");
list.add("马超");
list.add("关羽");
list.add("张飞");
for (String str:list) {
if("关羽".equals(str)){
list.remove(str);
}
System.out.println(str);
}
}
仔细观察发现集合最后一个元素(“张飞”)并没有被遍历出来,因为当我们移除倒数第二个元素(“关羽”)时 cursor(游标)为 4 ,list 中size 属性的值会发生变化(5 - 1 = 4)变为 4,所以下面代码返回 false ,也就不会继续向下遍历。这也是能够正常执行的原因,因为如果继续遍历就会出现问题1 中的情况,在进行checkForComodification() 时,因为 modCount 发生了变化,而expectedModCount 并没有发生变化,所以会出现 ConcurrentModificationException异常。
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public boolean hasNext() {
return cursor != size;
}
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
3.普通正序 for 循环为什么要 i –
因为遍历过程中进行remove 操作时,该位置后面的元素会挤到前面来,这时候会发生一种情况就是原来元素的位置会被他后面的元素取代,而该位置已经遍历过了,所以该元素不会背遍历。 所以要进行 i-- 操作从该位置重新遍历。
@Test
public void fun11(){
List<String> list = new ArrayList<>();
list.add("赵云");
list.add("黄忠");
list.add("马超");
list.add("关羽");
list.add("张飞");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
if("关羽".equals(list.get(i))){
list.remove(i);
}
}
System.out.println(list);
}
就是下面的情况 “张飞” 不见了…
4.为什么倒序for 循环可以
当我们倒序遍历元素的时候,无论删除元素之后的元素怎么移动,之前的元素对应的索引(index)是不会发生变化的,所以在删除元素的时候不会发生问题。
2.List集合按某个字段排序(Collections.sort)
package wjtest_01;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ListSort<E> {
@SuppressWarnings(“unchecked”)
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
// 创建3个学生对象,年龄分别是20、19、21,并将他们依次放入List中
Student s1 = new Student();
s1.setAge(20);
s1.setUsable(true);
Student s2 = new Student();
s2.setAge(19);
s2.setUsable(true);
Student s3 = new Student();
s3.setAge(21);
s3.setUsable(false);
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println("排序前:" + list);
Collections.sort(list, new Comparator<Student>() {```
@Override
public int compare(Student o1, Student o2) {
// 按照学生的年龄进行升序排列
if (o1.getAge() > o2.getAge()) {
return 1;
}
if (o1.getAge() == o2.getAge()) {
return 0;
}
return -1;
}
});
System.out.println("升序排序后:" + list);
> Collections.sort(list, new Comparator<Student>() {
>
> public int compare(Student o1, Student o2) {
>
> // 按照学生的年龄进行降序排列
> if (o1.getAge() > o2.getAge()) {
> return -1;
> }
> if (o1.getAge() == o2.getAge()) {
> return 0;
> }
> return 1;
> }
> });
System.out.println("降序排序后:" + list);
Boolean b1 = true; // 创建Boolean对象1
Boolean b2 = false; // 创建Boolean对象0
Boolean b3 = true; // 创建Boolean对象1
System.out.println(b1);
int i;
i = b1.compareTo(b2); // b1和b2进行比较
System.out.println(i);//1-0
i = b2.compareTo(b1); // b2和b1进行比较
System.out.println(i);//0-1
i = b1.compareTo(b3); // b1和b3进行比较
System.out.println(i);//1-1
}
}
class Student{
private int age;
private Boolean isUsable;
public int getAge() {
return age;
}
public Boolean isUsable() {
return isUsable;
}
public void setUsable(Boolean isUsable) {
this.isUsable = isUsable;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return getAge()+"";
}
}
转载自:https://blog.csdn.net/wangjuan_01/article/details/51351633
若有侵权,请告知删除。
-----------------------------------
List集合按某个字段排序(Collections.sort)
https://blog.51cto.com/82711020/2094455
1.List集合求差集/并集
@Override
public List<InstitutionVO> findAllByUnit(String id) {
List<InstitutionVO> vos = new ArrayList<InstitutionVO>();
ArrayList<String> strings = new ArrayList<>();
List<Institution> institutionList = institutionRepository.findAllByUnit(id); //自身及下级
List<Institution> institutionAllList = institutionRepository.findAllByUnit(); //全部
// 重点
if(CollectionUtils.isNotEmpty(institutionList)) {
for (Institution institution : institutionList) {
strings.add(institution.getId());
}
for (Institution institution : institutionAllList) {
if (!strings.contains(institution.getId())) {
InstitutionVO vo = parseInstitutionVO(institution);
vos.add(vo);
}
}
}
return vos;
}