目录
一、List集合
List集合继承自Collection接口,元素是以线性方式存储的,元素有序并且可以重复,存入顺序就是取出顺序可以使用下标和迭代器或增强型for循环遍历获取元素。
常用的方法有:
public void add(int index, E element)
: 将指定的元素,添加到该集合中的指定位置上。
public E get(int index)
:返回集合中指定位置的元素。
public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。
public E set(int index, E element)
:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
其实就是增删改查,前面讲Collection集合的时候已经接触过ArrayList了,所以稍后使用LinkedList来测试一下。
1、ArrayList集合
ArrayList是List的一个具体实现类,它以数组结构存储数据,这样的好处是方便查询和遍历元素,不过增加和删除元素相对来说慢一点,在日常开发中,查询和遍历元素使用的相对较多,所以ArrayList也是最常用的集合,不过也不要随意的使用ArrayList集合来完成任何需求,这样不严谨,不提倡使用。
前面讲Collectiong集合和iterator迭代器的时候已经使用过ArrayList集合来测试了,这里就不再演示。
2、LinkedList集合
LinkedList也是List集合的一个具体实现类,和ArrayList集合不同的是LinkedList集合使用的是链式结构来存储数据的,这样的好处是方便增加和删除元素,同时LinkedList集合还提供了大量首尾操作的方法,代码演示如下:
1、增加元素
import java.util.LinkedList;
public class Test {
public static void main(String[] args) {
//创建LinkedList集合对象
LinkedList<String> strLinkedList = new LinkedList<>();
//1、LinkedList集合增加元素
//使用add方法(默认添加在集合尾部)
strLinkedList.add("asd");
//添加元素到指定的下标
strLinkedList.add(0,"sdf");
}
}
我们如何直到元素添加成功了呢?有几种办法,第一种,看集合添加元素前后的长度,如果添加一个元素之后,集合的长度增加了1,那么就说明添加成功了,第二种,在没有指定元素添加位置时,add方法是会有一个boolean值返回来的,可以通过输出查看add方法返回的值来判断是否添加成功,第三种,遍历输出;对于添加在指定位置的add方法我们可以直接查看指定下标处的值是否为我们添加的元素,后面这两种办法有一点缺陷,那就是List集合是允许元素重复的,如果恰好我们指定添加元素的位置的值和添加的元素的值相同,那么就不好判断了,所以最好还是使用返回值和集合长度来判断,看代码演示:
public class Test {
public static void main(String[] args) {
//创建LinkedList集合对象
LinkedList<String> strLinkedList = new LinkedList<>();
//1、LinkedList集合增加元素
//添加元素前集合的长度
System.out.println("添加元素前集合的长度为"+strLinkedList.size());
//使用add方法(默认添加在集合尾部)
System.out.println("元素添加的状态:"+strLinkedList.add("asd"));
//添加元素到指定的下标
strLinkedList.add(0, "sdf");
//添加元素后集合的长度
System.out.println("添加元素后集合的长度为"+strLinkedList.size());
}
}
运行结果:
结果很显然,集合的长度在添加两个元素之后增加了2,不指定位置添加元素的时候add方法返回了一个true,这样即证明了元素添加成功。
下面看LinkedList集合提供的首尾操作的方法(添加元素到集合的首部和尾部):
public class Test {
public static void main(String[] args) {
//创建LinkedList集合对象
LinkedList<String> strLinkedList = new LinkedList<>();
//1、LinkedList集合增加元素
//添加元素前集合的长度
System.out.println("添加元素前集合的长度为"+strLinkedList.size());
//使用add方法(默认添加在集合尾部)
System.out.println("元素添加的状态:"+strLinkedList.add("asd"));
//添加元素到指定的下标
strLinkedList.add(0, "sdf");
//添加元素到集合的首部
strLinkedList.addFirst("dfg");
//添加元素到集合的尾部
strLinkedList.addLast("fgh");
//添加元素后集合的长度
System.out.println("添加元素后集合的长度为"+strLinkedList.size());
//增强型for循环遍历输出一下,查看元素"dfg"和元素"fgh"是否分别添加在集合的首部和尾部
for (String str : strLinkedList) {
System.out.println(str);
}
}
}
运行结果:
结果很明显,"dfg"添加在集合的首部了,"fgh"添加在了集合的尾部。
2、查询元素
//2、查询元素
System.out.println("集合的第一个元素为:"+strLinkedList.getFirst()); //获取集合的第一个元素并输出
System.out.println("集合的最后一个元素为:"+strLinkedList.getLast()); //获取集合的最后一个元素并输出
System.out.println("集合的第三个元素为:"+strLinkedList.get(2)); //获取集合指定位置的元素
在前面的基础上加上以上两句语句,运行结果如下:
这两个方法都是返回集合的元素,因为我开始存入集合的都是String对象,所以直接输出对象,就是我们要的String字符串。
3、修改元素
现在我要把集合的第三个元素修改为"zxcv",看代码:
//3、修改元素
System.out.println("修改的结果为:"+strLinkedList.set(2,"zxcv"));
运行结果:
这里怎么不对呢,我不是把第三个元素修改为"zxcv"了吗?怎么还是"asd"呢?其实它是修改成功了的,因为set方法修改元素后返回的是被修改的元素,它告诉我们哪个元素被修改了,再来查看一下第三个元素:
//3、修改元素
System.out.println("被修改的元素为:"+strLinkedList.set(2,"zxcv"));
System.out.println("修改后的元素为"+strLinkedList.get(2));
运行结果:
这就是LinkedList集合中元素的修改了。
4、删除元素
下面再来看看删除元素,代码如下:
//4、删除元素
System.out.println("remove方法不带参数默认删除的元素为:"+strLinkedList.remove());
System.out.println("remove方法删除元素\"zxcv\"的状态为"+(strLinkedList.remove("zxcv")?"成功":"失败"));
//再次遍历集合列表,看看是否删除成功
for (String str : strLinkedList) {
System.out.println(str);
}
运行结果:
很显然,集合里面第一个元素"dfg"被不带参数的remove方法删除了,而元素"zxcv"则是被带一个参数的remove方法删除了,并且都删除成功,除此之外,LinkedList集合还提供了删除首部元素和尾部元素的方法以及清空集合的方法,代码如下:
//4、删除元素
// System.out.println("remove方法不带参数默认删除的元素为:"+strLinkedList.remove());
// System.out.println("remove方法删除元素\"zxcv\"的状态为"+(strLinkedList.remove("zxcv")?"成功":"失败"));
System.out.println("集合的第一个元素:"+strLinkedList.removeFirst()+"已被删除");
System.out.println("集合的最后一个元素"+strLinkedList.removeLast()+"已被删除");
System.out.println("集合删除首部元素和尾部元素后"+(strLinkedList.isEmpty()?"为空":"不为空"));
strLinkedList.clear();
System.out.println("集合清空元素后"+(strLinkedList.isEmpty()?"为空":"不为空"));
这里演示了删除集合首部元素和尾部元素以及清空集合的方法,并且用isEmpty方法来判断集合是否为空,从而判断集合是否清空,clean方法和isEmpty方法前面都讲过了,它们都是Collection里面有的方法,LinkedList集合实现了List集合,而List集合又是Collection的子类,所以这些方法是LinkedList集合和ArraysList集合共有的。
二、Set集合
继承自Collection接口,与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,反而比Collection接口更加严格了。与List接口不同的是,Set接口都会以某种规则保证存入的元素不出现重复。
1、HashSet集合
HashSet集合是根据对象的哈希值来确定元素在集合中的存储位置的,元素无序,存取顺序不能保证一致
代码如下:
public class Test {
public static void main(String[] args) {
//创建HashSet集合对象
HashSet<String> strHashSet = new HashSet<>();
//先添加几个元素
strHashSet.add("qwe");
strHashSet.add("wer");
strHashSet.add("ert");
strHashSet.add("rty");
for (String str : strHashSet) {
System.out.println(str);
}
}
}
运行结果:
代码很简单,就是添加几个元素,之后遍历输出,但是这里有一个问题,输出的结果顺寻并不是我存数据的顺序,这里就体现出了Set集合元素无序,存取顺序不能保证一致。
数据不能重复,使用hashCode()和equals()方法保证数据唯一性
代码如下:
//先添加几个元素
strHashSet.add("qwe");
strHashSet.add("wer");
strHashSet.add("ert");
strHashSet.add("qwe");
运行结果:
你看,这里我添加了两次元素"qwe",但是只添加进一个,所以当集合里面添加一个集合中已经有的元素时,是添加不进去的,因为hashCode方法和equals方法保证了数据的唯一性。
元素无序,没有下标和get方法,不能使用下标访问元素,只能使用增强型for循环和迭代器访问![](https://img-blog.csdnimg.cn/2d6327cb53f142acbf1299957ecdcc09.png)
//迭代器访问元素
Iterator iter = strHashSet.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
System.out.println("--------迭代器访问和增强型for循环访问分界线---------");
//增强型for循环访问元素
for (String str : strHashSet) {
System.out.println(str);
}
运行结果:
存储数据类型为自定义类的时候,必须重写自定义类里面的hashCode和equals方法
看一段代码:
public class Test {
public static void main(String[] args) {
//创建HashSet集合对象
HashSet<Animal> strHashSet = new HashSet<>();
//先添加几个元素
strHashSet.add(new Animal("大黄","黄色"));
strHashSet.add(new Animal("大黑","黑色"));
strHashSet.add(new Animal("大黄","黄色"));
for (Animal animal : strHashSet) {
System.out.println("名字是:"+animal.name+",颜色是"+animal.color);
}
}
}
class Animal{
String name;
String color;
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public Animal() {
}
}
运行结果:
这里好奇怪啊,Set类集合里面怎么可以村相同的元素进去了呢?前面说过, Set集合是通过hashCode()和equals()方法来保证数据唯一性,现在我们在集合里面存放的是自己定义的数据类型,必须要重写hashCode()和equals()方法才可以,看代码:
PS:在ldea里面我们直接使用Alt+Insert组合键就可以自动生成了
public class Test {
public static void main(String[] args) {
//创建HashSet集合对象
HashSet<Animal> strHashSet = new HashSet<>();
//先添加几个元素
strHashSet.add(new Animal("大黄","黄色"));
strHashSet.add(new Animal("大黑","黑色"));
strHashSet.add(new Animal("大黄","黄色"));
for (Animal animal : strHashSet) {
System.out.println(animal);
}
}
}
class Animal{
String name;
String color;
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public Animal() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Animal)) return false;
Animal animal = (Animal) o;
return Objects.equals(name, animal.name) && Objects.equals(color, animal.color);
}
@Override
public int hashCode() {
return Objects.hash(name, color);
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}
运行结果:
此时发现,重写了hashCode()和equals()方法之后元素就不能重复了,这里我也重写了toString方法,这样就可以通过输出元素名来输出元素里面的值了。
2、LinkedHashSet集合
我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?
在HashSet下面有一个子类java.util.LinkedHashSet
,它是链表和哈希表组合的一个数据存储结构。
代码演示如下:
public class Test {
public static void main(String[] args) {
//创建LinkedHashSet集合对象
LinkedHashSet<String> strLinkedHashSet = new LinkedHashSet<>();
//添加几个元素
strLinkedHashSet.add("qaz");
strLinkedHashSet.add("wsx");
strLinkedHashSet.add("edc");
strLinkedHashSet.add("qaz");
//遍历输出
for (String str : strLinkedHashSet) {
System.out.println(str);
}
}
}
运行结果:
三、总结
1、List集合允许元素重复,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
2、Set集合不允许元素重复,使用hashCode和equals方法来保证元素的唯一性,元素无序,不能保证存入顺序和取出顺序一致,没有下标,只能通过迭代器或增强型for循环来访问。