一、List接口
List是Collection下面的一个子接口。
1、 List满足3个特点:
1. 有序(有序不是顺序, 有序指的是怎么存,就怎么取)
2. 有索引(可以根据索引获取元素)
3. 可以重复(List下面的集合可以存放重复的元素)
List是一个接口,如果要用,需要使用实现类,最常用的实现类是ArrayList。
public class Demo01List {
public static void main(String[] args) {
//创建一个List集合对象
List<String> list = new ArrayList<>();
//向集合中添加元素
list.add("张三");
list.add("李四");
list.add("王叔叔");
//打印集合
//1. 有序
System.out.println(list);
//2. 有索引
String value = list.get(1);
System.out.println(value);
//3. 可以重复
list.add("王叔叔");
System.out.println(list);
}
}
2、list集合中的方法
List是Collection的子接口,所以List接口除了拥有Collection中所有的方法外,还有一些自己的方 法, 这些自己的方法支持对索引的操作。
常见方法:
void add(int index, E element): 向集合的指定位置添加元素。
(重要)E get(int index):根据索引获取元素
E remove(int index): 根据索引删除元素。 返回被删除的元素.
E set(int index, E element): 替换指定索引位置的元素。
public class Demo02ListMethod {
public static void main(String[] args) {
method4();
}
//E set(int index, E element): 替换指定索引位置的元素。 返回值为被替换的元素
public static void method4() {
//创建一个集合
List<String> list = new ArrayList<>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
//使用php替换掉集合中索引为2的元素
String str = list.set(2, "php");
System.out.println("list:" + list);
System.out.println("str:" + str);
}
//E remove(int index): 根据索引删除元素。 返回被删除的元素.
public static void method3() {
//创建一个集合
List<String> list = new ArrayList<>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
//删除索引为1的元素
String str = list.remove(1);
System.out.println("list:" + list); //[hello, java]
System.out.println("str:" + str); //world
}
//E get(int index):根据索引获取元素
public static void method2() {
//创建一个集合
List<String> list = new ArrayList<>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
//根据索引获取元素
System.out.println(list.get(1));
}
//void add(int index, E element): 向集合的指定位置添加元素。
public static void method1() {
//创建一个List集合
List<String> list = new ArrayList<>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
System.out.println("list:" + list); //[hello, world, java]
//在索引为1的位置添加元素 php
list.add(1, "php");
System.out.println("list:" + list); //[hello, php, world, java]
}
}
3、ArrayList集合及其特点
(1)ArrayList集合的特点。
ArrayList是List接口的一个实现类,并且这个集合内部在使用数组这种数据结构去存储数据。
ArrayList的特点是: 增删慢, 查询
(2)LinkedList集合
LinkedList集合也是List接口的实现类。
LinkedList内部是一个链表(双向链表)
LinkedList 的特点: 增删快,查找慢
LinkedList中有一些【特有】的方法, 支持对首尾进行操作。
void addFirst(E e): 向集合的首个位置添加元素
void addLast·(E e):向集合尾部添加元素
E getFirst(): 获取集合首个位置的元素
E getLast():获取集合尾部的元素
E removeFirst():删除首个元素。 返回被删除的元素
E removeLast():删除最后一个元素。 返回被删除的元素
void push(E e): 压入, 向首个位置添加元素
E pop(): 弹出,移除第一个元素。
public class Demo02LinkedList {
public static void main(String[] args) {
method4();
}
/*
void push(E e): 压入, 向首个位置添加元素
E pop(): 弹出,移除第一个元素。
*/
public static void method4() {
//创建一个集合并添加元素
LinkedList<String> list = new LinkedList<>();
list.add("爱迪生");
list.add("达尔文");
list.add("达芬奇");
System.out.println("list:" + list); //[爱迪生, 达尔文, 达芬奇]
//void push(E e): 压入, 向首个位置添加元素
list.push("牛顿");
System.out.println("list:" + list); //[牛顿, 爱迪生, 达尔文, 达芬奇]
//E pop(): 弹出,移除第一个元素。
String str = list.pop();
System.out.println("list:" + list); //[爱迪生, 达尔文, 达芬奇]
System.out.println("str:" + str); //牛顿
}
/*
E removeFirst():删除首个元素
E removeLast():删除最后一个元素。
*/
public static void method3() {
//创建一个集合并添加元素
LinkedList<String> list = new LinkedList<>();
list.add("爱迪生");
list.add("达尔文");
list.add("达芬奇");
System.out.println("list:" + list); //[爱迪生, 达尔文, 达芬奇]
//调用 removeFirst() 删除首个元素
//String str = list.removeFirst();
//删除尾部元素
String str = list.removeLast();
System.out.println("删除后:" + list); //[爱迪生, 达尔文]
System.out.println("str:" + str); //达芬奇
}
/*
E getFirst(): 获取集合首个位置的元素
E getLast():获取集合尾部的元素
*/
public static void method2() {
//创建一个集合并添加元素
LinkedList<String> list = new LinkedList<>();
list.add("爱迪生");
list.add("达尔文");
list.add("达芬奇");
//获取集合中首个位置的元素并打印
System.out.println("首个元素:" + list.getFirst()); //爱迪生
//获取集合中首个位置的元素并打印
System.out.println("尾部元素:" + list.getLast()); //达芬奇
}
/*
void addFirst(E e): 向集合的首个位置添加元素
void addLast(E e):向集合尾部添加元素
*/
public static void method1() {
//创建一个集合
LinkedList<String> list = new LinkedList<>();
list.add("爱迪生");
list.add("达尔文");
list.add("达芬奇");
//打印list集合
System.out.println("list:" + list); //[爱迪生, 达尔文, 达芬奇]
//void addFirst(E e): 向集合的首个位置添加元素
list.addFirst("牛顿");
System.out.println("list:" + list); //[牛顿, 爱迪生, 达尔文, 达芬奇]
list.addLast("伽利略");
System.out.println("list:" + list); //[牛顿, 爱迪生, 达尔文, 达芬奇, 伽利略]
}
}
二、Set接口
1、Set 也是Collection下面的一个子接口。
Set接口满足一下三个特点:
1. 无序(怎么存,不一定怎么取)
2. 没有索引(不能根据索引获取元素)
3. 不可重复.
Set是一个接口,如果要用,需要使用实现类,最常用的实现类是HashSet
public class Demo01Set {
public static void main(String[] args) {
//创建一个Set集合
Set<String> set = new HashSet<>();
//向集合中添加元素
set.add("张三");
set.add("李四");
set.add("王叔叔");
//打印Set集合
//1. 无序(怎么存,不一定怎么取)
System.out.println(set); //[李四, 张三, 王叔叔]
//2. 没有索引(不能根据索引获取元素)
//set.get(1);
//3. 不可重复.
set.add("王叔叔");
set.add("王叔叔");
set.add("王叔叔");
set.add("王叔叔");
System.out.println(set);
}
}
2、Hashset接口
HashSet是Set接口下的实现类,它满足Set接口的所有特点。
1. 无序
2. 无索引
3. 不可重复
如何对Set集合进行遍历?
1. 迭代器
2. 增强for(推荐)
public class Demo02HashSet {
public static void main(String[] args) {
//创建一个Set集合,并遍历
Set<String> set = new HashSet<>();
//往集合中添加元素
set.add("张三丰");
set.add("宋远桥");
set.add("尹丽婷");
set.add("张翠山");
//使用迭代器遍历这个Set集合.
//获取集合的迭代器
Iterator<String> iterator = set.iterator();
//循环获取
while (iterator.hasNext()) {
String value = iterator.next();
System.out.println(value);
}
System.out.println("---------------------------------");
for(String str : set) {
System.out.println(str);
}
}
}
3、HashCode
1、哈希值
哈希值其实就是一个int数字, 我们可以把哈希值看成对象的一个标识,特征码。
在Object中,有一个方法,叫做hashCode,可以获取到对象的哈希值。
Object中的hashCode方法,哈希值是根据地址值进行计算的。
一般来说哈希值的计算方式不会根据地址值进行计算,而是根据对象的属性进行计算。
如果两个对象的属性完全相同,那么这两个对象的哈希值也应该相同。
如果想要自己定义哈希值的计算方式,那么我们需要在子类中重写hashCode方法。
哈希值是对象的一个特征码,但是哈希值并不是唯一的特征码, 对象的哈希值是允许重复的。
总结:
1. 哈希值就是对象的特征码
2. 我们可以通过hashCode方法来获取对象的哈希值
3. 如果希望自己定义哈希值的生成规则,那么我们可以在子类中重写hashCode方法。
4. 哈希值的计算方式一般是根据属性计算,属性相同得到的哈希值也一定相同。
public class Demo01HashCode {
public static void main(String[] args) {
//创建一个Person对象
Person p = new Person("刘德华", 18);
System.out.println(p.hashCode());
System.out.println(new Person("刘德华", 18).hashCode());
System.out.println(new Person("刘德华", 18).hashCode());
System.out.println(new Person("刘德华", 19).hashCode());
System.out.println(new Person("刘德华", 19).hashCode());
System.out.println(new Person("刘德华", 19).hashCode());
System.out.println("刘德华".hashCode()); //20977295
}
}
2、使用HashSet存储自定义对象,并且要保证元素的唯一性。
如果两个对象的属性完全相同,那么就当成是同一个对象。
HashSet如何判断唯一性?
1. 先比较两个对象的哈希值(通过hashCode方法得到哈希值比较)
如果两个对象的哈希值不同,那么肯定是不同的对象。
如果两个对象的哈希值相同,那么不一定是同一个对象。
2. 如果两个对象的哈希值相同,还要调用equals方法进行比较。
如果equals得到的结果是true,表示这两个对象是同一个对象
如果equals方法的到的结果是false,表示这两个对象不是同一个对象。
总结: 如果使用HashSet保存自定义对象看,那么如果要保证唯一性(如果属性完全相同,那么就是同一个对象)
此时需要重写hashCode和equals
public class Demo02HashSet {
public static void main(String[] args) {
//创建一个HashSet,用来保存Dog对象
Set<Dog> set = new HashSet<>();
//向set集合中添加一些狗对象
set.add(new Dog("哮天犬", 18));
set.add(new Dog("旺财", 8));
set.add(new Dog("王可可", 3));
//添加一个狗对象
set.add(new Dog("旺财", 8));
//遍历set集合,并打印每一个狗对象
for(Dog dog : set) {
System.out.println(dog);
}
}
}
3、LinkedHashSet是Set接口的一个实现类。
内部除了有一个哈希表之外还有一个链表。
链表的作用是保证有序、
Set是无序的,但是它不能保证所有的实现类都是无序的。
LinkedHashSet就是有序的。
public class Demo03LinkedHashSet {
public static void main(String[] args) {
//创建一个Set集合
Set<String> set = new LinkedHashSet<>();
//添加元素
set.add("张三丰");
set.add("张翠山");
set.add("莫声谷");
set.add("张无忌");
set.add("宋远桥");
//打印set集合
System.out.println(set);
}
}
三、可变参数
可变参数: 指的是方法参数的个数可以随意改变。
格式:
修饰符 返回值类型 方法名(参数类型... 参数名) {
方法体
}
a. 可变参数方法在调用的时候,参数可以传递任意个。
b. 这些参数的数据类型必须要一致
c. 可变参数本质是数组,所以可以依照数组的形式使用这个可变参数。 在调用可变参数的方法时,可变参数位置也可以传递数组。
注意事项:
1. 一个方法中最多只能有1个可变参数。
2. 可变参数必须在方法的最后一个位置
3. 可变参数本质是数组,所以不能和数组构成重载
public class Demo01Params {
public static void main(String[] args) {
//求数字 1 2 3 4 5 的和
int[] arr = {1,2,3,4,5};
//调用getSum方法,将数组进行传递
//int sum = getSum(arr);
//可变参数方法在调用的时候,参数可以传递任意个。(0个, 1个或者多个)
int sum = getSum(1, 2, 3, 4, 5, 6, 7, 8);
System.out.println("sum:" + sum);
}
/*
public static void method(int[] a) {
}
public static void method(int... a) {
}
*/
/*
定义方法,求任意个数字的和
*/
public static int getSum(int... arr) { // 可变参数本质是数组,所以可以按照数组的方式去使用。
int sum = 0;
for(int num : arr) {
sum += num;
}
return sum;
}
/*
定义方法,求任意个数字的和
*/
/*
public static int getSum(int[] arr) {
//对参数数组进行求和
int sum = 0;
for(int num : arr) {
sum += num;
}
return sum;
}
*/
}
四、Collections工具类
-
Collection 是所有单列集合的根接口
-
Collections 是操作集合的工具类。
-
Collections中常见的方法
-
static boolean addAll(Collection c, T... elements): 向集合中批量添加元素。参数c表示集合。参数elements表示要向此集合中添加哪些元素.
-
static void shuffle(List list): 对集合中的内容打乱顺序。
-
static void sort(List list): 对集合中的内容排序。
-
static void sort(List list, Comparator c) : 对集合中的内容排序。
public class Demo01Collections {
public static void main(String[] args) {
//创建一个集合
ArrayList<String> list = new ArrayList<>();
//Collections工具类中的addAll可以直接批量添加
Collections.addAll(list, "aa", "bb", "cc", "dd");
//打印集合
System.out.println(list);
//static void shuffle(List list): 对集合中的内容打乱顺序。
Collections.shuffle(list);
System.out.println(list);
}
}
(1)static void sort(List list): 对集合中的内容排序。
要使用sort方法排序的集合,里面的泛型类型必须要实现Comparable接口。
实现这个接口才表示这个类的对象具备了排序的功能。
这种排序叫做自然排序。
public class Demo02Collections {
public static void main(String[] args) {
//创建一个集合,保存数字
ArrayList<Integer> numList = new ArrayList<>();
//添加
numList.add(200);
numList.add(100);
numList.add(300);
//打印集合
System.out.println("numList:" + numList);
Collections.sort(numList);
//打印集合
System.out.println("numList:" + numList);
System.out.println("=======================================");
//创建一个集合保存字符串
ArrayList<String> strList = new ArrayList<>();
//添加元素
strList.add("bbb");
strList.add("aaa");
strList.add("ccc");
//打印集合
System.out.println("strList:" + strList);
//对集合中的内容进行排序
Collections.sort(strList);
//打印集合
System.out.println("strList:" + strList);
System.out.println("=======================================");
//创建集合,保存Person对象
ArrayList<Person> list = new ArrayList<>();
//添加三个Person对象
list.add(new Person("大幂幂", 18));
list.add(new Person("柳岩", 16));
list.add(new Person("金星", 20));
//对这个存放Person的集合进行排序
Collections.sort(list);
System.out.println("list:" + list);
}
}
(2)static void sort(List list, Comparator c) : 对集合中的内容排序。这种排序方式叫做比较器排序。
如果某些对象本身并不具备自己排序的功能,那么我们可以去找一个法官帮他们进行比较。这个法官其实就是比较器。
比较器用的是Comparator 接口。
自然排序(Comparable): 自然排序,某个类实现了Comparable接口,就表示这个类的对象自己就具备类排序的功能。
(重点)比较器排序(Comparator): 事物本身自己是并不会排序的,需要借助一个法官去帮他们排序,这个法官就是比较器。
public class Demo03Collections {
public static void main(String[] args) {
//创建一个集合,保存Student
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("柳岩", 18));
list.add(new Student("大幂幂", 16));
list.add(new Student("白百合", 20));
//使用比较器排序对集合中的内容进行排序
Collections.sort(list, new Rule());
//打印结果
System.out.println("list:" + list);
}
}
(3) 实现Comparable接口需要重写里面的compareTo方法。
当我们调用Collections的sort方法时,系统内部会通过对象调用compareTo进行比较。
返回值:
如果返回值是一个负数,那么表示当前对象小于参数对象
如果返回值是0,表示这两个对象相等
如果返回值是正数,表示当前对象大于参数对象。
升序就是我减他。
如果要根据年龄排序,那么在这个方法里面拿当前对象的年龄减去参数对象的年龄并返回
@Override
public int compareTo(Person o) {
return this.getAge() - o.getAge();
// return o.getAge() - this.getAge();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(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;
}
}
import java.util.Comparator;
/*
这个类实现了Comparator接口,那么就表示这个类变成了一个比较器类。
他可以比较两个Student对象谁大谁小。
*/
public class Rule implements Comparator<Student>{
/*
这个方法用来比较o1和o2这两个参数对象谁大谁小。
如果返回值是负数,那么表示o1小于02
如果返回值是0表示这两个对象相等。
如果返回值是正数,表示o1大于o2
公式: 升序就是1减2
*/
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
}