集合框架List、Set、Map

集合框架的继承关系

在这里插入图片描述
Collecton接口常用的子接口有:List接口、Set接口
List接口常用的子类有:ArrayList类、LinkedList类
Set接口常用的子类有:HashSet类、LinkedHashSet类
List允许有重复的元素,有序。
Set不予许有重复元素,无序。

Collection接口概述
既然Collection接口是集合中的顶层接口,那么它中定义的所有功能子类都可以使用,是共性的功能,是集合中所有实现类必须拥有的方法。
所有我们学习的时候首先从父类Collection开始,然后再学习子类中特有的内容。
Collection接口的基本方法
在这里插入图片描述

创建集合的格式:
方式1:Collection<元素类型> 变量名 = new ArrayList<元素类型>();
方式2:Collection 变量名 = new ArrayList();
方式1创建的集合,只能存储<>中指定的元素类型,该方式为常用方式
方式2创建的集合,集合的元素类型默认为Object类型,即任何类型的元素都可以存储。

public void test1() {
   Collection<String> collection = new ArrayList<>();
   collection.add("张三");
   collection.add("李四");
   collection.add("王五");
   collection.add("张三");
   System.out.println(collection);
   collection.remove("张三");
   System.out.println(collection);
   Object[] array = collection.toArray();
   for (int i = 0; i < array.length; i++) {
     System.out.print(array[i] + "  ");
   }
}

[张三, 李四, 王五, 张三]
[李四, 王五, 张三]
李四 王五 张三

Iterator迭代器

迭代:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。

Iteration的常见方法
在这里插入图片描述
在Collection接口描述了一个抽象方法iterator方法,所有Collection子类都实现了这个方法,并且有自己的迭代形式。
在这里插入图片描述

public void test2() {
   Collection<String> collection = new ArrayList<>();
   collection.add("张三");
   collection.add("李四");
   collection.add("王五");
   collection.add("张三");
   Iterator<String> iterator = collection.iterator();
   while (iterator.hasNext()) {//判断有没有下一个,有下一个返回true
     String data = iterator.next();//用来返回迭代的下一个元素,并把指针向后移动一位
     System.out.println(data);
   }
}


List接口特点(也是所有实现类的特点):

1、它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
2、它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
3、 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

List接口的常用子类有:

ArrayList集合
LinkedList集合

ArrayList:
1、增加元素方法
add(Object e):向集合末尾处,添加指定的元素
add(int index, Object e):向集合指定索引处,添加指定的元素,原有元素依次后移
2、删除元素删除
remove(Object e):将指定元素对象,从集合中删除,返回值为被删除的元素
remove(int index):将指定索引处的元素,从集合中删除,返回值为被删除的元素
3、替换元素方法
set(int index, Object e):将指定索引处的元素,替换成指定的元素,返回值为替换前的元素
4、查询元素方法
get(int index):获取指定索引处的元素,并返回该元素

public void ttt() {
   List<String> list = new ArrayList<String>();
   list.add("1");
   list.add("2");
   list.add("3");
   list.add("4");
   list.add("5");
   for (String item : list) {
     if (item.equals("3")) {
        System.out.println(item);
        list.remove(item);
     }
   }
   System.out.println(list.size());
}

遍历的时候移除使用Iterator里面的remove方法。
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
   String data = (String) iterator.next();
   if (data.equals("3")) {
     // 不管在foreach还是Iterator遍历过程中都不允许使用list改变长度
      // 如果是移除元素,可以使用Iterator里面的remove,但是对于添加
      // Iterator就没有提供,可以参考ListIterator
     iterator.remove();
     System.out.println(data);
   }
}
System.out.println(list.size());

LinkedList

LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法.
在这里插入图片描述

Vector

Vector集合数据存储的结构是数组结构,为JDK中最早提供的集合。Vector中提供了一个独特的取出方式,就是枚举Enumeration,它其实就是早期的迭代器。此接口Enumeration的功能与 Iterator 接口的功能是类似的。Vector集合已被ArrayList替代。枚举Enumeration已被迭代器Iterator替代。

Vector & ArrayList比较

相同点:Vector与ArrayList本质上都是一个Object[] 数组,都实现了List这个接口
不同点:
1)Vector是线程安全的集合类,ArrayList并不是线程安全的类。Vector类对集合的元素操作时都加了synchronized,保证线程安全。
2)Vector与ArrayList的扩容并不一样,Vector默认扩容是增长一倍的容量,Arraylist是增长50%的容量。ArrayList就有利于节约内存空间。
Vector无论查询还是增删都很慢,所以被ArrayList替代了。

