简单了解使用并掌握Collection集合

1.1 集合概述

Collection集合:集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?

  • 数组的长度是固定的。集合的长度是可变的。
  • 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。

集合框架

JAVASE提供了满足各种需求的API,在使用这些API前,先了解其继承与接口操作架构,才能了解何时采用哪个类,以及类之间如何彼此合作,从而达到灵活应用。

集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map

  • Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.Listjava.util.Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayListjava.util.LinkedListSet接口的主要实现类有java.util.HashSetjava.util.TreeSet

学习集合的目标:

  1. 会使用集合存储数据
  2. 会遍历集合,把数据取出来
  3. 掌握每种集合的特性

集合框架的学习方式:

  1. 学习顶层:学习顶层接口/抽象类中共性的方法,所有的子类都可以使用
  2. 使用底层:底层不是接口就是抽象类,无法创建对象使用,需要使用底层的子类创建对象使用

从上面的描述可以看出JDK中提供了丰富的集合类库,为了便于初学者进行系统地学习,接下来通过一张图来描述整个集合类的继承体系。
在这里插入图片描述
集合本身是一个工具,它存放在java.util包中。在Collection接口定义着单列集合框架中最最共性的内容。

Collection常用功能

Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:

  • public boolean add(E e): 把给定的对象添加到当前集合中 。
  • public void clear() :清空集合中所有的元素。
  • public boolean remove(E e): 把给定的对象在当前集合中删除。
  • public boolean contains(E e): 判断当前集合中是否包含给定的对象。
  • public boolean isEmpty(): 判断当前集合是否为空。
  • public int size(): 返回集合中元素的个数。
  • public Object[] toArray(): 把集合中的元素,存储到数组中。
package study_p232_p237_Collection_Iterator_Foreach;

import java.util.ArrayList;
import java.util.Collection;

/*
 	java.util.Collection接口
 		所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法
 		任意的单列集合都可以使用Collection接口中的方法
 */
public class Collection_1 {

	public static void main(String[] args) {
		//创建集合对象,可以使用多态
		Collection<String> coll = new ArrayList<String>();
		System.out.println(coll); // 重写了toString方法
		
		/*
		 	public boolean add(E e): 把给定的对象添加到当前集合中。
		 	返回值是一个boolean值,一般都返回true,所以可以不用接收
		 */
		boolean b1 = coll.add("张三");
		System.out.println("b1:" + b1); // b1:true
		System.out.println(coll); // [张三]
		coll.add("李四");
		coll.add("王五");
		coll.add("赵六");
		coll.add("田七");
		System.out.println(coll); // [张三, 李四, 王五, 赵六, 田七]
		
		/*
		 	public boolean remove(E e): 把给定的对象在当前集合中删除。
		 	返回值是一个boolean值,集合中存在元素,删除元素,返回true
		 							集合中不存在元素,删除失败,返回false
		 */
		boolean b2 = coll.remove("赵六");
		System.out.println("b2:" + b2); // b2:true
		boolean b3 = coll.remove("赵六");
		System.out.println("b3:" + b3); // b3:false
		System.out.println(coll); //[张三, 李四, 王五, 田七]
		
		/*
		 	public boolean contains(E e): 判断当前集合中是否包含给定的对象。
		 	返回值是一个boolean值,包含返回true,不包含返回false
		 */
		boolean b4 = coll.contains("李四");
		System.out.println("b4:" + b4); // b4:true
		boolean b5 = coll.contains("赵六");
		System.out.println("b5:" + b5); // b5:false
		
		//public boolean isEmpty(): 判断当前集合是否为空。集合为空返回true,不为空返回false
		boolean b6 = coll.isEmpty();
		System.out.println("b6:" + b6); // b6:false
		
		//public int size(): 返回集合中元素的个数。
		int size = coll.size();
		System.out.println("size:" + size); // size:4
		
		//public Object[] toArray(): 把集合中的元素,存储到数组中。
		Object[] array = coll.toArray();
		for (int i = 0; i < array.length; i++) {
			if (i == array.length - 1) {
				System.out.println(array[i]);
			}else {
				System.out.print(array[i] + " ");
			}
		}
		
		//public void clear(): 清空集合中所有的元素。
		coll.clear();
		System.out.println(coll); // []
		System.out.println(coll.isEmpty()); // true
	}
}

tips: 有关Collection中的方法可不止上面这些,其他方法可以自行查看API学习。

1.2 Iterator迭代器

Iterator接口
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.IteratorIterator接口也是Java集合中的一员,但它与CollectionMap接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:

  • public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。

下面介绍一下迭代的概念:

迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Iterator接口的常用方法如下:

  • public E next():返回迭代的下一个元素。
  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。

接下来通过代码来了解如何使用:

package study_p232_p237_Collection_Iterator_Foreach;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/*
 	java.util.Iterator接口:迭代器(对集合进行遍历)
 	有两个常用的方法
		public boolean hasNext(): 如果仍有元素可以迭代,则返回 true。
			判断集合中还有没有下一个元素,有就返回true,没有就返回false
		public E next(): 返回迭代的下一个元素。
			取出集合中的下一个元素
	Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊
	Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象。
		Iterator<E> iterator(): 返回在此 collection 的元素上进行迭代的迭代器。
		
	迭代器的使用步骤(重点):
		1、使用集合中的方法iterator获取迭代器的实现类对象,用Iterator接口来接收(多态)
		2、使用Iterator接口中的方法hasNext判断还有没有下一个元素
		3、使用Iterator接口中的方法next取出集合中的下一个元素
 */
