Java—类集1
1.什么是类集?
类集是为了解决数组长度固定的问题而产生的,
其本质就是一个用动态的对象数组实现的框架—Java类集框架。
可以说累计就是动态数组。
类集下有两个核心接口:
1.Collections 2.Map;
##Collections
1.Collection下有几个核心方法:
方法 | 内容 |
---|---|
public boolean add(E e) | 向集合中添加元素 |
public boolean remove(Object o) | 删除指定元素 |
public boolean contains(Object o) | 类集中是否包含指定元素 |
public Object[] toArray() | 将集合变为对象数组 |
public int size() | 返回集合中元素个数 |
public Iterator iterator() | 获取集合的Iterator接口对象 |
##子接口List
List接口有两个独有的方法:
方法 | 内容 |
---|---|
public E set(int index, E element) | 设置固定索引的值 |
public E get(int index) | 取得指定索引的值 |
1.有三个具体子类
ArrayList:版本JDK1.2,底层由数组实现,采用异步处理,性能较高,线程不安全,可以采用Iterator 、ListIteraror、foreach,初始化机制,lazy-load 每当add()方法添加一个元素后才会初始化,初始值为10,
并且每次扩容1.5
LinkedList:版本JDK1.0,底层由双向链表实现,才用异步处理,性能较高,线程不安全,但是由于底层是链表,性能高,可以采用Iterator 、ListIteraror、foreach
Vector:版本JDK1.0,底层由数组实现,采用同步处理,性能较低,但是线程安全,可以采用Iterator 、ListIteraror、foreach、Enumeration 当有一个实例化Vector就会初始化一个容量为10 的Vector。
我们可以看出,向集合内添加的是java自带的类型,那么,我们在查找和删除时可以找到,但如果是自定义类型,就必须覆写equals()方法:
class Person{
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name) &&
Objects.equals(age, person.age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test{
public static void main(String[] args) {
ArrayList<Person> list=new ArrayList<>();
list.add(new Person("张三",19));
list.add(new Person("李四",10));
list.add(new Person("王麻子",0));
System.out.println(list.contains(new Person("张三",19)));
}
}
如果覆写equals ,那么就相当于两个不同的对象在比较,所以即使内容一样,比较结果也是不同的,而我们想要比较的是内容。
2.迭代器输出
迭代器接口有Iterator ,ListI,Enumeration
Iterator:
Enumeration:v只提供了遍历Vector和HashTable类型集合元素的功能,不支持元素的移除操作。
ListIterator:针对List的迭代器ListIterator,该迭代器只能用于各种List类的访问。
可以双向访问。
1.获取迭代器接口对象
2.迭代器接口对象有三个方法
方法 | 解释 |
---|---|
boolean hasNext() | 是否有下一个元素 |
E next() | 取得下一个元素 |
default void remove() | 删除元素 |
public class Test{
public static void main(String[] args) {
ArrayList<Person> list=new ArrayList<>();
list.add(new Person("张三",19));
list.add(new Person("李四",10));
list.add(new Person("王麻子",0));
System.out.println(list.contains(new Person("张三",19)));
Iterator iterator=list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
在迭代器输出的时候,有如果有list.remove() 操作,会抛出ConcurrentModificationException
但是Iterator为我们提供了 iterator.remove()方法来避免出错。
实际上,如果是线程安全的集合 比如Vector就不会出现这个问题。
上述例子ArrayList采用的是异步操作,也就是说多个允许线程访问,如果一个线程删除一个数据,别的线程拿到的是不完整的数据,所以出现脏读,不允许删除。
所以 ,java采用一种fast–fail操作,保证用户在进行迭代遍历时数据一定输最新的。
通过查看原码,ArrayList里有一个modCount来记录集合的修改次数,
在取得迭代器接口时,会创建一个副本expectedModCount,来记录当前集合修改次数,如果使用remove,add,set等方法修改集合modCount就会自增,而每次迭代器输出的时候,会检查modCount和expectedModCount是否相等,所以如果不相等,那么就会抛出ConcurrentModificationException ,
这样保证每次输出都是最新的。
Colletions工具类有一个synchronizedList ()
可以将线程不安全的转换成线程安全的 但是不建议使用 如果要使用
就用CopyonWriteArrayList
子接口Set(数据不允许重复)
set接口下有两个具体的子类
HashSet,和TreeSet
其中他们的区别是TreeSet是有序的,而HashSet是无序的
同样,如果是java已有的类型添加或删除到Set中,可以自动去重或排序,但是如果是自定义类型,一定要覆写hashCode和equals 并且如果是TreeSet类型,加入集合元素一定要实现Compareble接口并且覆写里面的CompareTo 或者在构造器中传入一个Comparator() 比较器
class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name) &&
Objects.equals(age, person.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test{
public static void main(String[] args) {
TreeSet<Person> treeSet=new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((Person)o1).getAge()-((Person) o2).getAge();
}
});
treeSet.add(new Person("a",19));
treeSet.add(new Person("b",18));
treeSet.add(new Person("c",20));
treeSet.add(new Person("d",21));
treeSet.add(new Person("d",21));
Iterator iterator=treeSet.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}