1、集合概述
1.1、什么是集合?有什么用?
数组其实就是一个集合。集合实际上就是一个容器。可以来容纳其它类型的数据。
集合为什·么说在开发中使用较多?
集合是一个容器,是一个载体,可以一次容纳多个对象。在实际开发中,假设连接数据库,数据库当中有10条记录, 那么假设把这10条记录查询出来,在java程序中会将10条数据封装成10个java对象,然后将10个java对象放到某一个集合当中,将集合传到前端,然后遍历集合,将一个数据一个数据展现出来。
1.2、集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,
集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。)list.add(100); //自动装箱Integer
注意:
集合在java中本身是一个容器,是一个对象。
集合中任何时候存储的都是“引用”。
1.3、在java中每一个不同的集合,底层会对应不同的数据结构。
往不同的集合中存储元素,等于将数据放到了不同的数据结构当中。什么是数据结构?数据存储的结构就是数据结构。不同的数据结构,数据存储方式不同。例如:数组、二叉树、链表、哈希表...以上这些都是常见的数据结构。
你往集合c1中放数据,可能是放到数组上了。
你往集合c2中放数据,可能是放到二叉树上了。
.....
你使用不同的集合等同于使用了不同的数据结构。
你在java集合这一章节,你需要掌握的不是精通数据结构。java中已经将数据结构
实现了,已经写好了这些常用的集合类,你只需要掌握怎么用?在什么情况下选择
哪一种合适的集合去使用即可。
new ArrayList(); 创建一个集合,底层是数组。
new LinkedList(); 创建一个集合对象,底层是链表。
new TreeSet(); 创建一个集合对象,底层是二叉树。
1.4、集合在java JDK中哪个包下?
java.util.*;
所有的集合类和集合接口都在java.util包下。
1.5、集合的继承结构图
1.6、在java中集合分为两大类:
一类是单个方式存储元素:
单个方式存储元素,这一类集合中超级父接口:java.util.Collection;
一类是以键值对儿的方式存储元素
以键值对的方式存储元素,这一类集合中超级父接口:java.util.Map;
2、集合常用方法
2.1、collection
2.1.1collection集合常用方法
关于util.Collection里常用方法
* boolean add(Object o)
* int size()集合大小
* void clear()清空集合
* boolean contains()是否包含某元素
* remove(Object o);
* boolean isEmpty()
* Object[] toArray()
collection中能存放什么类型
* 没有使用泛型之前,collection可以存储object的子类型,使用泛型之后,只能存储某个具体的类型,不能存储基本数据类型,只能存java对象的内存地址。
常用方法代码如下:
public class CollectionDemo01 {
public static void main(String[] args) {
//collection是接口无法new
Collection c=new ArrayList();
//增加元素
c.add(1200);//自动装箱,实际上放进去一个内存地址,Integer a=new Integer(1200);
c.add(3.14);
System.out.println(c.size());
c.clear();
System.out.println(c.size());
c.add("张三");
c.add("李四");
System.out.println(c.contains("李四"));
c.remove("李四");
System.out.println(c.size());
System.out.println(c.isEmpty());
c.add("张三三");
c.add("李四三");
Object[] objects = c.toArray();
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
}
}
运行结果如下:
2
0
true
1
false
张三
张三三
李四三
2.1.2、迭代器使用
/**
* 关于集合遍历、迭代专题 重点
* 是所有collection通用的一种方式、
* 不适用map*/
public class CollectionDemo02 {
public static void main(String[] args) {
Collection c=new HashSet();
c.add("abc");
c.add(123);
c.add("张三");
c.add(new Object());
//对collection进行遍历迭代
//第一步获取迭代器
Iterator it=c.iterator();
/**
* boolean hasNext()
* 如果仍有元素可以迭代,则返回 true。
* E next()
* 返回迭代的下一个元素。
* void remove()
* 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。 */
//第二部通过以上或取得迭代器对象进行遍历
//迭代器最初并没有指向第一个元素
while(it.hasNext()){
//不管你当初存的是什么取的都是object
Object next = it.next();
System.out.print(next+" ");
}
}
}
运行结果如下:
java.lang.Object@776ec8df 张三 abc 123
2.1.3、set集合和list集合,前者无序不可重复,后者有序可重复
代码如下:
public class CollectionDemo03 {
public static void main(String[] args) {
Collection c=new ArrayList();//有序可重复
c.add("abc");
c.add(123);
c.add("张三");
c.add(123);
c.add(new Object());
Iterator it=c.iterator();
while(it.hasNext()){
Object next = it.next();
System.out.print(next+" ");
}
System.out.println();
System.out.println("################");
Collection c1=new HashSet();//无序不可重复
c1.add(45);
c1.add(22);
c1.add(33);
c1.add(4);
c1.add(4);
c1.add(new Object());
Iterator it1=c1.iterator();
while(it1.hasNext()){
Object next = it1.next();
System.out.print(next+" ");
}
}
}
输出如下:
abc 123 张三 123 java.lang.Object@404b9385
################
33 4 java.lang.Object@6d311334 22 45
2.1.4、深入contains()方法
底层调用了equals()方法,所以contains是判断是否包含某个元素,如即使对象不同,引用的字符串值相同,也是包含。
如果集合中存储String类型的值,由于String类重写了equals()方法,当调用contains()方法,底层会调用String类的equals()方法,才有以下结果。如果是自己写的实体类,用以下方式判断是否存在时,必须重写equals()方法。
代码如下:
/**
* 深入contains
* boolean contains(Object o)
* 如果此 collection 包含指定的元素,则返回 true。 */
/**
* 底层调用了equals()方法,所以contains是判断是否包含某个元素,如即使对象不同,引用的字符串值相同,也是包含*/
public class CollectionDemo04 {
public static void main(String[] args) {
Collection c =new ArrayList();
String s1 = new String("abc");
String s2 = new String("def");
c.add(s1);
c.add(s2);
System.out.println(c.size());
String x = new String("abc");
System.out.println("c.contains(x)->"+c.contains(x));
}
}
输出如下:
2
c.contains(x)->true
2.1.5、深入remove()方法
remove()底层也有调用equals()方法。
代码如下:
/**
* 测试contains方法
* 放在集合中的对象要重写equals方法
* 不重写比较的是对象的内存地址*/
public class CollectionDemo05 {
public static void main(String[] args) {
Collection c=new ArrayList();
User u1 = new User("jack");
User u2=new User("jack");
c.add(u1);
//没有重写equals方法,是false
System.out.println(c.contains(u2));
//remove有没有调用equals呢?有?
Collection cc=new ArrayList();
String s1=new String("abc");
cc.add(s1);
String s2=new String("abc");
cc.add(s2);
cc.remove(s2);
System.out.println(cc.size());
}
}
class User{
String name;
public User(){
}
public User(String name){
this.name=name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
输出如下:
true
1
2.1.6、集合只要发生改变,迭代器必须重写
代码如下:
/**
* 集合只要发生改变,迭代器必须重写
* ConcurrentModificationException*/
public class CollectionDemo06 {
public static void main(String[] args) {
Collection c=new ArrayList();
c.add(1);
c.add(2);
c.add("张三");
Iterator it=c.iterator();
while(it.hasNext()){
Object next = it.next();
//这样不行会报错!直接通过集合删除元素,没有通知迭代器,导致迭代器快照与集合不同
c.remove(next);
//用迭代器去删,这个方法一执行,先把快照内元素删掉,再去删掉集合里的元素
/*it.remove();*/
}
}
}
结果如下:
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
at com.wu.collection.CollectionDemo06.main(CollectionDemo06.java:18)
用迭代器去删,it.remove()这个方法执行,先把快照内元素删掉,再去删掉集合里的元素。
while(it.hasNext()){
Object next = it.next();
//这样不行会报错!直接通过集合删除元素,没有通知迭代器,导致迭代器快照与集合不同
/*c.remove(next);*/
//用迭代器去删,这个方法一执行,先把快照内元素删掉,再去删掉集合里的元素
it.remove();
}
2.1.7、Collections工具类
1、sort()方法升序排序,synchronizedList()将集合变为线程安全的。
代码如下:
public static void main(String[] args) {
// ArrayList集合不是线程安全的。
List<String> list = new ArrayList<>();
// 变成线程安全的
List<String> strings = Collections.synchronizedList(list);
// 排序
list.add("abf");
list.add("abx");
list.add("abc");
list.add("abe");
Collections.sort(list);
for(String s : list){
System.out.print(s+" ");
}
}
输出如下:
abc abe abf abx
2、如果集合中存储的是自定义的对象,如何排序?
注意:对List集合中元素排序,需要保证List集合中的元素实现了:Comparable接口。
先写一个实体类实现Conparable接口,重写compareTo()方法
class WuGui2 implements Comparable<WuGui2>{
int age;
public WuGui2(int age){
this.age = age;
}
@Override
public int compareTo(WuGui2 o) {
return this.age - o.age;
}
@Override
public String toString() {
return "WuGui2{" +
"age=" + age +
'}';
}
}
写测试类
public class CollectionsDemo01 {
public static void main(String[] args) {
List<WuGui2> wuGuis = new ArrayList<>();
wuGuis.add(new WuGui2(1000));
wuGuis.add(new WuGui2(8000));
wuGuis.add(new WuGui2(500));
// 注意:对List集合中元素排序,需要保证List集合中的元素实现了:Comparable接口。
Collections.sort(wuGuis);
for(WuGui2 wg : wuGuis){
System.out.print(wg+" ");
}
}
}
结果如下:
WuGui2{age=500} WuGui2{age=1000} WuGui2{age=8000}
3、对Set集合怎么排序呢?可以先转化为list集合
// 对Set集合怎么排序呢?
Set<String> set = new HashSet<>();
set.add("king");
set.add("kingsoft");
set.add("king2");
set.add("king1");
// 将Set集合转换成List集合
List<String> myList = new ArrayList<>(set);
Collections.sort(myList);
for(String s : myList) {
System.out.print(s+" ");
}
// 这种方式也可以排序。
//Collections.sort(list集合, 比较器对象);
输出如下
king king1 king2 kingsoft
2.1.8、ArrayList