Collection 接口是 Java 集合框架中的根接口,它是所有集合类的父接口。它定义了一些通用的方法和行为,用于操作和管理集合中的元素。
Collection 接口的主要方法和行为包括:
添加和删除元素:add(Object obj)
方法用于向集合中添加一个元素,remove(Object obj)
方法用于从集合中删除指定元素,clear()
方法用于清空集合中的所有元素。
判断集合是否包含某个元素:contains(Object obj)
方法用于判断集合是否包含指定元素,isEmpty()
方法用于判断集合是否为空。
获取集合大小:size()
方法用于获取集合中元素的个数。
迭代访问集合元素:iterator()
方法返回一个用于遍历集合元素的迭代器。
转换为数组:toArray()
方法将集合转换为数组。
除了以上常用的方法外,Collection 接口还提供了其他一些方法,如批量操作、集合的交集、并集、差集等。具体的方法可以参考 Java 文档。
需要注意的是,由于 Collection 是一个接口,它本身不能直接实例化,需要通过其子接口(如 List、Set)或实现类(如 ArrayList、HashSet)来创建具体的集合对象。
List(列表)是集合框架中的一个子接口,它继承自 Collection 接口。List 是一个有序的集合,可以包含重复的元素。
List 接口的常见实现类有 ArrayList
、LinkedList
和 Vector
。
ArrayList类底层是动态数组,是List的实现类,
缺点
Arraylist集合扩容时会创建更大的数组空间,把原有数据复制到新数组中。这样就会导致,插入和删除时候的速度会很慢。
优点
因为底层是数组所以可以快速访问其中的元素
问题1:
如果我定义一个长度为10 的arraylist 那么我加入20 个数他的长度是多少
回答:
ArrayList内部使用一个数组来存储元素。当元素的数量超过当前数组的容量时,ArrayList会创建一个更大的数组,并将所有元素从旧数组复制到新数组中,从而实现扩容。通常情况下,ArrayList的扩容策略是将容量增加一半。
假设ArrayList按照每次扩容增加一半容量的策略,那么:
添加第11个元素后,ArrayList的容量增加至15。
添加第16个元素后,ArrayList的容量增加至22。
添加第21个元素后,ArrayList的容量增加至33。
Arrays.asList(...)
是一个用于将数组转换为列表的方法。它接受一个参数,即要转换为列表的数组,并返回一个包含数组元素的固定大小的列表。
该方法的作用是将数组转换为列表,这样我们可以使用列表接口提供的方法来操作数组的元素,例如添加、删除、修改等操作。
使用 Arrays.asList(...)
方法的示例代码如下:
String[] array = {"apple", "banana", "orange"};
List<String> list = Arrays.asList(array);
System.out.println(list); // 输出:[apple, banana, orange]
在上面的示例中,我们先定义了一个字符串数组 array
,然后通过 Arrays.asList(array)
将数组转换为列表,并将结果赋值给 list
变量。接下来,我们打印输出了列表的内容,可以看到列表中包含了数组的元素。
需要注意的是,Arrays.asList(...)
返回的是一个视图列表(view list),它并不是一个独立的新列表。这意味着,对原始数组或转换后的列表进行的修改会互相影响。例如,如果我们修改了数组中的某个元素,那么对应的列表元素也会发生变化,反之亦然。此外,由于视图列表的大小是固定的,因此它不支持添加或删除元素的操作。
如果需要对转换后的列表进行添加、删除等操作,可以考虑使用 new ArrayList<>(Arrays.asList(...))
的方式来创建一个新的可变列表。
add(element)
: 将指定的元素添加到列表的末尾。ArrayList<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
get(index):
返回指定索引位置的元素。 String fruit = list.get(0); // 获取第一个元素
set(index, element):
将指定索引位置的元素替换成新的元素。
list.set(1, "grape"); // 将索引为 1 的元素替换为 "grape"
remove(index)
: 删除指定索引位置的元素,并将其返回。String removedElement= list.remove(2); // 删除索引为 2 的元素
size():
返回列表中的元素个数。java int size = list.size(); // 获取列表的大小
ArrayList的size()方法返回的是实际存储的元素数量,而不是容量
contains(element):
检查列表是否包含指定元素,如果包含则返回 true,否则返回 false。boolean contains = list.contains("apple"); //
检查列表是否包含 "apple"
isEmpty()
: 检查列表是否为空,如果为空则返回 true,否则返回 false。 boolean isEmpty = list.isEmpty(); // 检查列表是否为空
clear()
: 清空列表中的所有元素。 list.clear(); // 清空列表
Contains(element)方法其实是调用对象element的equals方法
下面我们通过代码来解析一下:
Collection arrayList = new ArrayList();
ArrayList arrayList1 = new ArrayList();
//创建arraylist的两种方式
arrayList.add("one");
arrayList.add("two");
arrayList.add(1);
arrayList.add(2);
arrayList.add(new student("小明",12));
String a ="one";
student student = new student("小明",12);
arrayList1.add("one");
arrayList1.add("two");
arrayList1.add(1);
arrayList1.add(2);
arrayList1.add(new student("小明",12));
System.out.println(arrayList.containsAll(arrayList1));
System.out.println(arrayList1.contains(student));
System.out.println(arrayList1.contains(a));
student类:
private String name;
private int age;
public student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 重写equals的代码
@Override
public boolean equals(Object o) {
System.out.println("User equals()....");
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
student user = (student) o;
if (this.age != user.age) {
return false;
} else {
return this.name != null ? this.name.equals(user.name) : user.name == null;
}
} else {
return false;
}
}
在这段代码中如果我没重写这个类对象的equals的话
就会导致下面这两段代码 返回 false 和true。
因为a是string类型的这个类型的equals已经被重新就是比较内容的
所以我们要重写这个equals方法在student类中
System.out.println(arrayList1.contains(student));
System.out.println(arrayList1.contains(a));
LinkedList
是 Java 中的一个双向链表实现类,它实现了 List
接口和 Deque
接口,并且提供了一系列操作链表的方法。
与 ArrayList
不同之处
LinkedList
的底层数据结构是一个双向链表,每个节点包含了当前元素的值以及指向前一个节点和后一个节点的引用。这使得 LinkedList
在插入、删除元素时更具有优势,因为只需要调整相邻节点的引用即可,而不需要像数组那样进行数据的搬移。
劣势
随机访问速度很慢,它每次访问元素都要从头开始
同时,定义内部类Node,作为LinkedList中保存数据的基本结构。 Node除了保存数据,还定义了两个变量:
addFirst(element)
或 offerFirst(element):
在链表的开头添加一个元素。addLast(element)
或 offerLast(element)
: 在链表的末尾添加一个元素。getFirst()
: 返回链表的第一个元素,但不删除它。getLast():
返回链表的最后一个元素,但不删除它。removeFirst()
或 pollFirst()
: 移除并返回链表的第一个元素。removeLast()
或 pollLast()
: 移除并返回链表的最后一个元素。peekFirst()
: 返回链表的第一个元素,但不移除它peekLast()
: 返回链表的最后一个元素,但不移除它。push(element)
: 将一个元素推入链表的开头(等效于addFirst(element)
)。pop()
: 从链表的开头弹出一个元素(等效于 removeFirst()
)`descendingIterator()
: 返回一个逆向迭代器,用于从链表的末尾向前遍历元素。1.获取集合的迭代器对象:通过调用集合的 iterator()
方法获取迭代器对象。例如:
List<String> list = new ArrayList<>();
// 添加元素到集合
Iterator<String> iterator = list.iterator();
2.使用迭代器遍历集合:使用迭代器的 hasNext()
方法判断是否还有下一个元素,next()
方法获取并返回下一个元素。例如:
while (iterator.hasNext()) {
String element = iterator.next();
// 处理元素
}
3.可选操作:在遍历过程中,如果需要删除集合中的某个元素,可以使用迭代器的 remove()
方法。例如:
iterator.remove(); // 移除当前元素
下面是一个完整的示例,展示了如何使用迭代器遍历一个 List 集合:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
输出结果:
apple
banana
orange
需要注意的是,一旦开始使用迭代器对集合进行遍历,就不要在遍历过程中直接修改集合的内容(如添加、删除元素),否则可能会抛出ConcurrentModificationException
异常。如果需要修改集合,应该使用迭代器的 remove() 方法。
此外,Java 8 引入了 forEach 方法和 Lambda 表达式,可以更简洁地遍历集合,如下所示:
java
list.forEach((element) -> {
// 处理元素
});
Collection arrayList = new ArrayList();
ArrayList arrayList1 = new ArrayList();
这两行代码的区别在于对类型的声明和使用上存在差异。
1.Collection arrayList = new ArrayList();
:
在这行代码中,arrayList
被声明为Collection 类型的变量,通过 new ArrayList()
创建了一个对象并将其赋值给 arrayList
。这样做的目的是使用更抽象的类型 Collection
,以便后续可以根据需要灵活地改变具体实现类。
在此声明中,只能使用 Collection 接口中定义的方法来操作 arrayList
对象,而不能使用 ArrayList
特定的方法。
2.ArrayList arrayList1 = new ArrayList()
;:
在这行代码中,arrayList1
被声明为 ArrayList 类型的变量,通过 new ArrayList()
创建了一个 ArrayList 对象并将其赋值给 arrayList1
。
在此声明中,可以使用 ArrayList 特定的方法来操作 arrayList1
对象,并且还可以使用 List 接口中定义的通用方法。
总体来说,Collection arrayList = new ArrayList();
声明的变量更加通用,适用于多种集合类型。而 ArrayList arrayList1 = new ArrayList();
声明的变量则明确指定了具体的集合类型为 ArrayList。
需要根据具体需求和使用场景选择合适的声明方式。如果确定只需要使用 ArrayList 的特定方法,可以选择第二种方式;如果可能会用到其他集合类型的方法,并希望在未来可以灵活更改具体实现,可以选择第一种方式
灵活更改具体实现代码举例
Collection<String> collection;
// 使用 ArrayList 实现类
collection = new ArrayList<>();
collection.add("Item 1");
collection.add("Item 2");
// 在后续代码中可以方便地切换为 LinkedList 实现类
collection = new LinkedList<>();
collection.add("Item 3");
collection.add("Item 4");
// 使用 HashSet 实现类
collection = new HashSet<>();
collection.add("Item 5");
collection.add("Item 6");
输出
Item 5
Item 6
请注意,在切换实现类时,之前存储的数据将会被新的实现类所替换。因此,在遍历和打印集合元素时,只会输出最后一次存储的数据