public class Iterator_1 {

	public static void main(String[] args) {
		Collection<String> coll = new ArrayList<String>();
		coll.add("姚明");
		coll.add("科比");
		coll.add("乔丹");
		coll.add("麦迪");
		coll.add("库里");
		/*
		 	1、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
		 	注意:
		 		Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
		 */
		// 多态		接口				实现类对象
		Iterator<String> iterator1 = coll.iterator();
		
		/*
		 	发现使用迭代器取出集合中元素的代码,是一个重复的过程
		 	所以我们可以使用循环优化
		 	不知道集合中有多少元素,要使用while循环
		 	循环结束的条件,hasnext方法返回false
		 */
		while (iterator1.hasNext() == true) {
			String e = iterator1.next();
			System.out.println(e);
		}
		System.out.println("=====================");
		for (Iterator<String> iterator2 = coll.iterator();iterator2.hasNext(); ) {
			String e = iterator2.next();
			System.out.println(e);
		}
		
		
		
//		//2、使用Iterator接口中的方法hasNext判断还有没有下一个元素
//		boolean b = iterator.hasNext();
//		System.out.println(b); // true
//		//3、使用Iterator接口中的方法next取出集合中的下一个元素
//		String str = iterator.next();
//		System.out.println(str); // 姚明
//		
//		b = iterator.hasNext();
//		System.out.println(b); // true
//		str = iterator.next();
//		System.out.println(str); // 科比
//		
//		b = iterator.hasNext();
//		System.out.println(b); // true
//		str = iterator.next();
//		System.out.println(str); // 乔丹
//		
//		b = iterator.hasNext();
//		System.out.println(b); // true
//		str = iterator.next();
//		System.out.println(str); // 麦迪
//		
//		b = iterator.hasNext();
//		System.out.println(b); // true
//		str = iterator.next();
//		System.out.println(str); // 库里
//		
//		b = iterator.hasNext();
//		System.out.println(b); // 没有元素 返回false
//			str = iterator.next(); // 没有元素,再取出元素
//			System.out.println(str); // 会抛出NoSuchElementException没有元素异常
	}
}

迭代器的实现原理

我们用代码已经完成了Iterator遍历集合的整个过程。当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素。
在这里插入图片描述
在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。

增强for

增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:

for(元素的数据类型  变量 : Collection集合or数组){ 
  	//写操作代码
}

它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。

代码演示:

package study_p232_p237_Collection_Iterator_Foreach;

import java.util.ArrayList;

/*
 	增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写
 	是JDK1.5之后出现的新特性
 	public interface Collection<E> extends Iterable<E>:所有的单列集合都可以使用增强for
 	public interface Iterable<T>	实现这个接口允许对象成为 "foreach" 语句的目标。
	
	增强for循环:用来遍历集合和数组
	
	格式:
		for(集合/数组的数据类型 变量名: 集合名/数组名){
			System.out.println(变量名);
		}
		
tips:新for循环必须有被遍历的目标,目标只能是Collection或者是数组。
		仅仅作为遍历操作出现。
 */
public class Foreach_1 {

	public static void main(String[] args) {
		method1();
		System.out.println("======================");
		method2();
	}

	//使用增强for循环遍历集合
	private static void method2() {
		ArrayList<String> list = new ArrayList<String>();
		list.add("aaa");
		list.add("bbb");
		list.add("ccc");
		list.add("ddd");
		for (String str : list) {
			System.out.println(str);
		}
	}

	//使用增强for循环遍历数组
	private static void method1() {
		int[] array = {1, 2, 3, 4, 5};
		for (int i : array) {
			System.out.println(i);
		}
		
	}
}

1.3 泛型

在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。
先用代码演示:

package study_p238_p243_Generic;

import java.util.ArrayList;
import java.util.Iterator;

public class Generic_1 {

	public static void main(String[] args) {
		show01();
		show02();
	}

	/*
	 	创建集合对象,使用泛型
	 	好处:
	 		1.避免类型转换的麻烦,存储的是什么类型,取出的就是什么类型
	 		2.把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)
	 	弊端:
	 		泛型是什么类型,只能存储什么类型的数据
	 */
	private static void show02() {
		ArrayList<String> list = new ArrayList<String>();
		list.add("abc");
//		list.add(1); // The method add(int, String) in the type ArrayList<String> is not applicable for the arguments (int)
		
		//使用迭代器遍历list集合
		Iterator<String> iterator = list.iterator();
		while (iterator.hasNext()) {
			String str = iterator.next();
			System.out.println(str + "->" + str.length());
		}
	} 

