java List、Set集合

集合的遍历

通常集合遍历,通过迭代器(Iterator)实现,Collection接口中的iterator()方法可返回此Collection进行迭代的迭代器。

使用方法:

  1. 创建迭代器Set
  2. 判断是否还有下一个元素
  3. 获取集合中的元素

注意:next方法返回的是Object

import java.util.*;

public class Muster{
	public static void main(String[] args) {
		Collection<String> list = new ArrayList<>();
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		
		//创建迭代器
		Iterator<String> it = list.iterator(); 
		//判断集合中是否存在元素
		while(it.hasNext()){
			//获取集合中的元素
			String str = (String)it.next();
			System.out.println(str);
		}
	}
}

第一章 List集合

1.1 List接口介绍

java.util.List 接口继承自 Collection 接口,是单列集合的一个重要分支,习惯性地会将实现了 List 接口的对 象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过 索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。

List接口特点:

  1. 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、 22、33的顺序完成的)。
  2. 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
  3. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

1.2 List接口中常用方法

List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操 作集合的特有方法,如下:

  • public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
  • public E get(int index) :返回集合中指定位置的元素。
  • public E remove(int index) :移除列表中指定位置的元素, 返回的是被移除的元素。
  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
public class ListDemo {
	public static void main(String[] args) {
		// 创建List集合对象
		List<String> list = new ArrayList<String>();
		
		// 往尾部添加 指定元素
		list.add("图图");
		list.add("小美");
		list.add("不高兴");
		System.out.println(list);
		
		// add(int index,String s) 往指定位置添加
		list.add(1,"没头脑");
		System.out.println(list);
		
		// String remove(int index) 删除指定位置元素 返回被删除元素
		// 删除索引位置为2的元素
		System.out.println("删除索引位置为2的元素");
		System.out.println(list.remove(2));
		System.out.println(list);
		// String set(int index,String s)
		// 在指定位置 进行 元素替代(改)
		// 修改指定位置元素
		list.set(0, "三毛");
		System.out.println(list);
	
		// String get(int index) 获取指定位置元素
		// 跟size() 方法一起用 来 遍历的
		for(int i = 0;i<list.size();i++){
			System.out.println(list.get(i));
		}
		//还可以使用增强for
		for (String string : list) {
			System.out.println(string);
		}
	}
}

第二章 List的子类

2.1 ArrayList集合

java.util.ArrayList 集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用多的功能为 查询数据、遍历数据,所以 ArrayList 是常用的集合。

许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。

对象添加到集合 :

public class Test02ArrayList {
	public static void main(String[] args) {
		//创建集合对象
		ArrayList<Student> list = new ArrayList<Student>();
		//创建学生对象
		Student s1 = new Student("赵",18);
		Student s2 = new Student("唐",20);
		Student s3 = new Student("景",25);
		Student s4 = new Student("罗",19);
		//把学生对象作为元素添加到集合中
		list.add(s1);
		list.add(s2);
		list.add(s3);
		list.add(s4);
		//遍历集合
		for(int x = 0; x < list.size(); x++) {
			Student s = list.get(x);
			System.out.println(s.getName()+"‐‐‐"+s.getAge());
		}
	}
}

打印集合方法
定义以指定格式打印集合的方法(ArrayList类型作为参数),使用{}扩起集合,使用@分隔每个元素。格式参照 {元素 @元素@元素}。

public class Test03ArrayList {
	public static void main(String[] args) {
		// 创建集合对象
		ArrayList<String> list = new ArrayList<String>();
		// 添加字符串到集合中
		list.add("张");
		list.add("宋");
		list.add("张");
		list.add("罗");
		// 调用方法
		printArrayList(list);
	}

	public static void printArrayList(ArrayList<String> list) {
		// 拼接左括号
		System.out.print("{");
		// 遍历集合
		for (int i = 0; i < list.size(); i++) {
			// 获取元素
			String s = list.get(i);
			// 拼接@符号
			if (i != list.size()1) {
				System.out.print(s + "@");
			} else {
			// 拼接右括号
			System.out.print(s + "}");
			}
		}
	}
}

获取集合方法
定义获取所有偶数元素集合的方法(ArrayList类型作为返回值)

public class Test04ArrayList {
	public static void main(String[] args) {
		// 创建Random 对象
		Random random = new Random();
		// 创建ArrayList 对象
		ArrayList<Integer> list = new ArrayList<>();
		
		// 添加随机数到集合
		for (int i = 0; i < 20; i++) {
			//随机生成0~999的数据
			int r = random.nextInt(1000) + 1;
			list.add(r);
		}
		// 调用偶数集合的方法
		ArrayList<Integer> arrayList = getArrayList(list);
		System.out.println(arrayList);
	}


