一、简介
将一系列相同类型的数据聚集在一起
在Java中集合用户存储一系列的数据,和数组相同
集合和数组的区别:
- 数组是定长的,集合是可变长的,集合的长度由存储数据的个数来决定
- 集合提供了更多的对数据进行操作的方式,使用起来更加方便
二、集合的体系结构
体系结构
Collection和Map的区别
- Collection对数据的存储采用的是线性结构,类似于数组
- Map对数据的存储采用的是键值对(key–value)通过key可以锁定一个value
List和Set的区别
-
List
有序的集合,数据的存储位置和放入顺序一致
可以存放重复的值 -
Set
无序的集合,数据的存放位置和放入顺序无关,会根据特殊的要求指定数据存放的位置
不可以存放重复的值
三、ArrayList
常用方法
public static void main(String[] args) {
//<T> 泛型
//指定当前集合对象存储的数据的类型
//集合只能存储引用类型的数据
//创建了一个集合对象 该对象存储整数
List<Integer> list = new ArrayList<Integer>();
System.out.println(list);
//1.添加数据
list.add(3);
list.add(4);
System.out.println(list);
//2.删除
list.remove(0);//根据下标删除
System.out.println(list);
//3.修改
list.set(2, 5);
System.out.println(list);
//4.根据下标查询
Integer num = list.get(0);
System.out.println(num);
//5.获取集合的长度
int size = list.size();
System.out.println(size);
//6.清空集合中的数据
list.clear();
//7.判断集合中是否存在指定的数据
boolean contains = list.contains(4);
System.out.println(contains);
//8.找出指定元素在集合中第一次出现的下标 没有则返回-1
int index = list.indexOf(3);
System.out.println(index);
//9.找出指定元素在集合中最后一次出现的下标 没有则返回-1
int lastIndex = list.lastIndexOf(3);
System.out.println(lastIndex);
//10.判断集合中是否有数据
boolean empty = list.isEmpty();
System.out.println(empty);
}
集合的遍历
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i = 0;i < list.size();i++) {
System.out.println(list.get(i));
}
}
四、Vector
Vector和ArrayList使用方式完全一样
ArrayList和Vector的区别
- 从使用者的角度而言没有任何区别
- 内部对数据的存储方式有区别
- ArrayList线程不安全,存储效率高
- Vector线程安全,存储效率低
五、Stack
栈集合,先进后出
public static void main(String[] args) {
Stack<Integer> stack = new Stack<Integer>();
stack.push(3);//进栈
stack.push(6);
Integer num = stack.pop();//出栈
Integer num1 = stack.pop();//出栈
System.out.println(num);//6
System.out.println(num1);//3
}
六、LinkedList
ArrayList和LinkedList的区别:
- 数据结构
- ArrayList采用的是数组
- LinkedList采用的是链表结构
- 操作性能
- ArrayList更适合查询的操作
- LinkedList更适合增删的操作
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
//在链表的首尾添加数据
list.addFirst(3);
list.addLast(5);
}
七、HashSet
常用方法
public static void main(String[] args) {
//数据的位置和放入的顺序无关 不能存放相同的值
//在set集合中 没有下标的概念
HashSet<Integer> set = new HashSet<Integer>();
set.add(7);
set.add(6);
set.add(4);
set.add(9);
set.add(9);
System.out.println(set);
//删除指定的值
boolean remove = set.remove(7);
System.out.println(set);
//修改 先删再增
}
哈希散列表
- HashSet是如何寻找数据位置以及判断数据是否重复的
1、当我们向HashSet集合中存放数据(调用add方法)时,该方法中会自动调用待添加对象的HashCode方法,得到当前对象的Hash值
2、JVM虚拟机根据得到的hash值使用哈希算法进行计算,得到了当前对象应该存放在哈希散列表中的位置
3、如果当前位置没有元素,立即放入
4、如果当前位置有元素,则调用待添加对象的equals方法和当前位置中的元素进行比较
5、如果返回的结果为true 表示当前对象和已存入的对象是相同的 将待添加对象直接丢弃
6、如果返回的结果为false 将待添加对象以外链的形式追加到当前位置
- 第6种情况不允许出现 所以重写equals方法时必须重写hashCode方法
- 保证两个对象如果相同 则hash值必定相同 如果hash值相同 则两个对象必定相同
public static void main(String[] args) {
Set<User> set = new HashSet<>();
User u1 = new User("张豆豆");
User u2 = new User("吃豆豆");
set.add(u1);
set.add(u2);
System.out.println(u1.equals(u2));
System.out.println(u1.hashCode());
System.out.println(u2.hashCode());
System.out.println(set);
}
八、迭代器
迭代器(iterator)的作用:对集合进行遍历
实现了Iterable
接口的类都拥有迭代器
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<Integer>();
set.add(7);
set.add(6);
set.add(4);
set.add(9);
set.add(10);
//获取需要遍历的集合的 迭代器
Iterator<Integer> iterator = set.iterator();
//迭代器相当于是一根指针
//判断指针所在位置的下一行是否有数据
// System.out.println(iterator.hasNext());
//1.获取指针指向的下一行中的数据 2.将指针向下移动一行
// System.out.println(iterator.next());
//一般依次循环 只让指针移动一次
while(iterator.hasNext()) {
Integer num = iterator.next();
System.out.println(num);
}
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(1);
list.add(1);
list.add(1);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
Integer num = iterator.next();
System.out.println(num);
if(num == 1) {
//删除当前指针指向的元素
iterator.remove();
}
}
}
九、增强for循环
本质上就是迭代器
foreach
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(1);
list.add(1);
list.add(1);
Iterator<Integer> iterator = list.iterator();
// while(iterator.hasNext()) {8678
// Integer num = iterator.next();
// System.out.println(num);
// }
//将每一次循环指针指向的值 赋值给num
//Integer num 相当于Integer num = iterator.next();
//list 指定需要遍历的集合
//当我们不需要使用下标时建议使用增强for
for(Integer num : list) {
System.out.println(num);
}
}
十、TreeSet
1.HashSet和TreeSet
- 存储值的方式不同
- HashSet是根据哈希值计算对象存放的位置
- TreeSet是根据**树形结构(排序从小到大)**计算对象存储的位置
- 排序
- 将待添加对象和已经存在的所有对象一一比较
- 根据比较的结果存放到对应的位置
- 如果比较结果相同则将待添加对象舍弃
- 操作性能
- HashSet保存值的性能更优
- TreeSet比较值的性能更优
- 存放值的区别
- HashSet可以存放null值
- TreeSet不可以存放null
2.使用方式
public static void main(String[] args) {
TreeSet<Integer> set = new TreeSet<Integer>();
set.add(5);
set.add(2);
System.out.println(set);
}
3. Comparable
放入TreeSet中的对象必须可以被排序(比大小)
反过来说,想要存放到TreeSet中的对象必须具备可以被比较的能力
在Java中 我们通常让一个类实现某一种接口 表示这个类具备该种能力
Comparable<数据类型>
- 接口
- 表示可以被排序
- <数据类型>
- 指定和什么类型的数据比较大小
/*
* 表示当前类可以被排序
*/
public class User implements Comparable<User> {
String name;
int age;
public User() {
}
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
return false;
}
/*
* 定义排序的规则
* 当前对象 和 o进行比较
* 1 大
* -1 小
* 0 相同
*/
@Override
public int compareTo(User o) {
if(this.age > o.age) {
return 1;
}
if(this.age < o.age) {
return -1;
}
return 0;
}
十一、HashMap
1.使用方式
public static void main(String[] args) {
//创建Map集合时 需要指定 键和值的类型
HashMap<Integer,String> map = new HashMap<Integer,String>();
//添加
map.put(2, "小明");
map.put(3, "大狗");
//删除
map.remove(2);
//查询
System.out.println(map.get(3));
//修改 key值是不能重复存在的 当存放相同的key时新的value会覆盖旧的value
map.put(3, "二蛋");
System.out.println(map);
}
2.总结
- HashMap的key就是HashSet key不可重复且无序 根据哈希值寻找key存放的位置
- value是可以重复的
- Map采用的是键值对的形式,一个key对应了一个value
3.Map的遍历
public static void main(String[] args) {
//创建Map集合时 需要指定 键和值的类型
HashMap<Integer,String> map = new HashMap<Integer,String>();
//添加
map.put(2, "张三");
map.put(3, "李四");
map.put(4, "王五");
map.put(5, "赵六");
System.out.println(map);
//方式一
//获取所有的key组成的Set集合
// Set<Integer> keys = map.keySet();
// for(Integer key : keys) {
// System.out.println(key + ":" + map.get(key));
// }
//方式二
//将key和value构建成了一个叫做Entry的对象 该对象中有一个key属性 还是有个value属性
Set<Entry<Integer, String>> entrySet = map.entrySet();
for(Entry entry : entrySet) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
十二、HashTable
- HashTable使用方式和HashMap完全一致
- HashTable线程安全,效率低
- HashMap线程不安全,效率高
十三、TreeMap
- TreeMap的key采用的是TreeSet
- TreeMap中的key必须可以被排序