	/*
	 	创建集合对象,不使用泛型
	 	好处:
	 		集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据
	 	弊端:
	 		不安全,会引发异常
	 */
	private static void show01() {
		ArrayList list = new ArrayList();
		list.add("abc");
		list.add(1);
		
		//使用迭代器遍历list集合
		//获取迭代器
		Iterator it = list.iterator();
		//使用迭代器中的方法hasNext和next遍历集合
		while (it.hasNext()) {
			//取出元素也是Object类型
			Object obj = it.next();
			System.out.println(obj);
			
			//想要使用String类特有的方法,length获取字符串的长度,不能使用 多态 Object obj = "abc";
			//需要向下转型
			//会抛出ClassCastException类型转换异常,不能把Integer类型转换为String类型
			//class java.lang.Integer cannot be cast to class java.lang.String
			String str = (String) obj;
			System.out.println(str.length());
		}
	}
}

程序在运行时发生了问题java.lang.ClassCastException
为什么会发生类型转换异常呢?
我们来分析下:由于集合中什么类型的元素都可以存储。导致取出时强转引发运行时 ClassCastException
怎么来解决这个问题呢? Collection集合虽然可以存储各种对象,但实际上通常Collection集合只存储同一类型对象。例如都是存储字符串对象。因此在JDK5之后,新增了泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样我们使用API的时候也变得更为简洁,并得到了编译时期的语法检查。

  • 泛型:可以在类或方法中预支地使用未知的类型。

tips:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

按如下代码演示

package study_p238_p243_Generic;
/*
 	定义一个含有泛型的类,模拟ArrayList集合
 	泛型是一个未知的数据类型,当我们不确定使用什么数据类型的时候,可以使用泛型
 	泛型可以接受任意的数据类型,可以使用Integer,String,Student...
 	创建对象的时候确定泛型的数据类型
 */
public class GenericClass_2<E> {
	private E name;

	public E getName() {
		return name;
	}

	public void setName(E name) {
		this.name = name;
	}
}

主方法如下所示:

package study_p238_p243_Generic;

public class Generic_2 {
	
	public static void main(String[] args) {
		//不写泛型默认为Object类型
		GenericClass_2 gc = new GenericClass_2();
		gc.setName("只能是字符串");
		Object obj = gc.getName();
		
		//创建GenericClass对象,泛型使用Integer类型
		GenericClass_2<Integer> gc2 = new GenericClass_2<Integer>();
		gc2.setName(1);
		
		Integer name = gc2.getName();
		System.out.println(name);
		
		//创建GenericClass对象,泛型使用String类型
		GenericClass_2<String> gc3 = new GenericClass_2<String>();
		gc3.setName("小明");
		String name1 = gc3.getName();
		System.out.println(name1);
	}
}

我们在集合中会大量使用到泛型,这里来完整地学习泛型知识。

泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。

先定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间
格式如下:

 		修饰符 <E> 返回值类型 方法名称(参数列表(使用泛型)){
 			方法体;
 		}

用代码演示:

package study_p238_p243_Generic;
/*	
 	含有泛型的方法,在调用方法的时候确定泛型的数据类型
 	传递什么类型的参数,泛型就是什么类型
 */
public class GenericMethod_3 {
	//定义一个含有泛型的方法
	public <M> void method01(M m) {
		System.out.println(m);
	}
	
	//定义一个含有泛型的静态方法
	public static <S> void method02(S s) {
		System.out.println(s);
	}
}

主方法如下:

package study_p238_p243_Generic;
/*
 	测试含有泛型的方法
 */
public class Generic_3 {

	public static void main(String[] args) {
		//创建GenericMethod对象
		GenericMethod_3 gm = new GenericMethod_3();
		
		/*
		 	调用含有泛型的方法method01
		 	传递什么类型,泛型就是什么类型
		 */
		gm.method01(10);
		gm.method01("abc");
		gm.method01(9.9);
		gm.method01('a');
		gm.method01(true);
		
		gm.method02("静态方法,不建议创建对象使用");
		
		//静态方法:通过类名.方法名(参数)可以直接使用
		GenericMethod_3.method02("静态方法");
		GenericMethod_3.method02(123);
	}
}

定义含有泛型的接口,代码演示:
先定义一个接口:

package study_p238_p243_Generic;

public interface GenericInterface_4<I> {

	public abstract void method(I i);
}

创建接口的实现类1:

package study_p238_p243_Generic;
/*
 	含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型
 	public interface Iterator<E> {
 		E.next();
 	}
 	Scanner类实现类Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默认就是String
 	public final class Scanner implements Iterator<String>{
 		public String next() {}
 	}
 */
public class GenericInterfaceImpl1_4 implements GenericInterface_4<String> {

	@Override
	public void method(String s) {
		System.out.println(s);
	}
}

创建接口的实现类2:

package study_p238_p243_Generic;
/*
 	含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就是用什么泛型,类跟着接口邹
 	就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型
 	public interface List<E>{
 		boolean add(E e);
 		E get (int index);
 	}
 	
 	public calss ArrayList<E> implements List<E>{
 		public boolean add(E e) {}
 		public E get (int index) {}
 	}
 */
public class GenericInterfaceImpl2_4<I> implements GenericInterface_4<I> {

	@Override
	public void method(I i) {
		System.out.println(i);
	}
}

创建主方法:

