List各种姿势操作及注意事项

用法大全

1.数组转List
方法很多,这里采用java 8新特性 Stream
		Stream<Integer> stream =Stream.of(123,4,21,5,6,1,4);
//		Stream<Integer> stream =Stream.of(new Integer[] {123,213,4,4});
		List<Integer> list =stream.collect(Collectors.toList());
		System.out.println(list);
2.排序
基本数组类型排序
		Stream<Integer> stream =Stream.of(123,4,21,5,6,1,4);
//		Stream<Integer> stream =Stream.of(new Integer[] {123,213,4,4});
		List<Integer> list =stream.collect(Collectors.toList());
		Collections.sort(list);
		System.out.println(list);

在这里插入图片描述

自定义对象排序
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {

	public static void main(String[] args) throws InterruptedException {
		Stream<Colour> stream =Stream.of(new  Colour(13, 34, 123),new  Colour(13, 34, 123),new  Colour(135, 1, 6));
//		Stream<Integer> stream =Stream.of(new Integer[] {123,213,4,4});
		List<Colour> list =stream.collect(Collectors.toList());
		Collections.sort(list,new Comparator<Colour>() {
			@Override
			public int compare(Colour o1, Colour o2) {
				// TODO Auto-generated method stub
				//按路绿色升序
//				return o1.getGreen()-o2.getGreen();
				//按路绿色降序
				return -(o1.getGreen()-o2.getGreen());
			}
		});
		list.forEach((t)->{
			System.out.println(t);
		});
		
	}
	static class Colour{
		
		public Colour(int red, int green, int yellow) {
			super();
			this.red = red;
			this.green = green;
			this.yellow = yellow;
		}
		private int red;
		private int green;
		private int yellow;
		public int getRed() {
			return red;
		}
		public void setRed(int red) {
			this.red = red;
		}
		public int getGreen() {
			return green;
		}
		public void setGreen(int green) {
			this.green = green;
		}
		public int getYellow() {
			return yellow;
		}
		public void setYellow(int yellow) {
			this.yellow = yellow;
		}
		@Override
		public String toString() {
			return "Letter [red=" + red + ", green=" + green + ", yellow=" + yellow + "]";
		}
		
	}

}

利用反射排序

如果对上面的例子进行红色排序,需要在compare方法改变要排序字段,但是如果有大量字段排序,这方法岂不是要复制很多遍?所以利用反射技术来解决一下


public class Main {

	public static void main(String[] args) throws InterruptedException {
		Stream<Colour> stream =Stream.of(new  Colour(13, 34, 123),new  Colour(13, 34, 123),new  Colour(135, 1, 6));
//		Stream<Integer> stream =Stream.of(new Integer[] {123,213,4,4});
		List<Colour> list =stream.collect(Collectors.toList());
		sort(list, "green", false);
		list.forEach((t)->{
			System.out.println(t);
		});
	}
	private static void sort(List<Colour> list ,String fieldName,boolean isDesc) {
		Collections.sort(list,new Comparator<Colour>() {
			@Override
			public int compare(Colour o1, Colour o2) {
				// TODO Auto-generated method stub
				//按路绿色升序
//				return o1.getGreen()-o2.getGreen();
				try {
					Field field1 =o1.getClass().getDeclaredField(fieldName);
					Field field2 =o2.getClass().getDeclaredField(fieldName);
					field1.setAccessible(true);
					field2.setAccessible(true);
					return isDesc?-(field1.getInt(o1)-field2.getInt(o2)):field1.getInt(o1)-field2.getInt(o2);
				} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				//按路绿色降序
				return -(o1.getGreen()-o2.getGreen());
			}
		});
	
	}
	static class Colour{
		