	public static ArrayList<Integer> getArrayList(ArrayList<Integer> list) {
		// 创建小集合,来保存偶数
		ArrayList<Integer> smallList = new ArrayList<>();

		// 遍历list
		for (int i = 0; i < list.size(); i++) {
		// 获取元素
			Integer num = list.get(i);
// 判断为偶数,添加到小集合中
			if (num % 2 == 0){
				smallList.add(num);
			}
		}
		// 返回小集合
		return smallList;
	}
}

2.2 LinkedList集合

java.util.LinkedList 集合数据存储的结构是链表结构。方便元素添加、删除的集合。

LinkedList是一个双向链表
特点:查询慢,增删快

  • public void addFirst(E e) :将指定元素插入此列表的开头。
  • public void addLast(E e) :将指定元素添加到此列表的结尾。
  • public E getFirst():返回此列表的第一个元素。
    -public E getLast():返回此列表的后一个元素。
  • public E removeFirst() :移除并返回此列表的第一个元素。
  • public E removeLast():移除并返回此列表的后一个元素。
  • public E pop():从此列表所表示的堆栈处弹出一个元素。
  • public void push(E e):将元素推入此列表所表示的堆栈。
  • public boolean isEmpty():如果列表不包含元素,则返回true。

LinkedList是List的子类,List中的方法LinkedList都是可以使用

public class LinkedListDemo {
	public static void main(String[] args) {
		LinkedList<String> link = new LinkedList<String>();
		//添加元素
		link.addFirst("abc1");
		link.addFirst("abc2");
		link.addFirst("abc3");
		System.out.println(link);
		// 获取元素
		System.out.println(link.getFirst());
		System.out.println(link.getLast());
		// 删除元素
		System.out.println(link.removeFirst());
		System.out.println(link.removeLast());
	
		while (!link.isEmpty()) { //判断集合是否为空
			System.out.println(link.pop()); //弹出集合中的栈顶元素
		}
		
		System.out.println(link);
	}
}

第三章 Set接口

java.util.Set 接口和java.util.List 接口一样,同样继承自 Collection接口,它与 Collection 接口中的方 法基本一致,并没有对Collection接口进行功能上的扩充,只是比 Collection 接口更加严格了。与 List 接口不同的是, Set接口中元素无序,并且都会以某种规则保证存入的元素不出现重复

Set 集合有多个子类,这里我们介绍其中的 java.util.HashSetjava.util.LinkedHashSet这两个集合。

tips:Set集合取出元素的方式可以采用:迭代器、增强for

3.1 HashSet集合介绍

java.util.HashSet 是 Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序 不一致)。 java.util.HashSet底层的实现其实是一个 java.util.HashMap支持,由于我们暂时还未学习,先做了 解。
HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于: hashCode 与 equals 方法。

重复的元素set集合直接不存储

3.2 HashSet集合存储数据的结构(哈希表)

简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示。
在这里插入图片描述

在这里插入图片描述

3.3 HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时,需要重写对象中的hashCodeequals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一

创建自定义Student类:

public class Student {
	private String name;
	private int age;


	public Student() {
	}

	public Student(String name, int age) {
	this.name = name;
	this.age = age;
	}

	public String getName() {
	return name;
	}
	
	public void setName(String name) {
	this.name = name;
	}

	public int getAge() {
	return age;
	}

	public void setAge(int age) {
	this.age = age;
	}
	
	@Override
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;
		Student student = (Student) o;
			return age == student.age &&
					Objects.equals(name, student.name);
		}

	@Override
	public int hashCode() {
		return Objects.hash(name, age);
	}
}

public class HashSetDemo2 {
	public static void main(String[] args) {
		//创建集合对象 该集合中存储 Student类型对象
		HashSet<Student> stuSet = new HashSet<Student>();
		//存储
		Student stu = new Student("罗", 43);
		stuSet.add(stu);
		stuSet.add(new Student("郭", 44));
		stuSet.add(new Student("于", 43));
		stuSet.add(new Student("谭", 23));
		stuSet.add(stu);

		for (Student stu2 : stuSet) {
			System.out.println(stu2);
		}
	}
}
执行结果:
Student [name=, age=44]
Student [name=, age=43]
Student [name=, age=23]

3.3 LinkedHashSet

我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢? 在HashSet下面有一个子类 java.util.LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构。

public class LinkedHashSetDemo {
	public static void main(String[] args) {
		Set<String> set = new LinkedHashSet<String>();
		set.add("bbb");
		set.add("aaa");
		set.add("abc");
		set.add("bbc");
		Iterator<String> it = set.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
}
结果:
bbb
aaa
abc
bbc

第四章 Collections工具类

4.1 常用功能

java.utils.Collections 是集合工具类,用来对集合进行操作
部分方法如下:

