第三部分Java SE-Java应用
第5单元 集合部分学习笔记
Part1 动手做
一、集合的背景
1.什么是集合?
集合类是Java数据结构的实现,位于java.util包中。它允许以各种形式将元素分组,并定义了各种使这些元素更容易操作的方法。集合类是可以往里面保存多个对象的类,存放的是对象,不同的集合类有不同的特点和功能。
2.什么东西可以容纳多个对象?
-
答:数组、集合。
-
数组中放的对象个数是不是固定的,集合里面的对象个数是动态的。数组放置的数据类型是单一的,集合可以放任何类型对象。
3.Java集合框架结构
- java.util.Collection (接口)
- 分两大类:第一类是List和Set ;第二类是Map。
- Map没有继承Collection
二、集合类图
集合里放什么?
- 答:放对象。
三、List集合的使用
1.创建List集合-放字符串对象
- 泛型,语法是<类型> ,List
- 泛型就是标签
- 使用泛型目的是方便从集合中取对象
- size()方法得到集合里对象的实际个数
- List有序列表,可重复。简单来说就是有序可重复。
import java.util.ArrayList;
import java.util.List;
//List集合-放字符串对象
public class StringList {
public static void main(String[] args) {
//创建List集合,左侧List是接口,<>是Java泛型,说明strList里只能放字符串
//ArrayList是类,该类实现了List接口
List<String> strList = new ArrayList<String>();
//添加对象到集合,使用add方法
strList.add("李琦");
strList.add("杨敏");
strList.add("学文");
strList.add("李琦");
//获取集合里对象的个数
System.out.println("集合里对象的个数是:" + strList.size());
System.out.println("集合里的对象是:" + strList);
}
}
- 执行结果能看出List集合可重复,有次序,放进去的次序和输出是一样的:
//集合里对象的个数是:4
//集合里的对象是:[李琦, 杨敏, 学文, 李琦]
2.List集合放对象(Student对象)-List集合遍历的3种方式
- add(); list.add(“hello”);
- List list = new ArrayList();
- List list = new ArrayList(15);
- ArrayList() 默认初始容量是10
//Student对象
public class Student {
private String name;
private int age;
private String sid;
public Student() {
super();
}
public Student(String name, int age, String sid) {
super();
this.name =name;
this.age = age;
this.sid = sid;
}
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// List集合放对象
public class StudentList {
public static void main(String[] args) {
Student s1 = new Student("张三", 21, "2016");
Student s2 = new Student("李四", 22, "2015");
Student s3 = new Student("张三", 21, "2016");
//使用泛型约定 该集合里只能放Student类的对象
List<Student> stuList = new ArrayList<Student>();
stuList.add(s1);//添加对象到集合
stuList.add(s2);
stuList.add(s3);
//遍历集合,从集合里取数据:方式一
for (int i = 0; i < stuList.size(); i++) {
Student student = stuList.get(i);
System.out.println(student);
}
//遍历集合,从集合里取数据:方式二,-for-each循环
for (Student student : stuList) {
System.out.println(student);
}
//遍历集合,从集合里取数据:方式三
Iterator it = stuList.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
System.out.println(s);
}
System.out.println("集合里对象的个数是:" + stuList.size());
}
}
- 单次输出结果为:这是对象的地址,三次new就会产生3个对象,因此有3个地址。
//com.ychs.corejava.javaseunit6.Student@15db9742
//com.ychs.corejava.javaseunit6.Student@6d06d69c
//com.ychs.corejava.javaseunit6.Student@7852e922
3.输出集合看到的是对象属性值,而不是地址
只需要在Student类中重写toString()方法即可。
public class Student {
private String name;
private int age;
private String sid;
public Student() {
super();
}
public Student(String name, int age, String sid) {
super();
this.name =name;
this.age = age;
this.sid = sid;
}
//重写toString方法,可以自动生成
public String toString() {
return "Student [name" + name + ",age=" + age + ",sid=" + sid + "]";
}
}
- 再次执行结果如下:
//Student [name张三,age=21,sid=2016]
//Student [name李四,age=22,sid=2015]
//Student [name张三,age=21,sid=2016]
四、Set集合的使用
- Set集合:无序不可重复,没有索引,没有get(i)
1.Set中放字符串
- HashSet()
import java.util.HashSet;
import java.util.Set;
//Set集合的使用:创建一个Set集合中仅能放字符串并遍历
public class SetDemo {
public static void main(String[] args) {
//多态,Set是接口,HashSet是类,实现了Set接口,用泛型指定只能是字符串
Set<String> set = new HashSet<String>();
set.add("hello");
set.add("123");
set.add("hello");//重复元素
set.add("tit");
System.out.println("Set中对象的个数:" + set.size());
//使用for-each循环遍历Set集合,Set集合没有get(i)方法
for (String str : set) {
System.out.println(str);
}
}
}
2.Set中放Student对象
import java.util.HashSet;
import java.util.Set;
// Set中放Student对象
public class StudentSet {
public static void main(String[] args) {
Set<Student> studentSet = new HashSet<Student>();
Student s1 = new Student("张三", 21, "2016");
Student s2 = new Student("李四", 22, "2015");
Student s3 = new Student("张三", 21, "2016");
studentSet.add(s1);
studentSet.add(s2);
studentSet.add(s3);
System.out.println("Set中对象的个数:" + studentSet.size());
System.out.println(studentSet);
}
}
- 发现“张三”是重复的,没有去掉。
//Set中对象的个数:3
//[Student [name张三,age=21,sid=2016], Student [name张三,age=21,sid=2016], Student [name李四,age=22,sid=2015]]
3.Set中放Student对象,去掉重复对象
重写Student的equals方法和hashCode方法
import javax.print.attribute.standard.MediaSize.Other;
//Student对象
public class Student {
private String name;
private int age;
private String sid;
public Student() {
super();
}
public Student(String name, int age, String sid) {
super();
this.name =name;
this.age = age;
this.sid = sid;
}
@Override //重写hashCode方法
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((sid == null) ? 0 : sid.hashCode());
return result;
}
@Override //重写equals方法
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Student other = (Student) obj;
if (age != other.age) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
} else if (!name.equals(other.name))
return false;
if (sid == null) {
if (other.sid != null) {
return false;
} else if (!sid.equals(other.sid))
return false;
}
}
return true;
}
//重写toString方法,可以自动生成
public String toString() {
return "Student [name" + name + ",age=" + age + ",sid=" + sid + "]";
}
}
- 此时,运行结果就是2个对象了,重复的只保留了一个。
4.利用HashSet去掉List中的重复对象-利用Set不可重复性
重写Student的equals方法和hashCode方法,Student类和上边的一样。
用Set集合包装List,使用构造方法。
常用在:Hibernate中
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class StudentList {
public static void main(String[] args) {
Student s1 = new Student("张三", 21, "2016");
Student s2 = new Student("李四", 22, "2015");
Student s3 = new Student("张三", 21, "2016");
//使用泛型约定 该集合里只能放Student类的对象
List<Student> stuList = new ArrayList<Student>();
stuList.add(s1);//添加对象到集合
stuList.add(s2);
stuList.add(s3);
System.out.println("集合里对象的个数是:" + stuList.size());
//创建Set集合
Set<Student> stuSet = new HashSet<Student>(stuList);
System.out.println("集合里对象的个数是:" + stuSet.size());
//遍历集合,从集合里取数据:方式三,遍历器,遍历集合里的对象
Iterator it = stuSet.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
System.out.println(s);
}
}
}
五、Map集合的使用-存放一个学生的信息
- HashMap无序的
- Map是独立的接口,由键-值(Key-Value)对构成。
- put():往里边放东西
- get():取东西
- size():获知大小
- 和Collection没关系,无继承关系。
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
//Map集合的使用-存放一个学生的信息
public class MapDemo {
public static void main(String[] args) {
Map map = new HashMap();
map.put("学号", "2016");
map.put("姓名", "张三");
map.put("sex", "男");
map.put("sex", "女");//重复的key,覆盖原有的key
map.put(null, null);//允许key是空
System.out.println("map对象的个数:" + map.size());
System.out.println(map.get("sex"));
System.out.println(map.get("学号"));
Set keys = map.keySet();//取map里所有的key
System.out.println("所有的key:" + keys);
}
}
六、链表-LinkedList(类)的用法
- 与Java数据结构有关
- 来自java.util包
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> str = new LinkedList<String>();
str.add("123");
str.add("a");
str.add("b");
str.add("09");
str.removeFirst();//删除第一个
System.out.println(str);
}
}
- 用Java实现链表
public class PersonLink {
public static void main(String[] args) {
Node node1 = new Node("张三", 20);
Node node2 = new Node("李四", 21);
Node node3 = new Node("王五", 25);
node1.next = node2;
node2.next = node3;
}
}
class Node {
String name;
int age;
// 节点构造方法
public Node(String name, int age) {
super();
this.name = name;
this.age = age;
}
Node next;
}
七、栈的使用Stack
- Stack是类,先进后出
- Queue队列,是接口,先进先出
- push():入栈
- pop():出栈
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
Stack<String> s = new Stack<String>();
s.push("A");//入栈
s.push("B");
s.push("C");
System.out.println("出栈次序:");
System.out.print(s.pop() + "、");
System.out.print(s.pop() + "、");
System.out.println(s.pop());
}
}
八、Collection和Collections区别
- Collection是接口,代表集合
- Collections是类,集合实用类,位于java.util包,提供了一系列方法对集合做操作
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectioonDemo {
public static void main(String[] args) {
List<String> all = new ArrayList<String>();//创建List集合
Collections.addAll(all, "开行大厦", "Java");//一次性将字符串集合到all中
System.out.println(all);
int point = Collections.binarySearch(all, "ychs");//检索数据
System.out.println("索引是:" + point);
}
}
Part2 理解并口述(面试题)
一、LIst、Set和Map的区别?
- List:放到里边的对象有次序,可以重复。
- Set:放到里边的对象无次序,不可重复。
- List和Set都继承自Collection接口。
- Map:是独立的接口,内容由键-值构成(Key - Value)
二、ArrayList、Vector、Hashtable、HashMap、HashSet、TreeSet各自的特点
1.ArrayList与Vector的区别
-
Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它 的方法之间是线程不同步的。
-
如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
-
ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定。
-
ArrayList与Vector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而ArrayList没有提供设置增长空间的方法
2.Hashtable
- 线程安全,Key-Value不能为null
- 数组和链表实现的
- 初始容量:11
- 扩容:x*2 + 1;
3.HashMap
- 非线程安全,Key-Value可以是null
- 数组和链表实现
- 初始容量:16
- 扩容:x * 2
4.ConcurrentHashMap:表示并发
- 线程安全,但效率比Hashtable高。
5.HashSet
- 非同步(非线程安全)
- 添加的对象可以是null
6.TreeSet
- 非同步
- 有序的
三、Collection和Collections区别
- Collection是接口,代表集合
- Collections是类,集合实用类,位于java.util包,提供了一系列方法对集合做操作
四、如何去掉List中的重复对象
- 首先重写类当中的两个方法equals和hashCode,然后用set用它进行构造。
五、ArrayList底层是如何实现的?
- 数组和列表实现
六、ArrayList的初始容量?容量能否动态增长?
- 初始容量是10,可以动态增长。
七、泛型是什么?有什么作用?
- 泛型就是标签,类型参数化,JDK1.5提供的;目的是方便从集合中取对象。
- 数组和链表实现
- 初始容量:16
- 扩容:x * 2
4.ConcurrentHashMap:表示并发
- 线程安全,但效率比Hashtable高。
5.HashSet
- 非同步(非线程安全)
- 添加的对象可以是null
6.TreeSet
- 非同步
- 有序的
三、Collection和Collections区别
- Collection是接口,代表集合
- Collections是类,集合实用类,位于java.util包,提供了一系列方法对集合做操作
四、如何去掉List中的重复对象
- 首先重写类当中的两个方法equals和hashCode,然后用set用它进行构造。
五、ArrayList底层是如何实现的?
- 数组和列表实现
六、ArrayList的初始容量?容量能否动态增长?
- 初始容量是10,可以动态增长。
七、泛型是什么?有什么作用?
- 泛型就是标签,类型参数化,JDK1.5提供的;目的是方便从集合中取对象。