		public Colour(int red, int green, int yellow) {
			super();
			this.red = red;
			this.green = green;
			this.yellow = yellow;
		}
		private int red;
		private int green;
		private int yellow;
		public int getRed() {
			return red;
		}
		public void setRed(int red) {
			this.red = red;
		}
		public int getGreen() {
			return green;
		}
		public void setGreen(int green) {
			this.green = green;
		}
		public int getYellow() {
			return yellow;
		}
		public void setYellow(int yellow) {
			this.yellow = yellow;
		}
		@Override
		public String toString() {
			return "Letter [red=" + red + ", green=" + green + ", yellow=" + yellow + "]";
		}
		
	}

}

完美

3.去重
	public static void main(String[] args) throws InterruptedException {
		Stream<Integer> stream =Stream.of(new  Integer(13),new  Integer(123),new  Integer(6),new  Integer(13));
//		Stream<Integer> stream =Stream.of(new Integer[] {123,213,4,4});
		List<Integer> list =stream.collect(Collectors.toList());
		
		//利用set特性去重
		Set<Integer> set =new HashSet<Integer>(list);
	
		//set转List
		List<Integer> newList =new ArrayList<Integer>(set);
		
		System.out.println(newList);
	}

如果是自定义对象,就要小心了,比如下面的,必须重写hashCode和equals判断两个对象相等的条件



public class Main {

	public static void main(String[] args) throws InterruptedException {
		Stream<Student> stream =Stream.of(new  Student(13),new  Student(123),new  Student(6),new  Student(13));
		List<Student> list =stream.collect(Collectors.toList());
		
		//利用set特性去重
		Set<Student> set =new HashSet<Student>(list);
	
		//set转List
		List<Student> newList =new ArrayList<Student>(set);
		
		newList.forEach((t)->{
			System.out.println(t);
		});
	}

	static class  Student{
		private int  age;

		public Student(int age) {
			super();
			this.age = age;
		}

		public int getAge() {
			return age;
		}

		public void setAge(int age) {
			this.age = age;
		}
		@Override
		public String toString() {
			return "Student [age=" + age + "]";
		}
		@Override
		public boolean equals(Object obj) {
			if (obj instanceof Student) {
				if(this==obj) {
					return true;
				}
				Student student =(Student)obj;
				return student.getAge()==this.getAge();
			}
			return false;
		}
		@Override
		public int hashCode() {
			return this.age;
		}
	}

}

4.筛选
使用java8 新特性

public class Main {

	public static void main(String[] args) throws InterruptedException {
		Stream<Student> stream =Stream.of(new  Student(13),new  Student(123),new  Student(6),new  Student(13));
		List<Student> list =stream.collect(Collectors.toList());
		
		List<Student> newList =	list.stream()
				.filter((t)->{
					//筛选age大于的Student
			return t.getAge()>6;
		}).collect(Collectors.toList());
		
		newList.forEach((t)->{
			System.out.println(t);
		});
	}

	static class  Student{
		private int  age;

		public Student(int age) {
			super();
			this.age = age;
		}

		public int getAge() {
			return age;
		}

		public void setAge(int age) {
			this.age = age;
		}
		@Override
		public String toString() {
			return "Student [age=" + age + "]";
		}
		@Override
		public boolean equals(Object obj) {
			if (obj instanceof Student) {
				if(this==obj) {
					return true;
				}
				Student student =(Student)obj;
				return student.getAge()==this.getAge();
			}
			return false;
		}
		@Override
		public int hashCode() {
			return this.age;
		}
	}

}

5.转JSON
最简单可以利用toString方法
public class Main {

	public static void main(String[] args) throws InterruptedException {
		Stream<Student> stream =Stream.of(new  Student(13),new  Student(123),new  Student(6),new  Student(13));
		List<Student> list =stream.collect(Collectors.toList());

		System.out.println(list.toString());
	}

	static class  Student{
		private int  age;

		public Student(int age) {
			super();
			this.age = age;
		}

		public int getAge() {
			return age;
		}