package study_p238_p243_Generic;

public class GenericInterfaceMain_4 {

	public static void main(String[] args) {
		//创建GenericInterfaceImpl1_4对象
		GenericInterfaceImpl1_4 gi1 = new GenericInterfaceImpl1_4();
		gi1.method("字符串");
		
		//创建GenericInterfaceImpl2_4对象
		GenericInterfaceImpl2_4<Integer>  gi2 = new GenericInterfaceImpl2_4<Integer>();
		gi2.method(10);
		
		GenericInterfaceImpl2_4<Double> gi3 = new GenericInterfaceImpl2_4<Double>();
		gi3.method(8.3);
	}
}

泛型通配符

当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。

通配符基本使用
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

此时只能接受数据,不能往该集合中存储数据。
用代码演示如下:

package study_p238_p243_Generic;

import java.util.ArrayList;
import java.util.Iterator;

/*
 	泛型的通配符:
 		?:代表任意的数据类型
 	使用方式:
 		不能创建对象使用
 		只能作为方法的参数使用
 */
public class Generic_E1_5 {

	public static void main(String[] args) {
		ArrayList<Integer> list01 = new ArrayList<Integer>();
		list01.add(1);
		list01.add(2);
		
		ArrayList<String> list02 = new ArrayList<String>();
		list02.add("a");
		list02.add("b");
		
		printArray(list01);
		printArray(list02);
		
//		ArrayList<?> list03 = new ArrayList<?>(); 不能作为对象使用
	}
	
	/*
	 	定义一个方法,能遍历所有类型的ArrayList集合
	 	这时候我们不知道ArrayList集合使用什么数据类型,可以泛型的通配符?来接收数据类型
	 	注意:
	 		泛型没有继承概念的
	 */
	public static void printArray(ArrayList<?> list) {
		//使用迭代器遍历集合
		Iterator<?> iterator = list.iterator();
		while (iterator.hasNext()) {
			//it.next()方法,取出的元素是Object,可以接收任意的数据类型
			Object obj = iterator.next();
			System.out.println(obj);
		}
	}
	
}

tips:泛型不存在继承关系 Collection list = new ArrayList();这种是错误的。

通配符高级使用----受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限下限

泛型的上限

  • 格式类型名称 <? extends 类 > 对象名称
  • 意义只能接收该类型及其子类

泛型的下限

  • 格式类型名称 <? super 类 > 对象名称
  • 意义只能接收该类型及其父类型

比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类
代码演示如下:

package study_p238_p243_Generic;

import java.util.ArrayList;
import java.util.Collection;

/*
 	泛型的上限限定: ? extends E	代表使用的泛型只能是E类型的子类/本身
 	泛型的下线限定: ? super E	代表使用的泛型只能是E类型的父类/本身
 */
public class Generic_E2_5 {
	
	public static void main(String[] args) {
	    Collection<Integer> list1 = new ArrayList<Integer>();
	    Collection<String> list2 = new ArrayList<String>();
	    Collection<Number> list3 = new ArrayList<Number>();
	    Collection<Object> list4 = new ArrayList<Object>();
	    
	    getElement1(list1);
//	    getElement1(list2);//报错
	    getElement1(list3);
//	    getElement1(list4);//报错
	  
//	    getElement2(list1);//报错
//	    getElement2(list2);//报错
	    getElement2(list3);
	    getElement2(list4);
	    
	    /*
	     	类与类之间的继承关系
	     	Integer extends Number extends Object
	     	String extends Object
	     */
	    
	}
	// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
	public static void getElement1(Collection<? extends Number> coll){}
	// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
	public static void getElement2(Collection<? super Number> coll){}
}

2.List集合

掌握了Collection接口的使用后,再来看看Collection接口中的子类,他们都具备那些特性呢?

接下来,一起学习Collection中的常用几个子类(java.util.List集合、java.util.Set集合)。

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

看完API,我们总结一下:

List接口特点:

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

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):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
    代码演示如下:
package study_p251_p264_List_Set_Collections_VarArgs;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*
 	java.util.List接口 extends Collection接口
 	List接口的特点:
 		1.有序的集合,存储元素和取出元素的顺序是一致的(存储123 取出123)
 		2.有索引,包含了一些带索引的方法
 		3.允许存储重复的元素

  注意:
  	操作索引的时候,一定要防止索引越界异常
  	IndexOutOfBoundsException: 索引越界异常,集合会报
  	ArrayIndexOutOfBoundsException: 数组索引越界异常
  	StringIndexOutOfBoundsException: 字符串索引越界异常
 */
public class List_1 {