Set接口:

HashSet:

无序:HashSet集合不能保证的迭代顺序与元素存储顺序相同。
不重复:HashSet集合,采用哈希表结构存储数据,保证元素唯一性的方式依赖于两个方法:hashCode()与equals()方法。


散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数.
HashSet元素不能重复,如何实现

当向哈希表中存放元素时,需要根据元素的特有数据结合相应的算法,这个算法其实就是Object类中的hashCode方法。由于任何对象都是Object类的子类,所以任何对象有拥有这个方法。即就是在给哈希表中存放对象时,会调用对象的hashCode方法,算出对象在表中的存放位置,这里需要注意,如果两个对象hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中。


总结:保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。 给HashSet中存储JavaAPI中提供的类型元素时,不需要重写元素的hashCode和equals方法,因为这两个方法,在JavaAPI的如String类、Integer类已经重写了hashCode和equal方法。
public void test551() {
  // 创建HashSet对象
   Set<String> set = new HashSet<String>();
   // 给集合中添加自定义对象
   set.add("zhangsan");
   set.add("lisi");
   set.add("wangwu"); 
   set.add("zhangsan");
   set.add(new String("lisi"));
   for (String string : set) {
      System.out.println(string);
   }
}

lisi
zhangsan
wangwu

因为HashSet默认是根据变量的地址判断是不是已经加入HashSet了。
这样的话:
Student stu1 = new Student(1, “张三”, 20);
Student stu2 = new Student(1, “张三”, 20);
stu1和stu2都能够加入HashSet里面,因为他们的地址不一样,但是这其实是同一个Student,
只是分别通过不同的方式new出来,如果stu1和stu2都能够加入的话,那么这个学生就在HashSet里面重复了。
所有的类都继承自Object类,Object类里面有hashCode和equal这两个方法,

HashSet调用add方法时候判断这个对象有没有已经在Set里面就是根据hashCode和equal方法
解决方法就是:我们自己来判断是不是已经存在,选择你要比较的属性,覆写hashCode和equal方法

自定义类型(如果要使用HashSet,必须手动实现hashCode和equals):
能不能放进Set里面,首先看hashCode值是不是一样,如果不一样就可以放进去,
如果hashCode值一样,再比较equals是不是一样,如果不一样就可以放进去

测试:
public void test66() {
   HashSet<Student> set = new HashSet<>();
   set.add(new Student(1, "zhangsan1", 21));
   set.add(new Student(2, "zhangsan2", 22));
   set.add(new Student(3, "zhangsan3", 23));
   set.add(new Student(4, "zhangsan4", 24));
   set.add(new Student(2, "zhangsan2", 22));
   Iterator<Student> iterator = set.iterator();
   while (iterator.hasNext()) {
     Student student = iterator.next();
     System.out.println(student);
   }
}
结果:
Student [id=3, name=zhangsan3,  age=23]
Student [id=4, name=zhangsan4,  age=24]
Student [id=1, name=zhangsan1,  age=21]
Student [id=2, name=zhangsan2,  age=22]

LinkedHashSet介绍

我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序?
在HashSet下面有一个子类LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。

public void test4() {
   Set<String> set = new LinkedHashSet<String>();
   set.add("bbb");
   set.add("aaa");
   set.add("abc");
   set.add("bbc");
   Iterator it = set.iterator();
   while (it.hasNext()) {
     System.out.println(it.next());
   }
}

TreeSet:

java中的TreeSet是Set的一个子类,TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一。
需要指定比较的规则,需要在自定义类(Student)中实现Comparable接口,并重写接口中的compareTo方法

public class Student implements Comparable<Student>{
   private Integer id;
   private String name;
   private Integer age;
   
  //两个Student怎么比较大小
  @Override
   public int compareTo(Student o) {
       return 0;  //当compareTo方法返回0,元素值每次比较,都认为是相同的元素
       return >0;  //当compareTo方法返回值正数,元素值每次比较,都认为新插入的元素比上一个元素大,读取时就是正序排列的
       return <0; //当compareTo方法返回值负数,元素值每次比较,都认为新插入的元素比上一个元素小,读取时就是倒序排列的
   }
}
按照年龄来排序,年龄相同按照名字排序
public int compareTo(Student o) {
    int num = this.age - o.age;                //年龄是比较的主要条件
    return num == 0 ? this.name.compareTo(o.name) : num;//姓名是比较的次要条件
}

