目录
集合可以理解为可变长度的数组。
数组一定开辟大小,长度不可改变。
集合是可以根据向集合中增加数据,自动实现对集合进行扩容。
1 集合的功能
集合与数组一样,都是用来保存相同类型的大量数据。
使用集合,一般都会与泛型一起使用。使用泛型来约束集合中可以保存的数据类型。
2 集合的分类
在Java中根据集合的实现方式分为二个大类。
① 线性集合:java.util.Collection接口
所有集合中的数据都是按自身保存到集合中。
在Collection接口下面还有二个子接口:
java.util.List 有序,可重复。
java.util.Set 无序,不可重复。
② 键值映射:java.util.Map接口
所有集合中的数据(value),在保存到集合中时,都必须创建一个关键字(key)。
在Java集合中常用的接口有三个:List,Set,Map
3 集合常用的实现类
① ArrayList类:线性集合中,使用最多的一个类。就是一个可变长度的数组。
② LinkedList类:链表方式实现的线性集合。
③ HashSet类:Hash散列。
④ HashMap类:Hash算法的键值映射集合。按键找值。
⑤ TreeSet类:是一个有序的Set接口的实现类。
⑥ TreeMap类:是一个有序的Map接口的实现类。
3.1 ArrayList
① 通过构造方法来创建实例:ArrayList<String> strList = new ArrayList<>();
② 向容器中保存对象:strList.add(“”);
List集合是有序可重复。必须保证对象在集合中的顺序。默认以增加顺序为标准。
③ 从容器中取对象:String s = strlist.get(1);
List集合是有序。ArrayList是一个可变长度的数组。
集合中的每个对象,都有自己的索引。按索引取对象。
④ 动态获取集合大小:int i = strlist.size();
⑤ 对集合进行迭代:
版本一:老的方式
for(int i = 0 ;i < strlist.size();i++){
System.out.println(strlist.get(i));
}
版本二:forEach
for (String str : strlist) {
System.out.println(str);
}
3.2 HashSet类
Set接口中的常用类。
Set接口:无序,不可重复。
① 使用构造方法创建集合实例
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {public HashSet() {
map = new HashMap<>();
}}
② 增加集合元素的方法
public boolean add(E e) 添加时,会验证元素是否重复。
如何判断二个元素是不是重复? 调用二个方法:hashCode 和 equals 二个方法。
③ 获取集合元素个数
public int size()
④ 没有取值方法
因为Set集合无序。不保证顺序,没有索引。
获取方法:以前使用迭代器。现在有foreach的方式,迭代器基本不使用了。
⑤ 针对Set集合一般都是进行遍历操作
//foreach循环
for (String s: strSet) {
System.out.println(s);
}
//Iterator迭代器
Iterator<String> iterator = strSet.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
3.3 HashMap类
Map接口的常用类。Map接口是一种K-V结构。键值映射的集合接口。按键取值。
① 创建实例:HashMap<String , String> hashMap = new HashMap<>();
② 使用put方法添加元素
hashMap.put("点名员","闫凯");
hashMap.put("活动委员","徐萌");
hashMap.put("点名员","史志鹏");
添加元素时,必须保证HashMap集合中的key唯一,不可重复。
重复时直接覆盖原来的值。
③ 使用get方法按key取value
//按key取value
String name = hashMap.get("点名员");
System.out.println(name);
④ 迭代/遍历
版本一:使用键的集合。
使用keySet()方法,将集合中所有的key取出来,形成了一个Set集合。
Set<String> keySet = hashMap.keySet();
for (String key : keySet) {
String value = hashMap.get(key);
System.out.println(key+":"+value);
}
新版本:Entry<String,String>来表示一组Key-Value的映射。
entrySet这个集合中的第一个元素是一组 Key-Value类型 的Entry对象。
每一个Entry对象都包含的二个部分:Key 和 Value。
Set<Map.Entry<String, String>> entrySet = hashMap.entrySet();
for (Map.Entry<String, String> entry : entrySet ) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+":"+value);
}
3.4 LinkedList类
一个以链表方式实现的集合类。
在插入和删除操作时效率要快于ArrayList类。
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList();
linkedList.add("abc");
linkedList.addFirst("first");
linkedList.addLast("last");
System.out.println(linkedList);
}
3.5 TreeSet类
TreeSet是一个有序的Set接口的实现类。(Set无序)
每放一个对象到TreeSet集合中,就进行一次排序。找到正确的位置。
① 使用构造方法创建实例:public TreeSet()
TreeSet集合的构造方法,需要指定排序规则。
② 构造一个新的、空的数组,根据其元素的自然排序进行排序。
public TreeSet(Comparator<? super E> comparator)
③ 构造一个新的,空的树集,根据指定的比较器进行排序。
public static void main(String[] args) {
TreeSet<String> strSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
strSet.add("dd");
strSet.add("aaa");
strSet.add("c");
System.out.println(strSet);
}
3.6 hashCode()方法
hashCode()方法是返回当前对象的hash值。
Hash称为散列。一种数据结构。将一个容器按规则分成多个容器,之后可以快速从多个容器
的其中一个中查找数据。
HashSet与HashMap都是以散列的方式来保存数据。
HashSet还是一个不可重复的Set集合。
调用Set集合的add方法向容器中添加对象时,一定要验证是不是有重复,分两步:
先确定散列的盒子调用hashCode()方法。
再比较是否相等调用equals()方法。
3.7 Queue接口
是List接口的一个子接口。
表示是队列接口。队列是一种数据结构。先进先出(FIFO)。
LinkedList类就是Queue接口的实现类。
① boolean offer(E e):向队列中加对象。
② E poll():检索并删除此队列的头,如果此队列为空,则返回 null 。
③ E peek():检索但不删除此队列的头部,如果此队列为空,则返回 null 。
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
//这是一个队列 。先进先出。
queue.offer("a");
queue.offer("d");
queue.offer("c");
String peek = queue.peek();
System.out.println(peek);
String poll = queue.poll();
System.out.println(poll);
int size = queue.size();
System.out.println(size);
}
4. List集合的排序
本身List集合是有序的,可以对List集合中的元素进行排序操作。
4.1 String类型的集合的排序
针对List集合进行排序的方法是:Collections类的静态方法sort()
Collections.sort(strlist);//排序
System.out.println(strlist);
String类型的集合,为什么能被排序?
排序的前提是能比较大小。 String类的二个对象之间是可以进行比较的。
String类中比较大小的方法:public int compareTo(String anotherString)
返回值:int a.compareTo(b); (=0 a=b ;>0 a>b ;<0 a<b)
String 类的二个对象是通过调用compareTo方法的返回值进行大小的比较的。
String类能被比较大小是因为String类中实现了Comparable接口。
Comparable接口我们称为比较器接口。
4.2 比较器接口
比较器接口,表示了一种可以进行比较的能力。
任何类实现了比较器接口,都表示这个类具备了比较大小的能力。
在Java中提供了二个比较器接口:
① Comparable接口(内置比较器接口)
② Comparator接口(外置比较器接口)
4.2.1 内置比较器接口-Comparable
内置:是在实体类内部编写的比较规则。
public interface Comparable<T> {
public int compareTo(T o);
}
让Stu这个需要被比较的类,实现Comparable接口,重写compareTo方法。
public class Stu implements Comparable<Stu>{
private Integer id;
private String name;
private Double score;
@Override
/**
* 返回值的作用:
* >0 说明本对象大于o
* =0 说明本对象与o相等
* <0 说明本对象小于o
*/
public int compareTo(Stu o) {
return (this.id - o.id);//用学号比较
}
因为内置比较器是在实体类中编写的。所以比较的规则只能有一种。
4.2.2 外置比较器接口-Comparator
外置比较器接口是对内置比较器接口规则的扩展。
@FunctionalInterface
public interface Comparator<T> {int compare(T o1, T o2);
}
返回值:
>0 o1 > o2
=0 o1 = o2
<0 o1 < o2
外置比较器接口的使用。用一个非实体类去实现这个接口。
第一个这个接口的实现类,都是一种外置的比较规则。
/**
* 按学员姓名进行比较的外置比较器实现类
*/
public class StuNameComparator implements Comparator<Stu> {
@Override
public int compare(Stu o1, Stu o2) {
return o1.getName().compareTo(o2.getName());
}
}
/**
* 按学员成绩进行比较的外置比较器实现类
*/
public class StuScoreComparator implements Comparator<Stu> {
@Override
public int compare(Stu o1, Stu o2) {
if(o1.getScore() > o2.getScore()){
return 1;
}else{
return -1;
}
}
}
调用Collections类的静态方法sort进行排序时,指定外置比较器规则。
可以在main方法中写外置比较器,也可以单独在新建类中写。
public static void main(String[] args) {
Collections.sort(stuList,new StuScoreComparator());
System.out.println(stuList);
//按姓名的长度进行排序:外置比较器。
Collections.sort(stuList, new Comparator<Stu>() {
@Override
public int compare(Stu o1, Stu o2) {
return o1.getName().length() - o2.getName().length();
}
});
System.out.println(stuList);
}