	public static void main(String[] args) {
		//创建一个List集合对象,多态
		List<String> list = new ArrayList<String>();
		//使用add方法往集合中添加元素
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		list.add("a");
		//打印集合
		System.out.println(list); // [a, b, c, d, a]	不是地址值 重写toString
		
		//public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
		//在c和d之间添加一个小明
		list.add(3, "小明");
		System.out.println(list); // [a, b, c, 小明, d, a]
		
		//public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
		//移除c元素
		String removeE = list.remove(2);
		System.out.println("被移除的元素:" + removeE); // 被移除的元素:c
		System.out.println(list); // [a, b, 小明, d, a]
		
		//public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
		//把最后一个a,替换成A
		String setE = list.set(4, "A");
		System.out.println("被替换的元素:" + setE); // 被替换的元素:a
		System.out.println(list); // [a, b, 小明, d, A]
		
		//List集合遍历有三种方式
		//使用普通的for循环
		for (int i = 0; i < list.size(); i++) {
			//public E get(int index) :返回集合中指定位置的元素。
			System.out.println(list.get(i));
		}
		System.out.println("==============");
		//原始迭代器
		Iterator<String> iterator = list.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		System.out.println("==============");
		//使用foreach
		for (String str : list) {
			System.out.println(str);
		}
		
//		String str = list.get(999); // IndexOutOfBoundsException: Index 999 out of bounds for length 5
//		System.out.println(str); // 索引越界异常
		
	}
}

2.1 List的子类

2.1.1 ArrayList集合

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

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

ArrayList集合的特点

  • ArrayList 底层是通过维护了一个Object数组实现的,特点是查询速度快,增加删除慢 ArrayList
  • 使用无参构造函数创建对象时,Object数组默认的容量是10,当长度不够时,自动增长0.5倍,也就是原来数组长度的1.5倍
  • 当数据需要频繁的查询,而增加删除较少的时候,建议使用ArrayList数组存储数据。

2.2.2 LinkedList集合

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

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都是可以使用,这里就不做详细介绍,我们只需要了解LinkedList的特有方法即可。在开发时,LinkedList集合也可以作为堆栈,队列的结构使用。(了解即可)
代码演示如下:

package study_p251_p264_List_Set_Collections_VarArgs;

import java.util.LinkedList;

/*
 	java.util.linkedList集合 implements List接口
 	LinkedList集合的特点:
 		1.底层是一个链表结构:查询慢,增删快
 		2.里边包含了大量操作首尾元素的方法
 		注意:使用LinkedList集合特有的方法,不能使用多态
 		
 		public void addFirst(E e) :将指定元素插入此列表的开头。
 		public void addLast(E e) :将指定元素添加到此列表的结尾。
 		public void push(E e) :将元素推入此列表所表示的堆栈。
 		
 		public E getFirst() :返回此列表的第一个元素。
 		public E getLast() :返回此列表的最后一个元素。
 		
 		public E removeFirst() :移除并返回此列表的第一个元素。
 		public E removeLast() :移除并返回此列表的最后一个元素。
 		public E pop() :从此列表所表示的堆栈处弹出一个元素。
 		
 		public boolean isEmpty() :如果列表不包含元素,则返回true。
 */
public class LinkedList_1 {

	public static void main(String[] args) {
		method01();
		System.out.println("=====================");
		method02();
		System.out.println("=====================");
		method03();
	}

	/*
	 	public E removeFirst() :移除并返回此列表的第一个元素。
 		public E removeLast() :移除并返回此列表的最后一个元素。
 		public E pop() :从此列表所表示的堆栈处弹出一个元素。 等效于removeFirst
	 */
	private static void method03() {
		//创建LinkedList集合对象
		LinkedList<String> linkedList = new LinkedList<String>();
		//使用add方法往集合中添加元素
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		
//		System.out.println("被移除的第一个元素:" + linkedList.removeFirst());
		System.out.println("被移除的第一个元素:" + linkedList.pop());
		System.out.println("被移除的最后一个元素:" + linkedList.removeLast());
		System.out.println(linkedList);
		
	}

	/*
	 	public E getFirst() :返回此列表的第一个元素。
 		public E getLast() :返回此列表的最后一个元素。
	 */
	private static void method02() {
		//创建LinkedList集合对象
		LinkedList<String> linkedList = new LinkedList<String>();
		//使用add方法往集合中添加元素
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		
		linkedList.clear(); // 再获取元素抛出异常NoSuchElementException
		//public boolean isEmpty() :如果列表不包含元素,则返回true。
		if (!linkedList.isEmpty()) {
			System.out.println(linkedList.getFirst());
			System.out.println(linkedList.getLast());
		}
	}

	/*
	 	public void addFirst(E e) :将指定元素插入此列表的开头。
 		public void addLast(E e) :将指定元素添加到此列表的结尾。
 		public void push(E e) :将元素推入此列表所表示的堆栈。
	 */
	private static void method01() {
		//创建LinkedList集合对象
		LinkedList<String> linkedList = new LinkedList<String>();
		//使用add方法往集合中添加元素
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		System.out.println(linkedList); // [a, b, c]
		
		//public void addFirst(E e) :将指定元素插入此列表的开头。
		//public void push(E e) :将元素推入此列表所表示的堆栈。 等效于addFirst()
//		linkedList.addFirst("www");
		linkedList.push("www");
		System.out.println(linkedList); // [www, a, b, c]
		
		//public void addLast(E e) :将指定元素添加到此列表的结尾。 等效于add()
		linkedList.addLast("com");
		System.out.println(linkedList); // [www, a, b, c, com]
	}
}

3.1 Set接口

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

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

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

