集合框架
-
Collection接口:单列集合,用来存储对象
List接口:存储有序可重复的数据。
包括:ArrayList、LinkedList、VoctorSet接口:存储无序的,不可重复的数据。
包括:HashSet、LinkedHashSet、TreeSet -
Map接口:键值对存储(Key-Value)
包括:HashMap、LinkedHashMap、TreeMap、HashTable、Properties
ArrayList
Collection coll = new ArrayList();
常用增删改方法
add()//添加
size()//元素个数
coll.addAll(coll2)//添加到coll集合中 coll2的所有元素
coll.clear()//清空集合
coll.isEmpty()//判断是否为空 判断依据是长度为0(非null)
coll.contains(Object o)//通过调用类的equals方法,判断coll中是否有o,自定义类需重写equals方法
coll.containsAll(Collection coll2);//判断coll中是否有coll2中的所有元素
coll.remove(Object o)//移除cool中的元素o,不存在则返回false
coll.removeAll(Collection coll2)//移除cool中所有与coll2相同的元素
coll.retainAll(Collection coll2)//移除cool中所有与coll2不同的元素
coll.equals(cool)//判断中元素是否相同 判断顺序与否跟具体实现类有关
coll.hashCode()//返回coll哈希值
Object o = coll.toArray()//集合转数组(Object)
coll.toArray(T[] t)//(T[])
String[] str = {"aa","bb","cc"};
List<String> list = Arrays.asList(str)//数组转集合 对应List size:3
**特别注意**
List list = Arrays.asList(new int[]{123,456});//会认为是一个元素 size:1
List list = Arrays.asList(new Integer[]{123,456});//包装类可以 size:2
示例
public void test2(){
Collection coll1 = new ArrayList();
Collection coll2 = new ArrayList();
//添加元素
coll1.add(123);
coll1.add("abc");
coll1.add(new Date());
coll2.add("abc");
//删除
coll1.remove(123);
//删除coll1中所有与coll2中相同的元素
coll1.removeAll(coll2);
//通过调用类的equals方法,判断coll中是否有"abc",自定义类需重写equals方法
coll1.contains("abc");
//判断coll中是否有coll2中的所有元素
coll1.containsAll(coll2);
//将coll2中所有元素添加到coll1中
coll1.addAll(coll2);
//移除coll1中所有与coll2不同的元素
coll1.retainAll(coll2);
//长度
coll1.size();
//是否存在此元素
coll1.contains("abc");
//判空
coll1.isEmpty();
//清空
coll1.clear();
}
ArrayList通过equals()方法判断是否存在
@Test
public void test1(){
Collection coll = new ArrayList();
//new一个Xr对象
Xr xr = new Xr(8);
//添加到集合中
coll.add(xr);
//判断是否存在 如果重写了equals方法 返回true 否则返回false
System.out.println(coll.contains(new Xr(8)));
}
Xr类
class Xr{
private int count;
public Xr(int count){
this.count = count;
}
//重写的equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Xr xr = (Xr) o;
return count == xr.count;
}
}
迭代器遍历
迭代器 遍历集合
Iterator iterator = coll1.iterator();
while (iterator.hasNext()){//判断下一个是否为空
System.out.println(iterator.next());//先下移 再返回
}
错误写法
while (coll1.iterator.hasNext()){//判断下一个是否为空
System.out.println(iterator.next());//先下移 再返回
}
while (iterator.next()!=null){//判断下一个是否为空
System.out.println(iterator.next());//先下移 再返回
}
删除指定元素
Iterator iterator = coll1.iterator();
while (iterator.hasNext()){//判断下一个是否为空
Object o = iterator.next();
if("Tom".equals(o)){
iterator.remove();
}
}
Iterator iterator = coll1.iterator(); //再次遍历时需要新造迭代器 因为指针此时在最低端
For Each遍历
Collection coll = new ArrayList();
for (Object obj :list){
System.out.println(obj);
}
for (int i = 0;i < list.size(); i++){
System.out.println(list.get(i));
}
—————————————————分割线———————————————————
HashSet
HashSet底层是数组加链表,判断元素是否相同是通过哈希值和equals方法。
先判断哈希值,如果位置上没元素,直接放,如果有,在调用equals方法,如果与位置上的所有元素(链表存储)都不等,再放。
自定义类需要重写equals方法
JDK7版本:新增元素放在链表的头部。
JDK8版本:新增元素放在链表的尾部。
LinkedHashSet作为HashSet的子类,在HashSet的基础上按加入顺序加上双向链。
优点:便于频繁的遍历
需要重写equals()
方法和hashCode()
方法
Set和List的区别
Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变
<实现类有ArrayList,LinkedList,Vector> 。
TreeSet
TreeSet判断元素是否相同是通过自然排序
Comparable
重写方法compareTo
,不再是哈希值和equals方法
亦或是通过自定义排序Comparator
重写compsre
,TreeSet
直接调Comparator
为参数的构造器即可
常用方法示例
public void test3(){
Set set1 = new HashSet();
Set set2 = new HashSet();
//添加
set1.add(123);
set1.add("abc");
//不会添加重复元素
set1.add(123);
//判空
set1.isEmpty();
//清空
set1.clear();
//长度
set1.size();
//将set2中的所欲元素添加到set1中
set1.addAll(set2);
//删除
set1.remove(123);
//删除所有相同元素
set1.removeAll(set2);
}
面试题
@Test
public void test(){
HashSet set = new HashSet();
Person p1 = new Person("aa",12);
Person p2 = new Person("bb",24);
set.add(p1);
set.add(p2);
p1.age = 13;
set.remove(p1);
//age被修改 哈希值已变 但地址没变 所以删除的是改变之后的地址 所以删不掉
System.out.println(set);
set.add(new Person("aa",13));
//添加至指定哈希值位置处 可以添加 虽与p1相同 但p1在哈希值改变前的地址 所以不会形成链表
System.out.println(set);
set.add(new Person("aa",12));
//也可以添加 哈希值与p1相同 但equals之后 不同 可以添加至p1链后
System.out.println(set);
}
Person类
重写了equals()
方法和hashCode()
方法
class Person{
String str;
int age;
public Person(String str, int age) {
this.str = str;
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;
if (age != person.age) return false;
return str != null ? str.equals(person.str) : person.str == null;
}
@Override
public int hashCode() {
int result = str != null ? str.hashCode() : 0;
result = 31 * result + age;
return result;
}
@Override
public String toString() {
return "Person{" +
"str='" + str + '\'' +
", age=" + age +
'}';
}
}
测试结果
[Person2{name='bb', age=24}, Person2{name='aa', age=13}]
[Person2{name='bb', age=24}, Person2{name='aa', age=13}, Person2{name='aa', age=13}]
[Person2{name='bb', age=24}, Person2{name='aa', age=13}, Person2{name='aa', age=13}, Person2{name='aa', age=12}]
如果注释掉equals()
方法和hashCode()
方法
则测试结果为
[Person2{name='bb', age=24}]
[Person2{name='aa', age=13}, Person2{name='bb', age=24}]
[Person2{name='aa', age=13}, Person2{name='bb', age=24}, Person2{name='aa', age=12}]
可以利用HashSet给List去重(如果是自定义类 则要重写equals和hashCode)
set.addAll(list)
将list中所有元素加入到set中,此时已经去重。
new List(set)
转换回来即可
Collections工具类
Collections工具类系列笔记 https://blog.csdn.net/weixin_46002478/article/details/109059635
HashMap
HashMap系列笔记 https://blog.csdn.net/weixin_46002478/article/details/109057051