前言:
这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
Java的类集框架比较多,也十分重要,在这里给出图解,可以理解为相应的继承关系,也可以当作重要知识点回顾;
Collection集合接口
继承自:Iterable
public interface Collection<E> extends Iterable<E>
java.util.Collection是单值集合操作的最大父接口,其中有几个核心操作方法以及常用操作方法;
| Modifier and Type | Method(public) | Description |
|---|---|---|
boolean | add(E e) | 确保此集合包含指定的元素(可选操作)。 |
boolean | addAll(Collection<? extends E> c) | 将指定集合中的所有元素添加到此集合(可选操作)。 |
void | clear() | 从集合中删除所有元素(可选操作)。 |
boolean | contains(Object o) | 如果该集合包含指定的元素,则返回true。 |
boolean | remove(Object o) | 如果存在,则从此集合中删除指定元素的单个实例(可选操作)。 |
int | size() | 返回此集合中的元素数。 |
Object[] | toArray() | 返回一个包含此集合中所有元素的数组。 |
Iterator<E> | iterator() | 返回对此集合中的元素进行迭代的迭代器。 |
上面方法中有两个特殊的方法就是cotains与remove;都需要equals方法的支持才能删除与查询数据;否则找不到元素。
后面都是衍生出的子类方法。
List集合
最大特点:允许保存重复的元素,并在其父接口上扩充了其他的方法;
继承关系:
public interface List<E> extends Collection<E>
| Modifier and Type | Method(public) | Description |
|---|---|---|
void | add(int index, E element) | Inserts the specified element at the specified position in this list (optional operation). |
boolean | add(E e) | Appends the specified element to the end of this list (optional operation). |
ListIterator<E> | listIterator() | Returns a list iterator over the elements in this list (in proper sequence). |
static <E> List<E> | of() | Returns an unmodifiable list containing zero elements. |
default void | forEach(Consumer<? super T> action) | Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception. |
实例:
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.List;
public class 多数据保存 {
public static void main(String[] args) {
List<String> all = List.of("xbhg","Hello","World","welcome");
Object[] result = all.toArray();
for (Object t: result) {
System.out.println(t);
}
System.out.println("----------分割线----------");
all.forEach(System.out::println); //方法引用部分的引用构造方法
}
}
ArrayList子类
继承结构如下:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
实例化:重复元素允许保存并且按照添加时的顺序保存;
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayList实例化List {
public static void main(String[] args) {
List<String> all = new ArrayList<String>();
all.add("Hello");
all.add("你好");
all.add("你好");
all.add("xbhog");
System.out.println(all);
all.forEach(System.out::print);
//lambda表达式
all.forEach((str)->{
System.out.print(str+"、");
});
}
}
集合操作方法:
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.ArrayList;
import java.util.List;
public class ArrayLIst集合相关操作 {
public static void main(String[] args) {
List<String> all = new ArrayList<String>();
System.out.println("集合是否为空?"+all.isEmpty()+"、集合元素个数"+all.size());
all.add("1");
all.add("2");
all.add("3");
System.out.println("集合是否为空?"+all.isEmpty()+"、集合元素个数"+all.size());
System.out.println(all.get(1));
System.out.println(all.remove("3"));
System.out.println("集合是否为空?"+all.isEmpty()+"、集合元素个数"+all.size());
}
}
ArrayList原理分析:重点
首先需要明确ArrayList是通过数组实现的;这样就出现了ArrayList通过什么样的方式进行的扩容操作,以及在什么情况下才会扩容?
ArrayList类中的数组是在构造方法中进行的空间开辟的;其对应的有无参和有参构造方法:
无参构造方法:使用空数组(长度为0)初始化,在第一次使用时会为其开辟空间为(初始化程度为10);
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//默认的开辟空间大小
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
有参构造方法:长度大于0则以指定长度开辟数组空间;如果长度为0,则按照无参构造方法进行;如果负数则抛出ILLegaLArgumentException异常;
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
当数组扩充后利用数组复制的形式,将旧数组中的数据复制到开辟的新数组中;
其最大程度为:
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
ArrayList保存自定义类对象:
该操作必然包含了相关的增删改查;由于contains与remove方法的实现都需要通过对象比较俩完成;所以我们需要覆写equals方法
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.ArrayList;
import java.util.List;
class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public boolean equals(Object obj){
if(this== obj) return true;
if(obj == null) return false;
if(!(obj instanceof Person)) return false;
Person pe = (Person) obj;
return this.name.equals(pe.name) && this.age == pe.age;
}
@Override
public String toString() {
return "姓名:"+this.name +"、年龄:"+this.age;
}
}
public class ArrayList保存自定义类对象 {
public static void main(String[] args) {
List<Person> std = new ArrayList<Person>();
std.add(new Person("xbhog",1));
std.add(new Person("小明",2));
std.add(new Person("小白",3));
System.out.println("-------删除前的数据内容----------");
std.forEach((person)->{
System.out.println("姓名:"+person.getName()+"、年龄:"+person.getAge());
});
System.out.println("-------删除后的数据内容----------");
std.remove(new Person("小白",3));
std.forEach((person)->{
System.out.println("姓名:"+person.getName()+"、年龄:"+person.getAge());
});
System.out.println("-------查看数据是否存在----------");
System.out.println(std.contains(new Person("小明",2)));
}
}
LinkedList子类:
继承结构如下:基于链表形式的实现
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable
实现LinkedList的集合操作:
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.LinkedList;
import java.util.List;
public class LinkList链表操作 {
public static void main(String[] args) {
List<String> all = new LinkedList<String>();
all.add("java");
all.add("python");
all.add("Linux");
System.out.println(all);
System.out.println(all.get(2));
System.out.println(all.get(1));
}
}
Vector子类:
继承结构如下:
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
从继承结构上可以看出,Vector子类的使用方式与ArrayList的使用方式相同;
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.List;
import java.util.Vector;
public class Vector子类实现List接口 {
public static void main(String[] args) {
List<String> all = new Vector<String>();
all.add("asda");
all.add("你好");
all.add("buhao");
System.out.println(all);
}
}
不同点:
以下是vector操作方法,采用的方式是synchronized 同步处理;属于线程安全,但是效率没有ArrayList高;
在考虑线程并发访问的情况下才能去使用vector子类。
public synchronized void copyInto(Object[] anArray)
结束:
如果你看到这里或者正好对你有所帮助,希望能点个关注或者推荐,感谢;
有错误的地方,欢迎在评论指出,作者看到会进行修改。