HashSet集合介绍
java.util.HashSetSet接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap支持,由于我们暂时还未学习,先做了解。

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCodeequals方法。

用代码演示:

package study_p251_p264_List_Set_Collections_VarArgs;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/*
 	java.util.Set接口 extends Collection接口
 	Set接口的特点:
 		1.不允许存储重复的元素
 		2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
 	java.util.HashSet集合 implements Set接口
 	HashSet特点:
 		1.不允许存储重复的元素
 		2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
 		3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
 		4.底层是一个哈希表结构(查询速度快)
 */
public class Set_1 {

	public static void main(String[] args) {
		Set<Integer> set = new HashSet<Integer>();
		//使用add方法往集合中添加元素
		set.add(1);
		set.add(3);
		set.add(2);
		set.add(1);
		//使用迭代器遍历set集合
		Iterator<Integer> iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next()); //1, 2, 3
		}
		//使用增强for遍历set集合
		System.out.println("============================");
		for (Integer integer : set) {
			System.out.println(integer);
		}
	}
}

tips:根据结果我们发现只存储了一个1,也就是说重复的元素set集合不存储。

3.2 哈希表

什么是哈希表呢?

JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示。
在这里插入图片描述
总而言之,JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一。
创建一个Person类:

package study_p251_p264_List_Set_Collections_VarArgs;

public class HashCode_Person_2 extends Object {

	//重写hashCode方法
	@Override
	public int hashCode() {
		return 1;
	}
}

主方法的实现:

package study_p251_p264_List_Set_Collections_VarArgs;
/*
 	哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来的地址,不是数据实际存储的物理地址)
 	在Object类有一个方法,可以获取对象的哈希值
 	int hashCode():返回该对象的哈希码值。
 	hashCode方法的源码:
 		public native int hashCode();
 		native:代表该方法调用的是本地操作系统的方法
 */
public class HashCode_2 {
	public static void main(String[] args) {
		//Person类继承了Object类,所以可以使用Object类的hashCode方法
		HashCode_Person_2 person = new HashCode_Person_2();
		System.out.println(person.hashCode()); // 1389133897  | 1
		HashCode_Person_2 person1 = new HashCode_Person_2();
		System.out.println(person1.hashCode()); // 1534030866	| 1
		/*
		 	toString方法的源码:
		 public String toString() {
        	return getClass().getName() + "@" + Integer.toHexString(hashCode());
    	 }
		 */
		// 16进制
		System.out.println(person); //  study_p251_p.HashCode_Person_1@52cc8049	| 1
		System.out.println(person1); // study_p251_p.HashCode_Person_1@5b6f7412	| 1
		System.out.println(person == person1); // false 实际物理地址不相等
		
		/*
		 	String类的哈希值
		 		String类重写了Object类的hashCode方法
		 */
		String s1 = new String("abc");
		String s2 = new String("abc");
		System.out.println(s1.equals(s2)); // true
		System.out.println(s1.hashCode()); // 96354
		System.out.println(s2.hashCode()); // 96354
		System.out.println(s1 == s2); // false
		
		System.out.println("重地".hashCode()); // 1179395
		System.out.println("通话".hashCode()); // 1179395
	}
}

3.3 LinkedHashSet

我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?

在HashSet下面有一个子类java.util.LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。

用代码演示如下:

代码分析

set集合不允许存储重复元素的原理

Set集合在调用add方法的时候,add方法会调用元素的hashCode方法和equals方法,判断元素是否重复
set.add(s1);
add方法会调用s1的hashCode方法,计算字符串"abc"的哈希值,哈希值是【96354】
在集合中找有没有【96354】这个哈希值的元素,发现【没有】
【就会把s1存储到集合中】

set.add(s2);
add方法会调用s2的hashCode方法,计算字符串"abc"的哈希值,哈希值是【96354】
在集合中找有没有【96354】这个哈希值的元素,发现【有】(哈希冲突)
s2会调用equals方法和哈希值相同的元素进行比较 s2.equals(s1) 返回true
两个元素的哈希值相同 equals方法返回true,认定【两个元素相同】
【就不会把s2存储到集合中】

set.add("重地");
add方法会调用"重地"的hashCode方法,计算字符串"重地"的哈希值,哈希值是【1179395】
在集合中找有没有【1179395】这个哈希值的元素,发现【没有】
【就会把"重地"存储到集合中】

set.add("通话");
add方法会调用"通话"的hashCode方法,计算字符串"通话"的哈希值,哈希值是【1179395】
在集合中找有没有【1179395】这个哈希值的元素,发现【有】(哈希冲突)
"通话"会调用equals方法和哈希值相同的元素进行比较 "通话".equals("重地") 返回false
两个元素的哈希值相同 equals方法返回false,认定【两个元素不同】
【就会把"通话"存储到集合中】

set集合存储不重复的元素的前提:存储的元素必须重写hashCode()方法和equals()方法

package study_p251_p264_List_Set_Collections_VarArgs;

import java.util.HashSet;

