集合类似于保存一组对象的存储库,是用来存储和管理其他对象的对象,即对象的容器。(与数组类似,一个集合可以存放很多元素,但与数组不同的是,集合的长度是可变的,而数组的长度是固定不变的;集合用来存放对象的引用,而数组用来存放基本数据类型;集合可以存储多种数据类型的数据,而数组只能存储单一类型的元素)。java集合可分为Collection和Map两种体系。
Map接口:双列数据,保存具有映射系"key-value对"的集合。
一. Collection接口Collection接口:单列数据,定义了存取一组独对象方法集合,Set代表无序的、不允许有重复的元素的集合;List代表有序的、允许有重复的元素的集合。
1.Collection接口中常用方法public boolean add(Object obj) //加入指定元素obj public boolean remove(Object obj) //移除指定元素obj public void clear() //清除所有元素 public boolean contains(Object obj) //判断是否包含元素obj public int size() //返回元素个数 public boolean isEmpty() //判断是否为空,若是返回true,否则返回false public Iterator iterator() //返回一个迭代器,指向当前类集合包含的元素 public boolean equals(Object o) //比较此 collection 与指定对象是否相等。 public Object[] toArray() //返回包含此 collection 中所有元素的数组。二.List接口
List接口是Collection的子接口,List接口允许有重复元素,而且它是有序的。List接口主的主要实现类有ArraryLise类、LinkedList类和Vector类。
ArraryList类实现了可变大小的数组,他允许存储所有的元素,包括null元素。其优点是可以快速定位List集中的数据、缺点是插入、删除对象是速度较慢。
LinkedList类采用链表存储对象,可以在收尾对数据对象进行操作,同样允许有null元素。
Vector类实现了可动态扩充的数组。像数组一样,它包含的元素可以通过数组下标来访问,但是,与数组不同的是,他的长度可以根据实际包含的元素个数增加或减少。(默认情况下,扩容为原来的1.5倍,同时需要将原有的数组中的数据复制到新的数组中)
1>list常用方法public void add(int index, E element) //在列表的指定位置插入指定元素(可选操作)。 public boolean addAll(int index, Collection extends E> c) //将指定 collection 中的所有元素都插入到列表中的指定位置。 public E get(int index) //返回列表中指定位置的元素。 public int indexOf(Object o) //返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。 public int lastIndexOf(Object o) //返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。 public ListIterator listIterator() //返回此列表元素的列表迭代器(按适当顺序)。 public E remove(int index) //移除列表中指定位置的元素(可选操作)。 public E set(int index, E element) //用指定元素替换列表中指定位置的元素(可选操作)。 public List subList(int fromIndex, int toIndex) //返回列表中指定的 fromIndex (包括 )和toIndex (不包括)之间的部分视图。2>ArrayList,LinkedList,Vector三者异同
ArrayList:作为List接口的主要实现类;线程不安全,效率高;底层使用自动变长数组。
LinkedList:对于频繁插入、删除操作,使用此类效率比ArrayList高;线程不安全;底层使用双向链表。
Vector:作为List接口的古老实现类,线程安全的、效率低。底层适应自动变长的数组
自动变长的数组(ArrayList list=new ArrayList();//底层创建了长度为10的数组,如果在添加过程中,导致数组容量不够,则自动扩容;扩容为原来的1.5倍,同时将原有数组中的数据复制到新的数组中)
ArrayList和LinkedList的异同
二者都是线程不安全,相对于Vector,执行效率高;
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和setArrayList优于LinkedList,因为LinkedList要移动指针。对于add和remove操作,LinkedList占优,因为ArrayList要移动数据。
ArrayList和Vector的区别
Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同 步类。因此开销就比ArrayList要大,访问要慢。
三.Set接口Set接口是Collection的子接口,Set接口中没有提供额外的方法Set集合不允许包含相同的元素,Set判断两个对象是否相等需要用equals()方法。
1.HashSetHashSet是Set接口的典型实现,大多数使用Set集合是都用HashSet来实现类。HashSet按Hash算法来存储集合中的元素,具有很好的存取、查找、删除性能。
1>HashSet特点不能保证元素的排列顺序。HashSet线程不安全。集合元素可以使null。
HashSet底层也是数组,初始容量为16,当如果使用率超过0.75,就会扩大容量为原 来的2倍。
HashSet集合两个对象的比较,不仅要通过hashCode()方法来进行比较,并且还用通过equals()方法来判断。即:“相等的对象必须具有相等的散列码”。
2>HashSet添加元素的过程当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该 对象在 HashSet 底层数组中的存储位置。如果此位置上没有其他元素,则元素添加成功。如果此位置上有其他元素,则比较俩元素的hash值。如果两个元素的hashCode()值相等,会再继续调 用equals方法,如果equals方法结果为true,添加失败;如果为false,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过链表的方式继续链接。如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们 存储在不同的位置,但依然可以添加成功。
2.LinkedListLinkedHashSet 是 HashSet 的子类。LinkedHashSet 根据元素的 hashCode 值来决 定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。 LinkedHashSet 同样不允许集合元素重复。
3.TreeSetTreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。TreeSet底层 使用红黑树结构存储数据。
排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关 系,然后将集合元素按升序(默认情况)排列如果试图把一个对象添加到 TreeSet 时,则该对象的类必须 实现 Comparable 接口。实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即 通过compareTo(Object obj) 方法的返回值来比较大小。
四.Map接口Map接口是与Collection接口并列存在的,主要用于存储“键-值(key-value)”对,不允许键重复,但允许值重复。Map接口的常用实现类:HashMap、TreeMap、Hashtable。
Map中的key,无序,不可重复,使用Set存储。
Map中的value,无序,可重复,使用Collection存储value。
一个键值对,key-value构成一个entry对象。Map中的entry,无序,不可重复的。使用 Set存储所有的entry。
1>Map接口常用的方法public void put(Object key,Object vale); //向列表中添加一对“键-值” public int siz(); //返回map中键值对的个数 public void clear(); //清空当前map中的所有数据 public Object get(Object key); //获取指定key对应的value public Object remove(Object key); //删除key对应的value public boolean containsKey(Object key); //是否包含指定的key public boolean containsValue(Object value); //是否包含指定的value public boolean isEmpty(); //判断map是否为空2>HashMap
是Map使用频率最高的实现类,允许有null键和null值,无序,线程不安全,效率高。
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相 等。HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。
JDK 7及以前版本:HashMap是数组+链表结构
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。
3>LinkedHashMapLinkedHashMap 是 HashMap 的子类在HashMap存储结构的基础上,使用了一对 双向链表来记录添加元素的顺序与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序: 迭代顺序与 Key-Value 对的插入顺序一致。
4>TreeMapTreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。TreeSet底层使用红黑树结构存储数据。TreeMap 的 Key 的排序:自然排序
5>HashtableHashtable是线 程安全的。Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快。但Hashtable 不允许使用 null 作为 key 和 value。
练习.用集合实现学生管理系统
public class Student {
private int id;
private String name;
private String sex;
private int score;
private static int inc = 100;
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getSex() {
return this.sex;
}
public void setScore(int score) {
this.score = score;
}
public int getScore() {
return this.score;
}
public Student() {
this.id = inc++;
}
public Student(String name, String sex, int score) {
this();
this.name = name;
this.sex = sex;
this.score = score;
}
}
import com.openlab.bean.Student;
import java.util.ArrayList;
import java.util.List;
public class StudentDao {
private static List list = new ArrayList();
static {
Student s1 = new Student("a", "男", 99);
Student s2 = new Student("b", "女", 87);
Student s3 = new Student("c", "男", 86);
Student s4 = new Student("d", "女", 93);
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
}
public List getData() {
return list;
}
public void add(Student stu) {
list.add(stu);
}
public Student find(int id) {
Student student = null;
for(int i = 0; i < list.size(); ++i) {
student = (Student)list.get(i);
if (id == student.getId()) {
break;
}
}
return student;
}
public void delete(Student student) {
list.remove(student);
}
}
package com.openlab.view;
import com.openlab.bean.Student;
import com.openlab.dao.StudentDao;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
public class StudentView {
Scanner scanner;
StudentDao dao;
public StudentView() {
this.scanner = new Scanner(System.in);
this.dao = new StudentDao();
}
public void menu() {
System.out.println("1.显示t2.添加t3.修改t4.删除t0.退出");
int input = this.scanner.nextInt();
switch (input) {
case 0:
System.out.println("谢谢使用");
break;
case 1:
this.show();
this.menu();
break;
case 2:
this.add();
this.menu();
break;
case 3:
this.update();
this.menu();
break;
case 4:
this.delete();
this.menu();
break;
default:
System.out.println("您的选择错误的,请重新选择");
this.menu();
}
}
public void show() {
List list = this.dao.getData();
Iterator var2 = list.iterator();
while(var2.hasNext()) {
Student student = (Student)var2.next();
System.out.println(student.getId() + "t" + student.getName() + "t" + student.getSex() + "t" + student.getScore());
}
}
public void add() {
System.out.println("请输入你的姓名");
String name = this.scanner.next();
System.out.println("请输入你的性别");
String sex = this.scanner.next();
System.out.println("请输入你的成绩");
int sorce = this.scanner.nextInt();
Student student = new Student(name, sex, sorce);
this.dao.add(student);
}
public void update() {
System.out.println("请输入你要学生修改的学号");
int id = this.scanner.nextInt();
Student s = this.dao.find(id);
if (s == null) {
System.out.println("学号有误!!!");
} else {
System.out.println("是否要修改姓名(y/n)");
String c1 = this.scanner.next();
String c2;
if (c1.equals("y")) {
System.out.println("请输入你要更正的姓名");
c2 = this.scanner.next();
s.setName(c2);
} else if (c1.equals("n")) {
System.out.println("---");
} else {
System.out.println("无效输入!!!");
}
System.out.println("是否要修改性别(y/n)");
c2 = this.scanner.next();
if (c2.equals("y")) {
if (s.getSex().equals("男")) {
s.setSex("女");
} else if (s.getSex().equals("女")) {
s.setSex("男");
}
} else if (c1.equals("n")) {
System.out.println("---");
} else {
System.out.println("无效输入!!!");
}
System.out.println("是否要修改成绩(y/n)");
String c3 = this.scanner.next();
if (c3.equals("y")) {
System.out.println("请输入你要更正的成绩");
int sorce = this.scanner.nextInt();
s.setScore(sorce);
} else if (c1.equals("n")) {
System.out.println("---");
} else {
System.out.println("无效输入!!!");
}
}
}
public void delete() {
System.out.println("请输入你要删除学生的学号");
int id = this.scanner.nextInt();
Student s = this.dao.find(id);
this.dao.delete(s);
}
}
package com.openlab.Test;
import java.util.ArrayList;
import java.util.List;
public class StudentTest {
public StudentTest() {
}
public static void main(String[] args) {
List Listlist1 = new ArrayList();
Listlist1.add(0);
System.out.println(Listlist1.get(0) instanceof Integer);
System.out.println(Listlist1.get(0) instanceof Integer);
}
}



