一、集合框架
集合架构
• Collection 接口存储一组不唯一,无序的对象
• List 接口存储一组不唯一,有序(索引顺序)的对象
• Set 接口存储一组唯一,无序的对象
• Map接口存储一组键值对象,提供key到value的映射
• Key 唯一 无序
• value 不唯一 无序
二、List集合
List集合的主要实现类有ArrayList和LinkedList,分别是数据结构中顺序表和链表的实现。另外还包括栈和队列的实现类:Deque和Queue。
List
1.特点:有序 不唯一(可重复)
ArrayList
1.在内存中分配连续的空间,实现了长度可变的数组
2.优点:遍历元素和随机访问元素的效率比较高
3.缺点:添加和删除需大量移动元素效率低,按照内容查询效率低
LinkedList
1.采用双向链表存储方式。
2.缺点:遍历和随机访问元素效率低下
3.优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发生在头尾可以减少查询次数)
2.1 ArrayList
ArrayList底层就是一个长度可以动态增长的Object数组;(StringBuilder底层就是一个长度可以动态增长的char数组)
public static void main(String[] args) {
//ArrayList<Integer> list = new ArrayList<>();
List<Integer> list = new ArrayList<>();
Collections.synchronizedList(list);//变成线程安全的
//list集合就是线程安全的了.
list.add(123);//自动装箱
list.add(124);
list.add(125);
System.out.println(list);
/*list.add(222);
list.add(1,444);
System.out.println(list);*/
List<Integer> list3 = new ArrayList<>();
list3.add(1);//自动装箱
list3.add(2);
list3.add(3);
list.addAll(list3);
//list.addAll(2,list3);
System.out.println(list);
//修改
//list.set(0,888);
//获取
//Integer num = list.get(1);
//System.out.println(num);
//删除
//list.remove(0);//根据下标进行移除
//list.remove(new Integer(123));//根据内容进行删除,注意如果是整数类型标识内容的时候,必须显示的写出当前的包装类,否则认为是下标.
//list.removeAll(list);把集合内容清空
//list.clear();//把集合内容清空
boolean empty = list.isEmpty();//判断集合内容是否为空
//System.out.println(empty);
//集合的长度
int size = list.size();
//判断
int i = list.indexOf(12);//跟据内容返回数组中第一次出现该元素下标,如果元素内容不存在返回-1
boolean contains = list.contains(1233);//判断集合中是否包含指定元素,如果包含返回是true,否则返回false
System.out.println(contains);
System.out.println(list);
}
public static void main(String[] args) {
//集合中也可以保存集合
List<List<Integer>> list = new ArrayList();
List<Integer> list1 = new ArrayList<>();
list1.add(1);//自动装箱
list1.add(2);
list1.add(3);
List<Integer> list2 = new ArrayList<>();
list2.add(11);//自动装箱
list2.add(12);
list2.add(13);
list.add(list1);
list.add(list2);
System.out.println(list);
//集合的遍历
for (int i = 0; i < list.size(); i++) {
List<Integer> li = list.get(i);
for (int j = 0; j < li.size(); j++) {
System.out.println(li.get(j));
}
}
}
2.2LinkedList
LinkedList底层结构是一个双向链表。
public static void main(String[] args) {
//List<Integer> list = new LinkedList<>();
LinkedList<Integer> list = new LinkedList<>();
//System.out.println("======LinkedList中常用方法======");
//添加
/*list.add(1);
list.add(2);
list.add(3);*/
System.out.println("======LinkedList中特有方法======");
/*list.addFirst(1);头插法
list.addFirst(2);
list.addFirst(3);*/
list.addLast(1);//尾插法
list.addLast(2);
list.addLast(3);
//获取头结点值 NoSuchElementException
Integer first = list.getFirst();
//获取尾结点值 NoSuchElementException
Integer last = list.getLast();
//获取头结点值 如果头结点是null 不会保存 返回值null
Integer integer = list.peekFirst();
//获取尾结点值 如果尾结点是null 不会保存 返回值null
Integer integer1 = list.peekLast();
//移除头结点 NoSuchElementException
list.removeFirst();
//移除尾结点 NoSuchElementException
list.removeLast();
//移除头结点 如果没有元素返回是null 不会报错
list.pollFirst();
//移除尾结点 如果没有元素返回是null 不会报错
list.pollLast();
//Stack<String> stack = new Stack<>();
System.out.println(list);
}
三、Set
3.1 Set集合类型
Set
• 特点:无序 唯一(不重复)
HashSet (底层是 数组+链表+红黑树===》哈希表)
• 采用Hashtable哈希表存储结构(神奇的结构)
• 优点:添加速度快 查询速度快 删除速度快
• 缺点:无序
LinkedHashSet (底层是 链表+哈希表)
• 采用哈希表存储结构,同时使用链表维护次序
• 有序(添加顺序)
TreeSet (底层数据结构 红黑树)
• 采用二叉树(红黑树)的存储结构
• 优点:有序 查询速度比List快(按照内容查询)
• 缺点:查询速度没有HashSet快
创建一个学生类
package com.atguigu.collection3;
import java.util.Objects;
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getAge() == student.getAge() &&
Objects.equals(getName(), student.getName());
}
//保证唯一的方式
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
HashSet用法:
package com.atguigu.collection3;
import java.util.HashSet;
import java.util.Set;
/**
* set集合中保存一个对象 Student对象
* HashSet底层是哈希表 哈希表保证元素唯一的方式通过两个方法 equals()/hashCode()
* hashCode():计算hash码值 如果两个对象相同 他们的hashCode()一定相同
* equals() 在存储hash表的时候判断值是否唯一
* 如果我们定义的对象 保存到HashSet 集合中一定要重写对象的equals()/hashCode()
*/
public class TestSet2 {
public static void main(String[] args) {
Set<Student> set = new HashSet<>();
set.add(new Student("zs",19));
set.add(new Student("李四",19));
set.add(new Student("王五",19));
set.add(new Student("王五",19));
System.out.println(set);
Student stu1 = new Student("王五",19);
Student stu2 = new Student("王五",19);
System.out.println(stu1.hashCode());
System.out.println(stu2.hashCode());
}
}
TreeSet用法:
package com.atguigu.collection3;
import java.util.Set;
import java.util.TreeSet;
/**
* TreeSet --Student对象保存在TreeSet中
* TreeSet底层是红黑树 红黑树底层进行存储的时候会进行值的比较,在进行值的比较的时候使用就是Comparable(比较器)
* 调用存入对象的Comparable(内部比较器) compareTo方法比较的 通过返回值进行判断呢 正数 负数 0
*/
public class TestSet3 {
public static void main(String[] args) {
//默认内补比较器进行比较存值
Set<Student> set = new TreeSet<>();
set.add(new Student("张三",12));
set.add(new Student("李四",15));
set.add(new Student("王五",19));
set.add(new Student("王五2",19));
System.out.println(set);
Student stu = new Student("李四",18);
Student stu1 = new Student("王五",16);
int i = stu.compareTo(stu1);
System.out.println(i);
//创建外部比较器
//内部比较器是我们可以在操作类源码的前提下可以直接修改代码
//如果我们不可以改源码,这个时候如何进行对象比较呢,需要使用外部比较器
MyCompar myCompar = new MyCompar();
TreeSet<Teacher> set2 = new TreeSet<>(myCompar);
Teacher tea = new Teacher("zs",12);
Teacher tea1 = new Teacher("zs",19);
set2.add(tea);
set2.add(tea1);
int compare = myCompar.compare(tea, tea1);
System.out.println(compare);
System.out.println(set2);
}
}
创建外部比较器:
package com.atguigu.collection3;
import java.util.Comparator;
/**
* 外部比较器
*/
public class MyCompar implements Comparator<Teacher> {
@Override
public int compare(Teacher o1, Teacher o2) {
return o1.getAge() - o2.getAge();
}
}
总结
- HashSet 哈希表 唯一 无序
- LinkedHashSet 哈希表+链表 唯一 有序(添加顺序)
- TreeSet 红黑树 一种二叉平衡树 唯一 有序(自然顺序)
- List针对Collection增加了一些关于索引位置操作的方法 get(i) add(i,elem),remove(i),set(i,elem)
- Set是无序的,不可能提供关于索引位置操作的方法,set针对Collection没有增加任何方法
- List的遍历方式:for循环、for-each循环、Iterator迭代器、流式编程forEach
- Set的遍历方式: for-each循环、Iterator迭代器、流式编程forEach
四、Map
4.1 Map集合类型
Map
• 特点:存储的键值对映射关系,根据key可以找到value
HashMap (底层是Hash表)
• 采用Hashtable哈希表存储结构(神奇的结构)
• 优点:添加速度快 查询速度快 删除速度快
• 缺点:key无序
LinkedHashMap (底层是 链表+Hash表)
• 采用哈希表存储结构,同时使用链表维护次序
• key有序(添加顺序)
TreeMap (底层是红黑树)
• 采用二叉树(红黑树)的存储结构
• 优点:key有序 查询速度比List快(按照内容查询)
• 缺点:查询速度没有HashMap快
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
Map<Integer, String> map2 = new TreeMap<>();
Map<Integer, String> map3 = new LinkedHashMap<>();
System.out.println("======HashMap表保存值情况=========");
map.put(1,"bj");
map.put(2,"bj2");
map.put(1,"bj3");
map.put(null,"bj4");
map.put(null,"bj5");//Hash表中是允许保存空对象
System.out.println(map);//HashMap中如果K相同了 后者的V就会把前者相同K的V进行覆盖
System.out.println("======TreeMap表保存值情况=========");
map2.put(1,"bj");
map2.put(2,"bj2");
map2.put(1,"bj3");
//map2.put(null,"bj4");//TreeMap中是不允许Key值出现空对象情况
System.out.println(map2);
}
map遍历方式:
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1,"zs1");
map.put(2,"zs2");
map.put(3,"zs3");
map.put(4,"zs4");
map.put(5,"zs5");
//遍历方式一 获取map集合的所有的key
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
System.out.println(key + "---" + map.get(key));
}
//遍历方式二 直接获取map集合的value 所有的value直接遍历
Collection<String> values = map.values();
for (String value : values) {
System.out.println(value);
}
//遍历方式三
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for (Map.Entry<Integer, String> entry : entrySet) {
System.out.println(entry.getKey() + "---" + entry.getValue());
}
}
结果: