1.集合框架
1.1为什么使用集合
当我们需要保存相同的数据时,需要使用一个容器来进行保存,这个容器就是数组。但是数组会存在很多的弊端,例如:只能存储相同类型的数据;声明之后不能再修改长度;数据存储是有序的、可重复的,特点单一。最重要的是,在我们实际开发中,储存的数据的类型是多种多样的,所以我们就需要一个新的容器来进行数据的存储,“集合”及时这个容器。
1.2集合的架构
1.3List集合
1.3.1添加元素
// 导入List和ArrayList包
import java.util.ArrayList;
import java.util.List;
// 创建集合对象
List list = new ArrayList();// 默认长度为10
list.add("星期一");
list.add("星期二");
list.add("星期三");
System.out.println(list);
list.add(1,"今天休息");// 在指定位置添加内容
System.out.println(list);
List list1 = new ArrayList();
list1.add(1);
list1.add(2);
list.add(list1); // 将list1中的元素全部添加进list中
System.out.println(list);
1.3.2删除元素
list.remove(2);// 删除制定下标的元素
System.out.println(list);
list.clear(); // 清空集合元素
System.out.println(list);
1.3.3修改元素
list.set(1,"星期二放假");
System.out.println(list);
1.3.4查找元素
//查找操作
Object o = list.get(1);// 根据下标查找
System.out.println(o);
int size = list.size();// 获取集合元素的个数
System.out.println(size);
boolean s = list.contains("星期天");// 查询指定元素 以Boolean值返回
System.out.println(s);
int index = list.indexOf("星期一"); //查询元素在集合中第一次出现的位置
System.out.println(index);
// 使用for循环遍历集合中的元素
for (int i = 0; i < list.size(); i++) {
Object o1 = list.get(i);
System.out.println(o1);
}
1.4 LinkedList
LinkedList是一个链表结构
1.4.1添加元素
// 创建LinkedList
LinkedList linkedList = new LinkedList();
//添加元素
linkedList.add("星期一"); // 添加到尾部
linkedList.addFirst("星期二");// 添加到头部
linkedList.addLast("星期三");// 添加到尾部
linkedList.addFirst("星期四");//添加到头部
System.out.println(linkedList);
1.4.2删除元素
linkedList.remove(2); // 以下标删除元素
System.out.println(linkedList);
linkedList.removeFirst();// 删除第一个元素
System.out.println(linkedList);
linkedList.removeLast();//删除最后一个元素
System.out.println(linkedList);
1.4.3修改元素
linkedList.set(2,"星期五");//修改制定下标的元素
System.out.println(linkedList);
1.4.4查找元素
int size = linkedList.size();// 查询集合长度
System.out.println(size);
Object o = linkedList.get(1);// 查找指定下标的元素
System.out.println(o);
Object first = linkedList.getFirst();// 查询第一个元素
System.out.println(first);
Object last = linkedList.getLast();// 查询最后一个元素
System.out.println(last);
1.4.5LinkedList的底层源码
public LinkedList() {
}//该类的构造方法内是空的,没有任何的代码。 但是该类中有三个属性。
transient int size = 0; //索引
transient Node<E> first;// 第一个元素对象
transient Node<E> last;// 表示最后一个元素对象
==============add的源码==========E:可以理解为object=========
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
// l:上一个节点 e:数据 null:下一个节点
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
============Node的源码============================
private static class Node<E> {
E item;
Node<E> next; // 下一个节点
Node<E> prev;// 上一个节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
==============get()获取元素================
public E get(int index) {
checkElementIndex(index); // 检查index的下标是否正确
return node(index).item;// 返回index下标的Node对象
}
=============node(index)====================
Node<E> node(int index) {
// >>:位运算,二进制运算 size >> 1 :相当于size/2
if (index < (size >> 1)) {// 前半部分
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else { // 后半部分
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
LinkedList查询效率低,是因为它查找数据时需要一个节点一个节点的向后查找
1.5 Set集合
1.5.1 HashSet集合
1.5.1.1创建HashSet对象
// 导入HashSet包
import java.util.HashSet;
public class Test02 {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
HashSet hashSet1 = new HashSet(16); // 设置初始容器的大小
// loadFactor:---> 0.7f表示负载因子,当空间使用到70%时,要求扩容
HashSet hashSet2 = new HashSet(10,0.7f);
}
}
1.5.1.2添加元素
// 添加元素
hashSet.add("星期一");
hashSet.add("星期二");
hashSet.add("星期三");
hashSet.add("星期四");
System.out.println(hashSet);
HashSet set = new HashSet();
set.add("一月");
set.add("二月");
set.add("三月");
hashSet.addAll(set);
System.out.println(hashSet);
1.5.1.3 删除元素
// 删除元素
hashSet.remove("一月"); // 因为是乱序放入,所以删除元素需要指定该元素
System.out.println(hashSet);
hashSet.clear(); // 清空集合中的所有元素
System.out.println(hashSet);
1.5.1.4 查找元素
// 查找元素
boolean empty = hashSet.isEmpty();// 判断集合是否为空,以布尔值返回
System.out.println(empty);
boolean b = hashSet.contains("三月");// 判断该元素是否在集合中,以布尔值返回
System.out.println(b);
1.5.1.5 hashSet的遍历
//遍历
// foreach 遍历
for (Object o:hashSet){
System.out.println(o);
}
// 迭代器遍历
Iterator iterator = hashSet.iterator(); // 获取迭代器对象
while (iterator.hasNext()){ // 判断指针是否能够移动
Object next = iterator.next(); // 指针移动并获取当前的元素
System.out.println(next);
}
1.5.1.6 hashSet的源码
public HashSet() {
map = new HashMap<>();
}
//在创建一个HashSet的对象时,底层创建的是HashMap。所以HashMap的底层原理就是hashset的底层原理。
1.5.2 TreeSet集合
TreeSet中的方法和HashSet中的方法一模一样,只是他们的实现不一样。 TreeSet 基于TreeMap 实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现。
// 存储String类型
TreeSet treeSet = new TreeSet();
treeSet.add("周二");
treeSet.add("周一");
treeSet.add("周三");
treeSet.add("周二");
treeSet.add("周三");
System.out.println(treeSet);
// 存储一个对象类型
public class Test04 {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();//TreeSet不允许重复元素
treeSet.add(new Student("孙悟空",18));
treeSet.add(new Student("猪八戒",17));
treeSet.add(new Student("沙僧",17));
treeSet.add(new Student("白龙马",16));
System.out.println(treeSet);
}
}
// 发现: TreeSet中的元素必须实现Comparable接口 方可放入TreeSet
在String中实现了Comparable接口才能接收数据,所以需要在Student类中也实现该接口
//实现Comparable接口解决问题
import java.util.TreeSet;
public class Test04 {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();//TreeSet不允许重复元素
treeSet.add(new Student("孙悟空",18));
treeSet.add(new Student("猪八戒",17));
treeSet.add(new Student("沙僧",17));
treeSet.add(new Student("白龙马",16));
System.out.println(treeSet);
}
}
class Student implements Comparable{
// 设置私有属性
private String name;
private Integer age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Student(String name,Integer age){
this.name = name;
this.age = age;
}
public Student(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public int compareTo(Object o) {
Student student = (Student) o;
System.out.println(this+"=======>"+o);
// age作为对比对象,this.age大则放后面
if (this.age>student.age){
return 1;
}
// age作为对比对象,this.age小则放前面
if (this.age<student.age){
return -1;
}
// age作为对比对象,this.age相同则不写入集合
return 0;
}
}
第二种解决方式,也是最常使用的,就是在创建TreeSet时指定其排序规则,自己对其排序规则进行定义,这样就能避免对已定义好的类进行修改。
//定义MyComparator类,为TreeSet指定排序规则
import java.util.Comparator;
public class MyComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
if (s1.getAge()>s2.getAge()){
return 1;
}else if (s1.getAge()<s2.getAge()){
return -1;
}else {
return 0;
}
}
}
import java.util.TreeSet;
public class Test04 {
public static void main(String[] args) {
// 调用MyComparator类为TreeSet指定排序规则
TreeSet treeSet = new TreeSet(new MyComparator());
treeSet.add(new Student("孙悟空",18));
treeSet.add(new Student("猪八戒",17));
treeSet.add(new Student("沙僧",17));
treeSet.add(new Student("白龙马",16));
System.out.println(treeSet);
}
}
class Student {
// 设置私有属性
private String name;
private Integer age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Student(String name,Integer age){
this.name = name;
this.age = age;
}
public Student(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
1.6 Map
map中得每个元素属于键值对模式。 如果往map中添加元素时,需要添加key 和 value. 它也属于一个接口,该接口常见得实现类有: HashMap.
1.6.1创建Map对象
import java.util.HashMap;
import java.util.Map;
public class Test01 {
public static void main(String[] args) {
Map map = new HashMap();// 默认初始大小为16,负载因子为0.75,可自己进行修改
Map map1 = new HashMap(20);//设置初始空间大小
Map map2 = new HashMap(20,0.7f);//设置初始大小和负载因子
}
}
1.6.2添加元素
//添加操作 key value
map.put("孙悟空",500);
map.put("猪八戒",600);
map.put("沙悟净",600);
map.put("白龙马",400);
System.out.println(map);
map.put("猪八戒",18);
System.out.println(map);
map1.put("张三",18);
map1.put("李四",18);
map.putAll(map1);// 将map1中元素全部添加到map中
System.out.println(map);
map.putIfAbsent("孙悟空",20);// 如果指定的key存在则不添加,不存在则添加
System.out.println(map);
1.6.3删除元素
//删除操作
map.remove("白龙马");//根据指定的key值进行与对应元素的移除
System.out.println(map);
map.clear();// 清空容器
System.out.println(map);
1.6.4修改元素
// 修改元素
// 通过对应的key值修改元素,也可以直接使用put进行添加,只要key值相同就可以直接进行覆盖
map.replace("白龙马",18);
System.out.println(map);
1.6.5查找元素
// 查找元素
boolean s = map.containsKey("孙悟空");//根据指定key值查找元素,返回Boolean值
System.out.println(s);
Object o = map.get("孙悟空");//根据指定的key值获取对应的value值
System.out.println(o);
Object f = map.get("唐僧");// key值不存在,对应的value值为null
System.out.println(f);
Set keys = map.keySet();//返回map中的所有key
System.out.println(keys);
//遍历map
for (Object k:keys){
Object o1 = map.get(k);
System.out.println(o1);// 根据获得key值,输出对应的value值
}