文章目录
1. 集合类概述
Java语言的java.util
包中提供了一些集合类,这些集合类又被称为容器。提到容器不难会想到数组,集合类与数组不同之处是,数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型的数据,集合用来存放对象的引用。常用的集合有List集合、Set集合、Map集合,其中List与Set实现了Collection接口。各接口还提供了不同的实现类。
2. Collection 接口
Collection接口是层次结构中的根接口。构成Collection的单位,被称之为元素。Collection接口通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。由于List接口与Set接口都继承了Collection接口,因此这些方法对List集合与Set集合是通用的。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo {
public static void main(String[] args) {
Collection c = new ArrayList();
System.out.println("集合是否为空:" + c.isEmpty() + ",集合长度:" + c.size());
c.add("你好");
c.add(3.14);
c.add(new Object());
System.out.println("集合是否为空:" + c.isEmpty() + ",集合长度:" + c.size());
c.remove(3.14);
System.out.println("集合是否为空:" + c.isEmpty() + ",集合长度:" + c.size());
Iterator it = c.iterator();
while (it.hasNext()) {
Object o = it.next();
System.out.println(o);
}
}
}
运行结果:
集合是否为空:true,集合长度:0
集合是否为空:false,集合长度:3
集合是否为空:false,集合长度:2
你好
java.lang.Object@4361bd48
3. List集合
List集合包括List接口及List接口的所有实现类。List集合中的元素允许重复,各元素的顺序就是对象插入的顺序。用户可以通过使用索引来访问集合中的元素。
3.1 List接口
List接口继承了Collection接口,因此包含Collection中的所有方法,此外,List接口还定义了以下两个非常重要的方法。
- get(int index):获得指定索引位置的元素。
- set(int index , Object obj):将集合中指定索引位置的对象修改为指定的对象。
3.2 List接口的实现类
List接口的常用实现类有ArrayList
与LinkedList
。
ArrayList
类实现了可变的数组,允许所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问。缺点是向指定的索引位置插入对象或删除对象的速度较慢。
LinkedList
类采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象,需要向集合中插入、删除对象时,使用LinkedList类实现的List集合的效率较好;但对于随机访问集合中的对象,使用LinkedList类实现List集合的效率较慢。
使用List集合时通常声明为List类型,可通过不同的实现类来实例化集合。
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
List list = new ArrayList();
list.add("清明时节雨纷纷");
list.add("孤家寡人欲断魂");
list.add("借问美女何处有");
list.add("牧童遥指三里屯");
list.remove(1);
list.add(1, "我插一句……");
list.set(1, "这句话我改了");
list.add("牧童遥指三里屯");
list.add("牧童遥指三里屯");
list.add("牧童遥指三里屯");
list.add(null);
for (int i = 0; i < list.size(); i++) {
System.out.println("list索引为" + i + "的元素:" + list.get(i));
}
System.out.println(list.size());
}
}
运行结果:
list索引为0的元素:清明时节雨纷纷
list索引为1的元素:这句话我改了
list索引为2的元素:借问美女何处有
list索引为3的元素:牧童遥指三里屯
list索引为4的元素:牧童遥指三里屯
list索引为5的元素:牧童遥指三里屯
list索引为6的元素:牧童遥指三里屯
list索引为7的元素:null
8
4. set 集合
Set集合中的对象不按特定的方式排序,只是简单地把对象加入集合中,但Set集合中不能包含重复对象。Set集合由Set接口和Set接口的实现类组成。Set接口继承了Collection接口,因此包含Collection接口的所有方法。
4.1 TreeSet
首先创建一个Person类:
public class Person implements Comparable {
int id;
int age;
String name;
public Person(int id, int age, String name) {// 点击Source->Generate Constructor using Fields
super();
this.id = id;
this.age = age;
this.name = name;
}
@Override
public String toString() {// 点击Source->Generate toString()
return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
}
@Override
public int compareTo(Object o) {
Person p;
if (o instanceof Person) {
p = (Person) o;
} else {
return -1;// 代表传入的参数比我本身小
}
int diff = this.id - p.id;
if (diff != 0) {
diff = diff / Math.abs(diff);// 差值除以本身绝对值,可以得到+1或-1
}
return diff;
}
}
然后创建一个Demo类:
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class Demo {
public static void main(String[] args) {
Set set = new TreeSet();
Person p1 = new Person(1, 18, "小明");
Person p2 = new Person(2, 5, "大壮");
Person p3 = new Person(3, 20, "阿强");
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p1);// 重复的元素不会被添加到集合中
// set.add(null);// TreeSet不能添加null值
System.out.println(set.size());
Iterator it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
得到结果:
3
Person [id=1, age=18, name=小明]
Person [id=2, age=5, name=大壮]
Person [id=3, age=20, name=阿强]
可以看到,这里是根据id进行排序的。如果需要按照年龄排序,可以如下操作:
@Override
public int compareTo(Object o) {
Person p;
if (o instanceof Person) {
p = (Person) o;
} else {
return -1;// 代表传入的参数比我本身小
}
int diff = this.age - p.age;
if (diff != 0) {
diff = diff / Math.abs(diff);// 差值除以本身绝对值,可以得到+1或-1
}
return diff;
}
将其中的id改为age即可,得到结果:
3
Person [id=2, age=5, name=大壮]
Person [id=1, age=18, name=小明]
Person [id=3, age=20, name=阿强]
4.2 HashSet
创建Person类:
public class Person {
int id;
String name;
public Person(int id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {// Source->Generate hashCode() and equals() 注意只勾选id
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (id != other.id)
return false;
return true;
}
}
创建Demo类:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo {
public static void main(String[] args) {
Set set = new HashSet();
Person p1 = new Person(1, "小明");
Person p2 = new Person(2, "大壮");
Person p3 = new Person(3, "阿强");
Person p4 = new Person(2, "大壮");
set.add(p1);
set.add(p2);
set.add(p3);
// set.add(null);// 与TreeSet不同,HashSet可以添加null
// p2.id = 5;
// set.remove(p2);// id为5的hashCode,导致删除无效
p2.name = "奥特曼";
set.remove(p2);
set.add(p4);
System.out.println("集合的长度:" + set.size());
Iterator it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
运行结果:
集合的长度:3
Person [id=1, name=小明]
Person [id=2, name=大壮]
Person [id=3, name=阿强]
Hash算法比较复杂,建议回看原视频。
5. Map集合
Map集合没有Collection接口,其提供的是Key到value的映射。Map中不能包含相同的key,每个key只能映射一个value。key还决定了存储对象在映射中的存储位置,但不时有key对象本身决定的,而是通过一种“散列技术”进行处理,产生一个散列码的整数值。散列码通常用作一个偏移量,该偏移量对应分配给映射的内存区域的起始位置,从而确定存储对象在映射中的存储位置。Map集合包括Map接口以及Map接口的所有实现类。
5.1 Map接口
Map接口提供了将key映射到值的对象。一个映射不能包含重复的key,每个key最多只能映射到一个值。Map接口中同样提供了集合的常用方法,除此之外还包括如下表所示的常用方法。
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class UpdateStu {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();// 创建Map实例
map.put("01", "李同学");// 向集合中添加对象
map.put("02", "魏同学");
Set<String> set = map.keySet();// 构建Map集合中所有key对象的集合
Iterator<String> it = set.iterator();
System.out.println("key集合中的元素:");
while (it.hasNext()) {// 遍历集合
System.out.println(it.next());
}
Collection<String> coll = map.values();// 构建Map集合中所有value对象的集合
it = coll.iterator();
System.out.println("value集合中的元素:");
while (it.hasNext()) {// 遍历集合
System.out.println(it.next());
}
}
}
运行结果:
key集合中的元素:
01
02
value集合中的元素:
李同学
魏同学
5.2 Map接口的实现类
Map接口常用的实现类有HashMap
和TreeMap
。建议使用HashMap类实现Map集合,因为由HashMap类实现的Map集合对于添加和删除映射关系效率更高。HashMap是基于哈希表的Map接口的实现,HashMap通过哈希码对其内部的映射关系进行快速查找;而TreeMap中的映射关系存在一定的顺序,如果希望Map集合中的对象也存在一定的顺序,应该使用TreeMap类实现Map集合。
首先创建Emp类:
public class Emp {
private String e_id;
private String e_name;
public Emp(String e_id, String e_name) {
this.e_id = e_id;
this.e_name = e_name;
}
public String getE_id() {
return e_id;
}
public void setE_id(String e_id) {
this.e_id = e_id;
}
public String getE_name() {
return e_name;
}
public void setE_name(String e_name) {
this.e_name = e_name;
}
}
在创建MapText类:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class MapText {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();// 由HashMap实现的Map对象
Emp emp = new Emp("351", "张雨绮");// 创建emp对象
Emp emp2 = new Emp("512", "李健");
Emp emp3 = new Emp("853", "王源");
Emp emp4 = new Emp("125", "尼古拉斯赵四");
Emp emp5 = new Emp("341", "黄贯中");
map.put(emp4.getE_id(), emp4.getE_name());// 将对象添加到集合中
map.put(emp5.getE_id(), emp5.getE_name());
map.put(emp.getE_id(), emp.getE_name());
map.put(emp2.getE_id(), emp2.getE_name());
map.put(emp3.getE_id(), emp3.getE_name());
Set<String> set = map.keySet();// 获取Map集合中的key对象集合
Iterator<String> it = set.iterator();
System.out.println("HashMap类实现的Map集合,无序:");
while (it.hasNext()) {
String str = (String) it.next();
String name = (String) map.get(str);
System.out.println(str + " " + name);
}
TreeMap<String, String> treemap = new TreeMap<>();// 创建TreeMap集合对象
treemap.putAll(map);
Iterator<String> iter = treemap.keySet().iterator();
System.out.println("TreeMap类实现的Map集合,键对象升序:");
while (iter.hasNext()) {
String str = (String) iter.next();
String name = (String) treemap.get(str);
System.out.println(str + " " + name);
}
}
}
运行结果:
HashMap类实现的Map集合,无序:
341 黄贯中
125 尼古拉斯赵四
512 李健
853 王源
351 张雨绮
TreeMap类实现的Map集合,键对象升序:
125 尼古拉斯赵四
341 黄贯中
351 张雨绮
512 李健
853 王源