/*
 	HashSet集合存储数据的结构(【哈希表】)
	jdk1.8版本之前:哈希表 = 数组 + 链表
	jdk1.8版本之后:哈希表 = 数组 + 链表;
	        	    哈希表 = 数组 + 红黑树(提高查询的速度)
	0		1		2		3		4
	xxx  |96354 |  xxx	|  xxx	|  1179395	......
			|						|
		  "abc"					  "重地"
									|
								  "通话"
 * 
 * set集合存储不重复的元素
 * 		前提:存储的元素必须重写hashCode()方法和equals()方法	
 */
public class HashSetSaveString_3 {

	public static void main(String[] args) {
		//创建HashSet集合对象
		HashSet<String> set = new HashSet<String>();
		String s1 = new String("abc");
		String s2 = new String("abc");
		set.add(s1);
		set.add(s2);
		set.add("重地");
		set.add("通话");
		set.add("abc");
		System.out.println(set); // [重地, 通话, abc]
	}
}

讨论HashSet存储自定义类型元素
代码如下演示:
先创建Person类:

package study_p251_p264_List_Set_Collections_VarArgs;

public class HashSetPerson_4 {
	private String name;
	private int age;
	
	public HashSetPerson_4() {
		
	}
	
	public HashSetPerson_4(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		HashSetPerson_4 other = (HashSetPerson_4) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "HashSetPerson_4 [name=" + name + ", 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;
	}
	
	
}

主方法的实现:

package study_p251_p264_List_Set_Collections_VarArgs;

import java.util.HashSet;

/*
 	HashSet存储自定义类型元素
 	
 	set集合保证元素唯一:
 		存储的元素(String,Integer,...Student,Person...),必须重写hashCode()方法和equals()方法
 		
 	要求:
 		同名同年龄的人,视为同一个人,只能存储一次
 */
public class HashSetSavePerson_4 {
	
	public static void main(String[] args) {
		//创建HashSet集合存储Person
		HashSet<HashSetPerson_4> hashSet = new HashSet<HashSetPerson_4>();
		HashSetPerson_4 person1 = new HashSetPerson_4("小明",18);
		HashSetPerson_4 person2 = new HashSetPerson_4("小明",18);
		HashSetPerson_4 person3 = new HashSetPerson_4("小明",19);
		System.out.println(person1.hashCode()); // 1389133897 | 758222
		System.out.println(person2.hashCode()); // 1534030866 | 758222
		System.out.println(person1 == person2); //false
		System.out.println(person1.equals(person2)); // false | true
		hashSet.add(person1);
		hashSet.add(person2);
		hashSet.add(person3);
		System.out.println(hashSet);
	}
	
}

3.4 可变参数

JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格式:

修饰符 返回值类型 方法名(参数类型... 形参名){  }

其实这个书写完全等价与

修饰符 返回值类型 方法名(参数类型[] 形参名){  }

只是后面这种定义,在调用时必须传递数组,而前者可以直接传递数据即可。

JDK1.5以后。出现了简化操作。 用在参数上,称之为可变参数。

同样是代表数组,但是在调用这个带有可变参数的方法时,不用创建数组(这就是简单之处),直接将数组中的元素作为实际参数进行传递,其实编译成的class文件,将这些元素先封装到一个数组中,在进行传递。这些动作都在编译.class文件时,自动完成了。

代码演示:

package study_p251_p264_List_Set_Collections_VarArgs;
/*
 	可变参数:是JDK1.5之后出现的新特性
 	使用前提:
 		当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数。
 	使用格式:定义方法时使用
 		修饰符 返回值类型 方法名(数据类型...变量名) {}
 	可变参数的原理:
 		可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的的数组来存储这些参数
 		传递的参数个数,可以是0个(不传递),1,2,...多个
 */
public class VarArgs_1 {

	public static void main(String args) {
//		int i = add();
//		int i = add(10);
//		int i = add(10, 20);
		int i = add(10, 20, 30, 40 ,50 ,60 ,70 ,80 ,90 ,100);
		System.out.println(i);
		
		method("abc", 5.5, 1, 2, 3, 4);
	}
	
	/*
	 	可变参数的注意事项
	 		1.一个方法的参数列表,只能有一个可变参数
	 		2.如果方法的参数有多个,那么可变参数必须写在参数的末尾
	 */
//	public static void method(int...array,String...strings) {}
	public static void method(String b, Double d, int...array) {}
	
	//可变参数的特殊(终极)写法
	public static void method1(Object...objects) {
		
	}
	
	/*
	 	定义计算(0-n)整数和的方法
	 	已知:计算整数的和,数据类型已经确定int
	 	但是参数的个数不确定,不知道计算几个整数的和,就可以使用可变参数
	 	add(); 就会创建一个长度为0的数组,new int[0]
	 	System.out.println(array); // [I@34c45dca
	 	System.out.println(array.length); // 0
	 	
	 	add(10); 就会创建一个长度为1的数组,存储传递过来的参数 new int[1] {10};
	 	add(10, 20); 就会创建一个长度为2的数组,存储传递过来的参数 new int[2] {10, 20};
	 	add(10, 20, 30, 40 ,50 ,60 ,70 ,80 ,90 ,100); 就会创建一个长度为10的数组,存储传递过来的参数 new int[10] {10, 20, 30, 40 ,50 ,60 ,70 ,80 ,90 ,100};
	 */
	public static int add(int...array) {
		System.out.println(array); // [I@34c45dca	底层是一个数组
		System.out.println(array.length); // 0,1,2,10
		//定义一个初始化的变量,记录累加求和
		int sum = 0;
		//遍历数组,获取数组中的每一个元素
		for (int i = 0; i < array.length; i++) {
			//累加求和
			sum += array[i];
		}
		return sum;
	}
	
	
//	//定义一个方法,计算三个int类型整数的和
//	public static int add (int a, int b, int c) {
//		return a + b + c;
//	}
//	//定义一个方法,计算两个int类型整数的和
//	public static int add (int a, int b) {
//		return a + b;
//	}
}

