一、List与Set的区别
list和set都是collection的子类
List | Set |
---|---|
允许重复对象 | 不允许对象重复 |
有序。保持插入顺序,先入先出 | 无序。无法保证存储顺序 |
可以存入多个null元素 | 只能存入一个null元素 |
二、List集合
public interface List< E > extends Collection
可以看到List是Collection的子类,但List子接口对于Collection接口的方法进行了扩充
以下是扩充的几个方法:
方法名称 | 作用 |
---|---|
get(int index) | 获取指定索引上的数据 |
set(int index, E element) | 修改指定索引数据 |
listIterator() | 返回ListIterator接口对象 |
其常用子类有:ArrayList、LinkedList与Vector
1.ArrayList集合
ArrayList 底层是基于数组来实现容量大小动态变化的。所以增删慢,查找快,线程不安全,效率高。
数组的长度是不能发生变化的,但是ArrayList集合长度是可以发生变化的
语法: ArrayList < E > list1 = new ArrayList();
- 对于ArrayList来说,有一个< E >代表泛型
- 泛型也就是装在集合当中的所有元素,全部都是统一的什么类型
注意:泛型只能是引用类型,不能是基本类型 - 左边类型必须要写,JDK 1.7+开始右边尖括号内的类型可以省略
ArrayList的具体操作可以参考我以前写的文章
2.LinkedList集合
LinkedList底层是一个双向链表。增删快,查询慢,线程不安全,效率高
语法: LinkedList < E > list1 = new LinkedList();
(1)获取链表的第一个元素getFirst ()
(2)获取链表的最后一个元素getLast()
(3)添加元素add()
(4)向前面添加addFirst()
(5)向后面添加addLast()
(6)删掉所有元素clear()
(7)删除第一个元素removeFirst()
(8)根据范围删除列表元素subList(起始, 结束).clear()
public class Main{
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.addFirst("1");
list.addLast("6");
Iterator<String> iter=list.iterator();
while(iter.hasNext()){//迭代器输出
String str=iter.next();
System.out.print(str);
}
System.out.println();
list.subList(2,4).clear();
for(Object m: list){//增强for循环输出
System.out.print(m);
}
}
}
输出结果为:
123456
1256
3.Vector集合(使用较少)
Vector的底层数据结构是数组,查询快,增删慢,线程安全,效率低
Vector是List子类实现中提供的一个线程安全子类,其线程安全的保证使用Synchronized实现。查看源码可以发现它在所有方法上都使用了Synchronized修饰
4.ArrayList与LinkedList区别
(1)ArrayList是数组实现的集合操作,LinkedList是链表实现的集合操作
(2)在List集合使用get方法时,ArrayList的时间复杂度为O(1),而LinkedList时间复杂度为O(n)(n为集合长度)
(3)ArrayList在使用时默认初始化对象数组大小为10,如果空间不足则会采用2倍的形式扩充,如果保存大数据量的时候有可能会造成垃圾产生和性能下降,但这个时候可以用LinkedList子类
二、Set集合
public interface Set< E > extends Collection
Set集合用于存储无序元素(存入和取出的顺序不一定相同),值不能重复。
其常用子类有:HashSet、TreeSet
1.HashSet集合
HashSet集合内部数据结构是哈希表 ,是不同步的。它是通过对象的hashCode和equals方法来完成对象唯一性。
当其判断两个元素是否相同时,先要判断元素的hashCode值是否一致,只有在该值一致的情况下,才会判断equals方法,如果存储在HashSet中的两个对象hashCode方法的值相同equals方法返回的结果是true,那么HashSet认为这两个元素是相同元素,只存储一个(即重复元素无法存入)。
需要注意的是,如果创建HashSet集合时使用的时自定义的类,则需要重写equals方法和hashCode方法,否则会将重复元素存储在里面
(1)查询集合元素contains(Object o) :如果此集合包含指定的元素,则返回 true 。注意,因为HashMap集合没有下标,无法通过get方法查询集合元素。
(2)HashSet集合中没有提供修改元素的方法。只能通过对象元素中提供的方法,修改对象元素中的值。实际上对象本身的引用没有变,但是哈希值发生了变化(因为修改对象中的属性值也会引起哈希值的变化)
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
class Student{
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {//重写equals方法,以保证唯一性
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name);
}
@Override
public int hashCode() {//重写hashCode方法,以保证唯一性
return Objects.hash(name);
}
@Override
public String toString() {//重写toString方法,否则会显示地址值
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
public class Main{
public static void main(String[] args) {
HashSet<Student> hs = new HashSet<>();
Student st1 = new Student("ljx");
Student st2 = new Student("lh");
hs.add(st1);
hs.add(st2);
Iterator iter1 = hs.iterator();
while (iter1.hasNext()){//输出原来集合中数据
System.out.println(iter1.next());
}
Iterator it = hs.iterator();
while (it.hasNext()){//修改
Student st = (Student) it.next();
st.setName("666");
}
Iterator iter2 = hs.iterator();
while (iter2.hasNext()){//输出修改后集合数据
System.out.println(iter2.next());
}
}
}
输出结果为:
Student{name='ljx'}
Student{name='lh'}
Student{name='666'}
Student{name='666'}
2.TreeSet集合
它与HashSet集合最大的区别是集合中保存的数据是有序的,当利用TreeSet保存数据的时候,所有数据都按升序自动进行排序处理。
它允许使用自定义类,但这个类必须实现Comparable接口,因为只有实现了此接口,才能确认对象大小关系。
由于TreeSet在操作过程之中需要将类中的所有属性进行比对,但这样操作难度太高,所以开发中首选HashSet集合进行存储
二、Map集合
Map与Collection在集合框架中属并列存在
Map用于保存具有映射关系的数据,Map集合里保存着两组值,一组用于保存Map的ley,另一组保存着Map的value。其中key值不能重发,是无序集合。
Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素
1.Map中的常用方法:
1.void clear();
删除该Map对象中所有键值对;
2.containsKey(Object key);
查询Map中是否包含指定的key值
3.containsValue(Object value);
查询Map中是否包含一个或多个value;
4.entrySet();
返回map中包含的键值对所组成的Set集合,每个集合都是Map.Entry对象。
5.get();
返回指定key对应的value,如果不包含key则返回null;
6.isEmpty();
查询该Map是否为空;
7.keySet();
返回Map中所有key组成的集合;
8.values();
返回该Map里所有value组成的Collection。
9. put(Object key,Object value);
添加一个键值对,如果集合中的key重复,则覆盖原来的键值对;
10.putAll(Map m);
将Map中的键值对复制到本Map中;
11.remove(Object key);
删除指定的key对应的键值对,并返回被删除键值对的value,如果不存在,则返回null;
12.remove(Object key,Object value);
删除指定键值对,删除成功返回true;
13.size();
返回该Map里的键值对个数;
2.Entry:
Map中包括一个内部类Entry,该类封装一个键值对,常用方法:
1.getKey();
返回该Entry里包含的key值;
2.getvalue();
返回该Entry里包含的value值;
3.setValue(V value);
设置该Entry里包含的value值,并设置新的value值。