按照姓名长度排序:
public int compareTo(Student o) {
    int length = this.name.length() - o.name.length();              //比较长度为主要条件
    int num = length == 0 ? this.name.compareTo(o.name) : length;    //比较内容为次要条件
    return num == 0 ? this.age - o.age : num;                        //比较年龄为次要条件
}

Map接口

1、Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。
2、Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
3、Collection中的集合称为单列集合,Map中的集合称为双列集合。
4、需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
5、Map中常用的集合为HashMap集合、LinkedHashMap集合
在这里插入图片描述

HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。


LinkedHashMap
public static void main(String[] args) {
   // 创建Map对象
   Map<String, String> map = new HashMap<String, String>();
   // 给map中添加元素
   map.put("星期一", "Monday");
   map.put("星期日", "Sunday");
   System.out.println(map); // {星期日=Sunday, 星期一=Monday}
   // 根据指定的key获取对应的value
   String en = map.get("星期日");
   System.out.println(en); // Sunday
   // 根据key删除元素,会返回key对应的value值
   String value = map.remove("星期日");
   System.out.println(value); // Sunday
   System.out.println(map); // {星期一=Monday}
}

Map集合遍历键找值方式:

一、键找值方式:即通过元素中的键,获取键所对应的值

1.获取Map集合中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键在这里插入图片描述
2.遍历键的Set集合,得到每一个键
3.根据键,获取键所对应的值
在这里插入图片描述

public void test1() {
   // 创建Map对象
   Map<String, String> map = new HashMap<String, String>();
   // 给map中添加元素
   map.put("邓超", "孙俪");
   map.put("李晨", "范冰冰");
   map.put("刘德华", "柳岩");
   // 获取Map中的所有key
   Set<String> keySet = map.keySet();
   // 遍历存放所有key的Set集合
   Iterator<String> it = keySet.iterator();
   while (it.hasNext()) {
     // 得到每一个key
     String key = it.next();
     // 通过key获取对应的value
     String value = map.get(key);
     System.out.println(key + "=" + value);
   }
}

二、Map集合遍历键值对方式

键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
1.获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。
在这里插入图片描述

2.遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象
3.通过键值对(Entry)对象,获取Entry对象中的键与值。
在这里插入图片描述
在这里插入图片描述

public void test2() {
   // 创建Map对象
   Map<String, String> map = new HashMap<String, String>();
   // 给map中添加元素
   map.put("邓超", "孙俪");
   map.put("李晨", "范冰冰");
   map.put("刘德华", "柳岩");
   // 获取Map中的所有key与value的对应关系
   Set<Map.Entry<String, String>> entrySet = map.entrySet();
   // 遍历Set集合
   Iterator<Map.Entry<String, String>> it = entrySet.iterator();
   while (it.hasNext()) {
     // 得到每一对对应关系
     Map.Entry<String, String> entry = it.next();
     // 通过每一对对应关系获取对应的key
     String key = entry.getKey();
     // 通过每一对对应关系获取对应的value
     String value = entry.getValue();
     System.out.println(key + "=" + value);
   }
}

Collections集合工具类 Arrays

在这里插入图片描述
public static void sort(List list) // 集合元素排序

//排序前元素list集合元素 [33,11,77,55]
Collections.sort( list );
//排序后元素list集合元素 [11,33,55,77]

public static void shuffle(List<?> list) // 集合元素存储位置打乱

//list集合元素 [11,33,55,77]
Collections.shuffle( list );
//使用shuffle方法后,集合中的元素为[77,33,11,55],每次执行该方法,集合中存储的元素位置都会随机打乱

排序操作:
void reverse(List list):反转
void shuffle(List list),随机排序
void sort(List list),按自然排序的升序排序
void sort(List list, Comparator c);定制排序,由Comparator控制排序逻辑
void swap(List list, int i , int j),交换两个索引位置的元素
void rotate(List list, int distance),旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面。
查找,替换操作:
int binarySearch(List list, Object key), 对List进行二分查找,返回索引,注意List必须是有序的
int max(Collection coll),根据元素的自然顺序,返回最大的元素。 类比int min(Collection coll)
int max(Collection coll, Comparator c),根据定制排序,返回最大元素,排序规则由Comparatator类控制。类比int min(Collection coll, Comparator c)
void fill(List list, Object obj),用元素obj填充list中所有元素
int frequency(Collection c, Object o),统计元素出现次数
int indexOfSubList(List list, List target), 统计targe在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List source, list target).
boolean replaceAll(List list, Object oldVal, Object newVal), 用新元素替换旧元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值