		public void setAge(int age) {
			this.age = age;
		}
		@Override
		public String toString() {
			return "{\"age\":" + age + "}";
		}
	}
}

但是这里会多一个空格
在这里插入图片描述
这是由于AbstractCollection的toString做了一个拼接,加的一个空格,所以在使用AbstractCollection的子类的toString时候要注意一下。
在这里插入图片描述
可以自定义一个类,继承ArrayList,重写toStirng,把AbstractCollection的toString复制过来去掉.append(’ ');
在这里插入图片描述

6.线程安全
ArrayList是线程不安全的,如下的例子,可能会输出<=10000的数
public class Main  implements Runnable{
	private  static List<Integer> list =new ArrayList<Integer>();
	
	@Override
	public void run() {
	
	}
	public static void main(String[] args) throws InterruptedException {
	     ThreadGroup group = new ThreadGroup("testgroup");
	        for (int i = 0; i < 10000; i++) {
	            new Thread(group, new Runnable() {
					
					@Override
					public void run() {
				 		list.add(1);
					}
				}).start();
	        }
	       while(group.activeCount()!=0) {
	       }
	        System.out.println(list.size()); 		
	}

}

可以通过Collections.synchronizedList构造一个线程安全的ArrayList,此时输出,大小总会是10000,但是速度会下降



public class Main  implements Runnable{
	private  static List<Integer> list =Collections.synchronizedList(new ArrayList<Integer>());
	
	@Override
	public void run() {
	
	}
	public static void main(String[] args) throws InterruptedException {
	     ThreadGroup group = new ThreadGroup("testgroup");
	        for (int i = 0; i < 10000; i++) {
	            new Thread(group, new Runnable() {
					
					@Override
					public void run() {
				 		list.add(1);
					}
				}).start();
	        }
	  
	       while(group.activeCount()!=0) {
	       }
	        System.out.println(list.size());
	}

}

7.遍历移除
可以用java 8中Stream.filter的方法进行过滤,也可以使用for进行遍历删除,但是会出现小问题,如下面的例子
		Stream<Integer> stream =Stream.of(4,4,21,5,6,1,4);
//		Stream<Integer> stream =Stream.of(new Integer[] {123,213,4,4});
		List<Integer> list =stream.collect(Collectors.toList());
		for (int i = 0; i < list.size(); i++) {
			if(list.get(i)==4) {
				list.remove(i);
			}
		}
		System.out.println(list);
		

最终可能会输出[4, 21, 5, 6, 1],其中的4并没有被删除
来分析一下
i等于0时 把第一位移除,此时list大小为6,集合元素为[4, 21, 5, 6, 1, 4]
i等于1时,可想而知,从下标1的元素开始,第一位的4就被跳过。

可以通过倒序来解决

		Stream<Integer> stream =Stream.of(4,4,21,5,6,1,4);
//		Stream<Integer> stream =Stream.of(new Integer[] {123,213,4,4});
		List<Integer> list =stream.collect(Collectors.toList());
		
		for (int i = list.size()-1; i >=0; i--) {
			if(list.get(i)==4) {
				list.remove(i);
			}
		}
	
		System.out.println(list);

或者使用Iterator

		Iterator<Integer> iteerator = list.iterator();
		while(iteerator.hasNext()) {
			if(iteerator.next()==4) {
				iteerator.remove();
			}
		}
		System.out.println(list);
	}

谨慎使用Arrays.asList

Arrays.asList返回的是ArrayList中的一个内部类,也叫ArrayList。
在这里插入图片描述但是这个ArrayList并没有实现add方法,最终由他的爸爸AbstractList实现,而AbstractList中直接抛出异常
在这里插入图片描述
所以使用下面方法会报错
在这里插入图片描述同样Collections.emptyList();也是如此

发布了14 篇原创文章 · 获赞 7 · 访问量 5836

猜你喜欢

转载自blog.csdn.net/HouXinLin_CSDN/article/details/103046298