目录
集合
collection接口
借助API工具学习接口中的方法
collection接口是java.util包下的提供了很多集合中的方法,但是JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。
常见的集合有List、Set、Map
ArrayList和LinkedList的区别
1.ArrayList内部是一个数组结构,因此对于get和set操作比LinkedList更快,因为LinkedList要移动指针
2.LinkedList是一个链表结构,因此对于添加add和删除remove操作更加的灵活,但是要根据具体的实际数据
集合和数组的区别
1.数组一旦创建,长度不可改变,是固定长度,要实现缩容(删除元素)和扩容(添加元素)都需要重新创建一个新的数组,然后再进行操作
2.集合的长度是可变的,增删改操作更加的灵活
3.数组存储相同类型的数据、集合可以存储各种类型的数据
数组转集合的方法:Arrays.asList(数组) 集合转数组的方法:集合.toArray();
collection方法摘要
add(E e) :将指定的对象添加到集合中
addAll(Collection c) :把小集合添加到大集合中
equals(Object o) :比较指定对象与集合是否相等
hashCode() :返回集合的哈希哈值
isEmpty():判断集合是否为空
iterator():返回在此集合元素上迭代的迭代器,用来遍历集合中的元素
remove(Object o):将指定元素从集合中移除
size() :返回集合中的元素
toArray() :将此集合转化为对象数组
clear():将所有元素从该集合中移除
// c.clear();
// System.out.println(c);//清空当前集合中的所有元素
System.out.println(c.hashCode());//获取集合对象的哈希码
System.out.println(c.toString());//打印集合的具体元素
System.out.println(c.equals(200));//false,集合对象c与值200是否相等
System.out.println(c.contains(200));//true,c集合中是否包含指定元素200
System.out.println(c.isEmpty());//false,判断集合是否为空
System.out.println(c.remove(100));//true,一处集合中的指定元素,成功返回true
System.out.println(c);//[200, 300, 400, 500]
System.out.println(c.size());//4,返回集合的元素个数
Object[] array = c.toArray();//将指定的集合转为数组Object[]
System.out.println(Arrays.toString(array));//[200, 300, 400, 500]
泛型
泛型的作用:规范集合中元素的类型,泛型实在编译器时有效,运行时会消除泛型的对象实例类型信息
一般是用<>表示,通常与集合一起使用,为了限制类型,而且可以把报错时机提前
注意事项:类型必须使用引用类型,不可以使用基本类型
List接口
实现collection接口,因此collection中定义的公共方法,都可以使用
此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
List接口的特点
1.有下标
2.有序
3.集合中的元素可以重复
4.有索引,可以通过具体的索引进行元素的操作
–ArrayList–底层结构是数组,查询快,增删慢,适合查询场景比较多的情况
–LinkedList–底层结构是链表,查询慢,增删快,适合增删场景比较多的情况
List接口特有的方法
add(int index, E element) :在列表的指定位置插入指定元素
get(int index):返回列表中指定位置的元素
remove(int index):移除列表中指定位置的元素
set(int index, E element):用指定元素替换列表中指定位置的元素
subList(int fromIndex, int toIndex) :返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图
listIterator(int index) :返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
listIterator() :返回此列表元素的列表迭代器
ArrayList类
//1.创建对应的集合对象
/**
* 底层会自动帮我们创建数组来存放对象,并且数组的初始容量是10
*/
ArrayList<Integer> list = new ArrayList<>();
//2.向集合中添加元素,用于测试
list.add(100);
list.add(200);
list.add(300);
list.add(400);
list.add(400);
list.add(300);
System.out.println(list);
//3.测试常用方法
// list.clear();//清空集合
// System.out.println(list);
System.out.println(list.contains("100"));//false
System.out.println(list.isEmpty());//false
System.out.println(list.get(0));//100,根据下标获取元素
System.out.println(list.indexOf(400));//3
System.out.println(list.lastIndexOf(400));//4
System.out.println(list.remove(1));//200 移除指定位置处的元素
// System.out.println(list.remove(300));//IndexOutOfBoundsException
/**
* 上面的代码会报错:数组下标越界:index:300 size:5
* 主要是因为List中有两个重载的remove(),如果传入的是300,会认为是int类型的index索引,
* 所以如果想指定元素删除数据,需要把int类型的300手动装箱成Integer类型
*/
System.out.println(list.remove(Integer.valueOf(300)));
System.out.println(list.set(2,777));//修改指定所引出元素的值为777
System.out.println(list.size());//获取列表中元素的个数
//4.进行集合的迭代
//1.for循环
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
//2.高效for循环
for(Integer s : list){
System.out.println(s);
}
//3.iterator迭代器
Iterator<Integer> it = list.iterator();
while(it.hasNext()){//判断是否有下一个元素可迭代,如果有,继续循环
System.out.println(it.next());//打印本轮迭代到的元素
}
//4.listIterator迭代器
ListIterator<Integer> it2 = list.listIterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
}
LinkedList类
//1.创建集合对象
LinkedList<String> list = new LinkedList<>();
//2.向集合中添加元素
list.add("孙悟空");
list.add("猪八戒");
list.add("沙师弟");
list.add("唐三藏");
list.add("白龙马");
System.out.println(list);
//3.1请自行测试继承自Collection与List方法
//3.2测试LinkedList自己的方法
list.addFirst("玉兔精");//添加首元素
list.addLast("孔雀精");//添加尾元素
System.out.println(list);
System.out.println(list.getFirst());//获取首元素
System.out.println(list.getLast());//获取尾元素
System.out.println(list.removeFirst());//移除首元素
System.out.println(list.removeLast());//移除尾元素
System.out.println(list);
//4.其他测试
//4.1创建集合对象
LinkedList<String> list2 = new LinkedList<>();
list2.add("水浒传");
list2.add("西游记");
list2.add("三国演义");
list2.add("石头记");
System.out.println(list2);
System.out.println(list2.element());//获取但不移除集合中的首元素(第一个元素)
/**
* 别名:查询系列
*/
System.out.println(list2.peek());//获取但不移除集合中的首元素(第一个元素)
System.out.println(list2.peekFirst());//获取但不移除集合中的首元素(第一个元素)
System.out.println(list2.peekLast());//获取但不移除集合中的尾元素(最后一个元素)
/**
* 别名:新增系列
*/
System.out.println(list2.offer("聊斋志异"));
System.out.println(list2.offerFirst("斗罗大陆"));
System.out.println(list2.offerLast("斗破苍穹"));
System.out.println(list2);
/**
*别名:移除系列
*/
System.out.println(list2.poll());//移除首元素
System.out.println(list2.pollFirst());//移除首元素
System.out.println(list2.pollLast());//移除尾元素
System.out.println(list2);
Set接口
一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。
Set接口的特点
1.没有下标,无序,不包含重复元素
2.HashSet实现Set接口,底层是一个哈希表,(实际是HashMap集合,是数组和链表的结合)它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
3.给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一
Set接口的方法
//1.创建对象
//Set s = new Set();//父接口不可直接创建对象
Set<String> set = new HashSet<String>();
//2.存入数据
set.add("哈哈哈");
set.add("啦啦啦");
set.add("丫丫呀");
set.add(null);//向集合中存入null值
set.add(null);
set.add("null");//向集合中存入字符串null
System.out.println(set);
/**总结1:set集合中的元素都是无序的
* 总结2:set集合中的元素不能重复
* 总结3:set集合可以存放null,也只允许最多存1个
* 总结4:自定义对象(如Student)如果想要去重
* 需要添加重写的hashCode()与equals()*/
Set<Student> set2 = new HashSet();
Student s1 = new Student("张三",3);
Student s2 = new Student("李四",4);
Student s3 = new Student("李四",4);
set2.add(s1);
set2.add(s2);
set2.add(s3);
System.out.println(set2);
//3.set集合常用方法测试
//set.clear();//清空Set集合
System.out.println(set.contains("小兔纸"));//false,判断set集合中是否包含指定元素"小兔纸"
System.out.println(set.equals("大灰狼"));//false,判断set集合对象与指定元素是否相等
System.out.println(set.hashCode());//1961052313,获取当前set集合对象的哈希码
System.out.println(set.isEmpty());//false,判断当前集合是否为空
System.out.println(set.remove("null"));//false,移除指定元素,没有"null"元素,所以返回false
System.out.println(set.remove(null));//true,成功移除指定元素null,所以返回true
System.out.println(set);
System.out.println(set.size());//2,获取当前set集合的元素个数,类似数组长度
Object[] array = set.toArray();//把集合中的元素放入数组中
System.out.println(Arrays.toString(array));//使用数组工具类查看数组中的元素
//4.集合间的操作
Set<String> set2 = new HashSet();
set2.add("小老鼠");//给set2集合添加指定元素
set2.add("小猫咪");//给set2集合添加指定元素
set2.add("小狗崽");//给set2集合添加指定元素
set2.add("小兔纸");//给set2集合添加指定元素
System.out.println(set2);//查看set2集合中的元素
System.out.println(set.addAll(set2));//true,把集合set2中的元素添加到set集合中,成功返回true
System.out.println(set.containsAll(set2));//true,判断set集合中是否包含set2集合中的所有元素,如果包含返回true
System.out.println(set.removeAll(set2));//ture,移除set集合中属于set2集合的所有元素
System.out.println(set.retainAll(set2));
//5.集合的迭代
Iterator<String> it = set2.iterator();//5.1获取集合的迭代器
while(it.hasNext()) {//5.2判断集合是否有下个元素
String s = it.next();//5.3如果有,进循环获取当前遍历到的元素
System.out.println(s);
Map接口
Map接口特点
1.是通过键值对的方式存储数据,可以通过键来提取值
2.要求键不可以重复,重复的话值就会被覆盖
3.Map存放的是无序的数据
4.Map初始容量为16,默认的加载因子是0.75
Map接口的方法
//1.创建Map对象
/**Map中的数据要符合映射规则,一定要注意同时制定K和 V的数据类型
*至于这个K和V具体要指定什么类型,取决于具体的业务需求
*/
Map<Integer,String> map = new HashMap<>();
//2.向map集合存入数据,注意方法是put(),并且需要存入一对<K,V>值
map.put(101,"白骨精");
map.put(102,"黑熊精");
map.put(103,"鲶鱼精");
map.put(104,"黄毛怪");
map.put(105,"黑熊精");
map.put(101,"女儿国国王");
/**
* 1.map中存放着的都是无序的数据
* 2.map中的value可以重复--比如我们可以存两个黑熊精
* 3.map中的key不允许重复,如果重复,后面的value会把前面的value覆盖掉
* 比如女儿国国王和白骨精都是101,白骨精就被覆盖掉了
*/
System.out.println(map);
//3.进行方法测试
// map.clear();
System.out.println(map.hashCode());//获取集合的哈希码
System.out.println(map.equals("黄毛怪"));//判断“黄毛怪”是否与集合对象相等
System.out.println(map.isEmpty());
System.out.println(map.size());
System.out.println(map.containsKey(102));//true,判断当前map中是否包含指定的key值
System.out.println(map.containsValue("白骨精"));//false,因为已经被覆盖。判断当前map中是否包含指定的value值
System.out.println(map.get(104));//根据key获取对应的value值
//根据此key值对应的键值对,K与V都删了
System.out.println(map.remove(101));
System.out.println(map.containsKey(101));
System.out.println(map.containsValue("鲶鱼精"));
//将map集合中所有value取出,放入collection集合中
//Collection<Type>中Type的类型,取决于map中value类型
Collection<String> values = map.values();
System.out.println(values);
}
Map集合的迭代
//4.map集合的迭代方式一
/**
* 方式一:
* 遍历map中的数据,但是map本身没有迭代器,所以需要先转换成set集合
* Set<Key>:把map中的所有key值存入到set集合中--keySet()
*/
//4.1将map集合中的key值取出存入set集合中,集合的泛型就是key的类型Integer
Set<Integer> keySet = map.keySet();
//4.2想要遍历集合就需要获取集合的迭代器
Iterator<Integer> it = keySet.iterator();
//4.3循环迭代结合中的所有元素
while(it.hasNext()){//
Integer key = it.next();//拿到本轮循环中获取到的map的key
String value = map.get(key);
System.out.println("{"+key+","+value+"}");
}
/**方式二:
* 遍历map集合需要把map集合先转换成set集合
* 是把map中的一对键值对Key&value作为一个Entry<K,V>整体放入set中
* 一对K,V就是一个Entry
*/
Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
//获取迭代器
Iterator<Map.Entry<Integer,String>> it2 = entrySet.iterator();
while(it2.hasNext()){//
//本轮遍历到的一个Entry对象
Map.Entry<Integer,String> entry = it2.next();
Integer key = entry.getKey();//获取Entry中的key
String value = entry.getValue();//获取Entry中的Value
System.out.println("{"+key+","+value+"}");
HashMap
HashMap的键要同时重写hashCode()和equlas()
hashCode()用来判定二者的hash值是否相同,重写后根据属性生成
equlas()用来判断属性的值是否相同,重写后,根据属性判断
–equlas()判断数据如果相等,hashCode()必须相同
–equlas()判断数据如果不等,hashCode()尽量不同
HashMap的工作原理
HashMap底层是一个Entry[ ]数组,当存放数据时,会根据hash算法来计算数据的存放位置
算法:hash(key)%n , n就是数组的长度,其实也就是集合的容量
当计算的位置没有数据的时候,会直接存放数据
当计算的位置,有数据时,会发生hash冲突/hash碰撞,解决的办法就是采用链表的结构,在数组中指定位置处已有元素之后插入新的元素,也就是说数组中的元素都是最早加入的节点