4.1 Collections

  • 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 static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
  • public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。

============================================================================

  • public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
    注意: sort(List list)使用前提
    被排序的集合里面存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序的规则

Comparable接口的排序规则:
自己(this) - 参数: 升序

============================================================================

  • public static <T> void sort(List<T> list,Comparator<? super T> ) :将集合中元素按照指定规则排 序。
    Comparator和Comparable的区别
    Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较的规则

  • 强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,

  • 类的compareTo方法 被称为它的自然比较方法。

  • 只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。

  • 实现 此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,

  • 对象可以用作有序映射中 的键或有序集合中的元素,无需指定比较器。

Comparator:相当于找一个第三方的裁判,比较两个

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

Comparator的排序规则:
o1 - o2:升序

package study_p251_p264_List_Set_Collections_VarArgs;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Collections_1 {

	public static <T> void main(String[] args) {
		ArrayList<String> list = new ArrayList<String>();
		//往集合中添加多个元素
//		list.add("a");
//		list.add("b");
//		list.add("c");
//		list.add("d");
//		list.add("e");
		//public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。
		Collections.addAll(list, "a", "b", "c", "d", "e");
		
		System.out.println(list);
		
		//public static void shuffle(List<?> list) 打乱顺序 :打乱集合顺序。
		Collections.shuffle(list);
		System.out.println(list);
		
		System.out.println("=====================================");
		ArrayList<Integer> list2 = new ArrayList<Integer>();
		Collections.addAll(list2, 1, 3, 2);
		System.out.println(list2); // [1, 3, 2]
		
		//public static <T> void sort(List<T> list) :将集合中元素按照默认规则排序。
		Collections.sort(list2); // 默认是升序
		System.out.println(list2); // [1, 2, 3]
		
		ArrayList<String> list3 = new ArrayList<String>();
		Collections.addAll(list3, "a", "c", "b");
		System.out.println(list3); // [a, c, b]
		Collections.sort(list3);
		System.out.println(list3); // [a, b, c]
		
		ArrayList<Collections_Person_1> list4 = new ArrayList<Collections_Person_1>();
		list4.add(new Collections_Person_1("张三", 18));
		list4.add(new Collections_Person_1("李四", 20));
		list4.add(new Collections_Person_1("王五", 15));
		System.out.println(list4); // [Collections_Person_1 [name=张三, age=18], Collections_Person_1 [name=李四, age=20], Collections_Person_1 [name=王五, age=15]]
		
		Collections.sort(list4);
		System.out.println(list4); // [Collections_Person_1 [name=王五, age=15], Collections_Person_1 [name=张三, age=18], Collections_Person_1 [name=李四, age=20]]
		
		System.out.println("=====================================");
		ArrayList<Integer> list5 = new ArrayList<Integer>();
		list5.add(1);
		list5.add(3);
		list5.add(2);
		System.out.println(list5); // [1, 3, 2]
		
		Collections.sort(list5, new Comparator<Integer>() {
			//重写比较的规则
			@Override
			public int compare(Integer o1, Integer o2) {
				// TODO Auto-generated method stub
				return o1 - o2; // 升序
//				return o2 - o1; // 降序
			}
		});
		System.out.println(list5); // [1, 2, 3]
		
		ArrayList<Collections_Student_1> list6 = new ArrayList<Collections_Student_1>();
		list6.add(new Collections_Student_1("a小明",18));
		list6.add(new Collections_Student_1("小王",20));
		list6.add(new Collections_Student_1("小陈",17));
		list6.add(new Collections_Student_1("b小陈",18));
		
		/*
		 * Collections.sort(list6, new Comparator<Collections_Student_1>() {
		 * 
		 * @Override 
		 * public int compare(Collections_Student_1 o1, Collections_Student_1 o2) {
		 * //按照年龄升序排序 return o1.getAge() - o2.getAge(); } });
		 */
		//扩展:了解
		Collections.sort(list6, new Comparator<Collections_Student_1>() {

			@Override
			public int compare(Collections_Student_1 o1, Collections_Student_1 o2) {
				//按照年龄升序排序
				int result = o1.getAge() - o2.getAge();
				//如果两个人年龄相同,再使用姓名的第一个字比较
				if (result == 0) {
					result = o1.getName().charAt(0) - o2.getName().charAt(0);
				}
				return result;
			}
		});
		System.out.println(list6);
	}
}

关于集合先简单介绍的这里,这也是我学完整理的笔记。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

舍其小伙伴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值