  • public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
  • public static void shuffle(List<?> list) 打乱顺序 :打乱集合顺序
  • public static <T> void sort(List<T> list):将集合中元素按照默认规则排序.
  • public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序
public class CollectionsDemo {
	public static void main(String[] args) {
		ArrayList<Integer> list = new ArrayList<Integer>();
		//原来写法
		//list.add(12);
		//list.add(14);
		//list.add(15);
		//list.add(1000);
		//采用工具类 完成 往集合中添加元素
		Collections.addAll(list, 5, 222, 12);
		System.out.println(list);
		//排序方法
		Collections.sort(list);
		System.out.println(list);
	}
}
结果:
[5, 222, 1, 2]
[1, 2, 5, 222]

4.2 Comparator比较器

public static <T> void sort(List<T> list) :将集合中元素按照默认规则排序。

public class CollectionsDemo2 {
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<String>();
		list.add("cba");
		list.add("aba");
		list.add("sba");
		list.add("nba");
		//排序方法
		Collections.sort(list);
		System.out.println(list);
	}
}
结果:[aba, cba, nba, sba]

自定义排序:
说到排序了,简单的说就是两个对象之间比较大小,那么在JAVA中提供了两种比较实现的方式,一种是比较死板的 采用 java.lang.Comparable 接口去实现,一种是灵活的当我需要做排序的时候在去选择的 java.util.Comparator 接口完成

那么我们采用的 public static <T> void sort(List<T> list) 这个方法完成的排序,实际上要求了被排序的类型 需要实现Comparable接口完成比较的功能,在String类型上如下:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {

String类实现了这个接口,并完成了比较规则的定义,但是这样就把这种规则写死了,那比如我想要字符串按照第 一个字符降序排列,那么这样就要修改String的源代码,这是不可能的了,那么这个时候我们可以使用public static <T> void sort(List<T> list,Comparator<? super T> ) 方法灵活的完成,这个里面就涉及到了 Comparator这个接口,位于位于java.util包下,排序是comparator能实现的功能之一,该接口代表一个比较器,比 较器具有可比性!顾名思义就是做排序的,通俗地讲需要比较两个对象谁排在前谁排在后,那么比较的方法就是:

public int compare(String o1, String o2) :比较其两个参数的顺序。
两个对象比较的结果有三种: 大于,等于,小于
如果要按照升序排序 则o1 小于o2,返回(负数),相等返回0,01大于02返回(正数)
如果要按照降序排序 则o1 小于o2,返回(正数),相等返回0,01大于02返回(负数)

public class CollectionsDemo3 {
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<String>();
		list.add("cba");
		list.add("aba");
		list.add("sba");
		list.add("nba");
		//排序方法 按照第一个单词的降序
		Collections.sort(list, new Comparator<String>() {
		@Override
		public int compare(String o1, String o2) {
			return o2.charAt(0) ‐ o1.charAt(0);
			}
		});
		System.out.println(list);
	}
}
结果:[aba, cba, nba, sba]

4.3 简述Comparable和Comparator两个接口的区别。

Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法 被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中 的键或有序集合中的元素,无需指定比较器。

Comparator:强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或 有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。

4.4 练习

创建一个学生类,存储到ArrayList集合中完成指定排序操作。

Student 初始类:

public class Student{
	private String name;
	private int age;
	
	public Student() {
	}
	
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
	}
	
	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student{" +
				"name='" + name + '\'' +
				", age=" + age +
				'}';
	}
}

测试类:

public class Demo {
	public static void main(String[] args) {
// 创建四个学生对象 存储到集合中
		ArrayList<Student> list = new ArrayList<Student>();
		
		list.add(new Student("rose",18));
		list.add(new Student("jack",16));
		list.add(new Student("abc",16));
		list.add(new Student("ace",17));
		list.add(new Student("mark",16));
		/*
		让学生 按照年龄排序 升序
		*/
		
		// Collections.sort(list);//要求 该list中元素类型 必须实现比较器Comparable接口
		for (Student student : list) {
			System.out.println(student);
		}
	}
}

发现,当我们调用Collections.sort()方法的时候程序报错了。
原因:如果想要集合中的元素完成排序,那么必须要实现比较器Comparable接口。 于是我们就完成了Student类的一个实现,如下:

public class Student implements Comparable<Student>{
	....
	@Override
	public int compareTo(Student o) {
		return this.age‐o.age;//升序
	}
}

再次测试,代码就OK 了效果如下:

Student{name='jack', age=16}
Student{name='abc', age=16}
Student{name='mark', age=16}
Student{name='ace', age=17}
Student{name='rose', age=18}

注:本文是作者一边学习一边做的笔记,内容参考所学的视频以及配套资料,并非全由自己创作

发布了37 篇原创文章 · 获赞 30 · 访问量 1137

猜你喜欢

转载自blog.csdn.net/myjess/article/details/104329139