集合
一:集合概念
对象的容器,实现了对对象常用的操作,类似数组功能。
二:集合和数组的区别
(1)数组长度固定,集合长度不固定。
(2)数组可以存储基本类型和引用类型,集合只能引用类型。
Collection体系集合
Collection父接口
特点
代表一组任意的类型的对象,无序、无下标、不能重复。
方法
-
boolean add(Object obj)//添加一个对象。
-
boolean addAll(Collection c)//将一个集合中的所有对象添加到此集合中。
-
void clear()//清空此集合中的所有对象。
-
boolean contains(Object o)//检查此集合中是否包含o对象。
-
boolean equals(Object o)//比较此集合是否与指定对象相等。
-
boolean isEmpty()//判断此集合是否为空。
-
boolean remove(Object o)//在此集合中移除o对象。
-
int size()//返回此集合中的元素个数。
-
Object[] toArray()//将此集合转换成数组。
迭代器(专门用来遍历集合的一种方式)
Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包括了可以返回迭代器实例的迭代方法。
hasNext()判断有没有下一个元素。
next()获取下一个元素。
remove()删除当前元素。
Collection的使用(1)
/**
* Collection接口的使用
* (1)添加元素
* (2)删除元素
* (3)遍历元素
* (4)判断
*/
public class Collection1 {
public static void main(String[] args) {
//创建集合
Collection collection = new ArrayList();
//(1)添加元素
collection.add("苹果");
collection.add("葡萄");
collection.add("香蕉");
System.out.println("元素个数:" + collection.size());
System.out.println(collection);
//(2)删除元素
// collection.remove("香蕉");
// collection.clear();
// System.out.println("元素个数:" + collection.size());
//(3)遍历元素【重点】
//3.1使用增强for
for (Object object : collection) {
System.out.println(object);
}
//3.2使用迭代器(迭代器专门用来遍历集合的一种方式)
//hasNext();有没有下一个元素
//next();获取下一个元素
//remove();删除当前元素
Iterator it = collection.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
//collection.remove(s); 不能使用collection删除方法,并发修改异常
it.remove();
}
System.out.println("元素个数:" + collection.size());
//(4)判断
System.out.println(collection.contains("香蕉"));//判断是否有"香蕉"
System.out.println(collection.isEmpty());//判断是否为空
}
}
Collection的使用(2)
/**
* Collection的使用:保存学生信息
*/
public class Collection2 {
public static void main(String[] args) {
//新建Collection对象
Collection collection = new ArrayList();
Student s1 = new Student("张三", 20);
Student s2 = new Student("李四", 21);
Student s3 = new Student("王五", 22);
//1.添加数据
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println("元素个数:" + collection.size());
System.out.println(collection.toString());
//2.删除数据
// collection.remove(s3);
// collection.clear();//清空
// System.out.println("元素个数:" + collection.size());
//3.遍历数据
//3.1增强for
for (Object object : collection) {
Student s = (Student) object;
System.out.println(s.toString());
}
//3.2迭代器:hasNext(); next(); remove();迭代过程中不能使用collection的删除方法
Iterator it = collection.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
System.out.println(s.toString());
}
//4.判断
System.out.println(collection.contains(s1));
System.out.println(collection.isEmpty());
}
}
/**
* 学生类
*/
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [" +
"name='" + name + '\'' +
", age=" + age +
']';
}
}
List集合
List子接口
特点
有序、有下标、元素可以重复。
方法
-
void add(int index,Object o)//在index位置插入对象o。
-
boolean addAll(int index,Collection c)//将一个集合中的元素添加到此集合中的index位置。
-
Object get(int index)//返回集合中指定位置的元素。
-
List subList(int fromIndex,int toIndex)//返回fromIndex和toIndex之间的集合元素。
列表迭代器
hasNext()判断有没有下一个元素。
hasPrevious()判断有没有上一个元素。
next()获取下一个元素。
nextIndex()返回next调用的元素下标。
previous()获取上一个元素。
previousIndex()返回previous调用的元素下标。
remove()删除当前元素。
List接口的使用(1)
/**
* List子接口的使用
* 特点:1 有序 有下标 2 可以重复
*/
public class Demo01 {
public static void main(String[] args) {
//先创建集合对象
List list = new ArrayList<>();
//1添加元素
list.add("苹果");
list.add("小米");
list.add(0, "华为");
System.out.println("元素个数:" + list.size());
System.out.println(list.toString());
//2删除元素
// list.remove("苹果");
// list.remove(0);
// System.out.println("元素个数:"+list.size());
// System.out.println(list.toString());
//3遍历
//3.1使用for遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//3.2使用增强for
for (Object object : list) {
System.out.println(object);
}
//3.3使用迭代器
Iterator it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//3.4使用列表迭代器,与Iterator的区别,ListIterator可以向前或向后遍历,添加、删除、修改元素。
ListIterator lit = list.listIterator();
//3.4.1使用列表迭代器从前往后进行遍历
while (lit.hasNext()) {
System.out.println(lit.nextIndex() + ":" + lit.next());
}
//3.4.2使用列表迭代器从后往前进行遍历
while (lit.hasPrevious()) {
System.out.println(lit.previousIndex() + ":" + lit.previous());
}
//4判断
System.out.println(list.contains("苹果"));
System.out.println(list.isEmpty());
//5获取位置
System.out.println(list.indexOf("华为"));
}
}
List接口的使用(2)
/**
* List的使用
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
List list = new ArrayList<>();
//1添加数字数据(自动装箱)
list.add(20);
list.add(30);
list.add(40);
list.add(50);
list.add(60);
System.out.println("元素个数:" + list.size());
System.out.println(list.toString());
//2删除操作
//list.remove(0);
//list.remove(list.indexOf(20));
//list.remove((Object) 20);
//list.remove(new Integer(20));
System.out.println("元素个数:" + list.size());
System.out.println(list.toString());
//3补充方法subList:返回子集合,左闭右开
List subList = list.subList(1, 3);
System.out.println(subList.toString());
}
}
List常见实现类
-
ArrayList【重点】:
-
数组结构实现,查询快、增删慢。
-
JDK1.2版本,运行效率快、线程不安全。
-
源码分析:DEFAULT_CAPACITY=10;默认容量。
注意:如果没有向集合中添加任何元素时,容量0,添加一个元素之后 容量10。
每次扩容大小是原来的1.5倍。
elementData 存放元素的数组。
size 实际元素个数。
add()添加元素。
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
-
-
Vertor:
-
数组结构实现,查询快、增删慢。
-
JDK1.0版本,运行效率慢、线程安全。
-
-
Linked List:
-
链表结构实现,增删快、查询慢。
-
源码分析:
int size:集合的大小。
Node first;链表的头节点。
Node last;链表的尾节点。
private void linkFirst(E e) { final Node<E> f = first; final Node<E> newNode = new Node<>(null, e, f); first = newNode; if (f == null) last = newNode; else f.prev = newNode; size++; modCount++; }
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
-
ArrayList的使用
/**
* ArrayList的使用
* 存储结构:数组,查找遍历速度快,增删慢
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList();
//1添加元素
Student s1 = new Student("刘德华", 22);
Student s2 = new Student("郭富城", 21);
Student s3 = new Student("周杰伦", 18);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println("元素个数:" + arrayList.size());
System.out.println(arrayList.toString());
//2删除元素
// arrayList.remove(s1);
// System.out.println("元素个数:"+arrayList.size());
//3遍历元素【重点】
//3.1使用迭代器
Iterator it = arrayList.iterator();
while (it.hasNext()) {
Student student = (Student) it.next();
System.out.println(student.toString());
}
//3.2列表迭代器
ListIterator lit = arrayList.listIterator();
while (lit.hasNext()) {
Student student = (Student) lit.next();
System.out.println(student.toString());
}
while (lit.hasPrevious()) {
Student student = (Student) lit.previous();
System.out.println(student.toString());
}
//4判断
System.out.println(arrayList.contains(s1));
System.out.println(arrayList.isEmpty());
//5查找
System.out.println(arrayList.indexOf(s1));
}
}
Vector的使用
/**
* Vector集合的使用
* 存储结构:数组
*/
public class Demo04 {
public static void main(String[] args) {
//创建集合
Vector vector = new Vector<>();
//1添加元素
vector.add("草莓");
vector.add("苹果");
vector.add("香蕉");
System.out.println("元素个数:" + vector.size());
//2删除元素
// vector.remove(0);
// vector.remove("西瓜");
// vector.clear();
//3遍历元素
//使用枚举器
Enumeration en = vector.elements();
while (en.hasMoreElements()) {
String o = (String) en.nextElement();
System.out.println(o);
}
//4判断
System.out.println(vector.contains("草莓"));
System.out.println(vector.isEmpty());
//5vector其他方法
//firstElement、lastElement、elementAt();
}
}
LinkedList的使用
/**
* LinkedList的使用
* 存储结构:双向列表
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
LinkedList linkedList = new LinkedList<>();
//1添加元素
Student s1 = new Student("刘德华", 22);
Student s2 = new Student("郭富城", 21);
Student s3 = new Student("周杰伦", 18);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
System.out.println("元素个数:" + linkedList.size());
System.out.println(linkedList.toString());
//2删除元素
// linkedList.remove(s1);
// System.out.println("元素个数:"+linkedList.size());
// linkedList.clear();
//3遍历元素
//3.1for遍历
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
//3.2增强for
for (Object object : linkedList) {
Student s = (Student) object;
System.out.println(s.toString());
}
//3.3使用迭代器
Iterator it = linkedList.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
System.out.println(s.toString());
}
ListIterator lit = linkedList.listIterator();
while (lit.hasNext()) {
Student s = (Student) lit.next();
System.out.println(s.toString());
}
//4判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
//5获取(集合在元素中的位置)
System.out.println(linkedList.indexOf(s2));
}
}
泛型(Generic)
-
Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
-
常见形式有泛型类、泛型接口、泛型方法。
-
语法:<T…> T称为类型占位符,表示一种引用类型。
-
好处:(1)提高代码的重用性。
(2)防止类型转换异常,提高代码的安全性。
泛型类
/**
* 泛型类
* 语法:类名<T>
* T是类型占位符,表示一种引用类型,如果编写多个使用逗号隔开
*/
public class MyGeneric<T> {
//使用泛型T
//1创建变量
T t;
//2泛型作为方法参数
public void show(T t) {
System.out.println(t);
}
//3泛型作为方法的返回值
public T getT() {
return t;
}
}
public class TestGeneric {
public static void main(String[] args) {
//使用泛型类创建对象
//注意:1泛型只能使用引用类型。2不同泛型对象之间不能相互赋值。
MyGeneric<String> myGeneric = new MyGeneric<>();
myGeneric.t = "hello";
myGeneric.show("大家好,加油!");
String string = myGeneric.getT();
System.out.println(string);
MyGeneric<Integer> myGeneric2 = new MyGeneric<>();
myGeneric2.t = 100;
myGeneric2.show(200);
Integer integer = myGeneric2.getT();
System.out.println(integer);
}
}
泛型接口
/**
* 泛型接口
* 语法:接口名<T>
* 注意:不能使用泛型创建静态常量
*
* @param <T>
*/
public interface MyInterface<T> {
String name = "张三";
T Server(T t);
}
public class MyInterfaceImpl implements MyInterface<String>{
@Override
public String Server(String t) {
System.out.println(t);
return t;
}
}
public class MyInterfaceImpl2<T> implements MyInterface<T> {
@Override
public T Server(T t) {
System.out.println(t);
return t;
}
}
MyInterfaceImpl impl=new MyInterfaceImpl();
impl.Server("xxxxxx");
MyInterfaceImpl2<Integer> impl2=new MyInterfaceImpl2<>();
impl2.Server(1000);
泛型方法
/**
* 泛型方法
* 语法:<T> 返回值类型
*/
public class MyGenericMethod {
//泛型方法
public <T> T show(T t) {
System.out.println("泛型方法" + t);
return t;
}
}
MyGenericMethod myGenericMethod = new MyGenericMethod();
myGenericMethod.show("加油!");
myGenericMethod.show(200);
myGenericMethod.show(3.14);
泛型集合
- 概率:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
- 特点:
- 编译时即可检查,而非运行时抛出异常。
- 访问时,不必类型转换(拆箱)。
- 不同泛型之间引用不能相互赋值,泛型不存在多态。
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("xxx");
arrayList.add("zzz");
for (String s : arrayList) {
System.out.println(s);
}
ArrayList<Student> arrayList2 = new ArrayList<>();
Student s1 = new Student("刘德华", 22);
Student s2 = new Student("郭富城", 21);
Student s3 = new Student("周杰伦", 18);
arrayList2.add(s1);
arrayList2.add(s2);
arrayList2.add(s3);
Iterator<Student> it = arrayList2.iterator();
while (it.hasNext()) {
Student student = it.next();
System.out.println(student.toString());
}
}
}
Set集合
Set子接口
- 特点:无序、无下标、元素不可重复。
- 方法:全部继承自Collection中的方法。
Set实现类
- HashSet【重点】
- 基于HashCode计算元素存放位置。
- 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
- TreeSet:
- 基于排列顺序实现元素不重复。
- 实现了SortedSet接口,对集合元素自动排序。
- 元素对象的类型必须实现Comparable接口,指定排序规则。
- 通过CompareTo方法确定是否为重复元素。
Set接口的使用
/**
* 测试Set接口的使用
* 特点:(1)无序、没有下标 (2)不能重复
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合
Set<String> set = new HashSet<>();
//1添加数据
set.add("小米");
set.add("苹果");
set.add("华为");
System.out.println("元素个数:" + set.size());
System.out.println(set.toString());
//2删除数据
// set.remove("苹果");
// System.out.println(set.toString());
//3遍历数据【重点】
//3.1增强for
for (String string : set) {
System.out.println(string);
}
//3.2使用迭代器
Iterator it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4判断
System.out.println(set.contains("华为"));
System.out.println(set.isEmpty());
}
}
HashSet的使用(1)
/**
* HashSet集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
HashSet<String> hashSet = new HashSet<>();
//1添加元素
hashSet.add("周杰伦");
hashSet.add("陈冠希");
hashSet.add("周慧敏");
hashSet.add("王祖贤");
System.out.println("元素个数:" + hashSet.size());
System.out.println(hashSet.toString());
//2删除元素
hashSet.remove(0);
System.out.println("元素个数:" + hashSet.size());
//3遍历元素
//3.1增强for
for (String string : hashSet) {
System.out.println(string);
}
//3.2迭代器
Iterator<String> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4判断
System.out.println(hashSet.contains("王祖贤"));
System.out.println(hashSet.isEmpty());
}
}
HashSet的使用(2)
/**
* 人类
*/
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (this.name.equals(person.getName())&&this.age== person.getAge()){
return true;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
/**
* HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 存储过程(重复依据)
* (1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步。
* (2)再执行equals方法,如果equals方法为true,则认为是重复,否则,形成列表。
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合
HashSet<Person> hashSet=new HashSet<>();
//1添加数据
Person p1 = new Person("王祖贤",18);
Person p2 = new Person("周慧敏",24);
Person p3 = new Person("周杰伦",20);
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
hashSet.add(new Person("周杰伦",20));
System.out.println("元素个数:"+hashSet.size());
System.out.println(hashSet.toString());
//2删除数据
// hashSet.remove(p1);
// System.out.println("元素个数:"+hashSet.size());
//3遍历数据
//3.1使用增强for
for (Person person:hashSet) {
System.out.println(person);
}
//3.2迭代器
Iterator<Person> it= hashSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4判断
System.out.println(hashSet.contains(new Person("周杰伦",20)));
System.out.println(hashSet.isEmpty());
}
}
TreeSet的使用(1)
/**
* TreeSet的使用
* 存储结构:红黑树
*/
public class Demo04 {
public static void main(String[] args) {
//创建集合
TreeSet<String> treeSet = new TreeSet<>();
//1添加元素
treeSet.add("xyz");
treeSet.add("abc");
treeSet.add("hello");
treeSet.add("xyz");//重复不再添加
System.out.println("元素个数:" + treeSet.size());
System.out.println(treeSet.toString());
//2删除元素
treeSet.remove("xyz");
System.out.println("元素个数:" + treeSet.size());
//3遍历元素
//3.1增强for
for (String string : treeSet) {
System.out.println(string);
}
//3.2迭代器
Iterator<String> it = treeSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4判断
System.out.println(treeSet.contains("xyz"));
System.out.println(treeSet.isEmpty());
}
}
TreeSet的使用(2)
public class Person implements Comparable<Person> {
//先按姓名比,然后再按年龄比
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.age - o.getAge();
return n1==0?n2:n1;
}
}
/**
* 使用TreeSet保存数据
* 存储结构:红黑树
* 要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
TreeSet<Person> treeSet = new TreeSet<>();
//1添加数据
Person p1 = new Person("xyz", 18);
Person p2 = new Person("hello", 24);
Person p3 = new Person("abc", 20);
Person p4 = new Person("abc", 22);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
treeSet.add(p4);
System.out.println("元素个数:" + treeSet.size());
System.out.println(treeSet.toString());
//2删除数据
treeSet.remove(p1);
System.out.println("元素个数:" + treeSet.size());
//3遍历数据
//3.1增强for
for (Person person : treeSet) {
System.out.println(person);
}
//3.2迭代器
Iterator<Person> it = treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4判断
System.out.println(treeSet.contains(p1));
System.out.println(treeSet.isEmpty());
}
}
Comparator接口
/**
* TreeSet集合的使用
* Comparator:实现定制比较(比较器)
* Comparable:可比较的
*/
public class Demo06 {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<Person> treeSet=new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1=o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
});
Person p1 = new Person("xyz", 18);
Person p2 = new Person("hello", 24);
Person p3 = new Person("abc", 20);
Person p4 = new Person("cba", 20);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
treeSet.add(p4);
System.out.println(treeSet.toString());
}
}
TreeSet案例
/**
* 要求:使用TreeSet集合实现字符串按照长度进行排序
* Comparator接口实现定制比较
*/
public class Demo07 {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length() - o2.length();
int n2 = o1.compareTo(o2);
return n1 == 0 ? n2 : n1;
}
});
//添加数据
treeSet.add("one");
treeSet.add("lisi");
treeSet.add("cat");
treeSet.add("zhangsan");
treeSet.add("chongqing");
System.out.println(treeSet.toString());
}
}
Map集合
Map父接口
特点
存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复。
方法
- V put(K key,V value)//将对象存入到集合中,关键键值。key重复则覆盖原值。
- Object get(Object key)//根据键获取对应的值。
- keySet //返回所有的key。
- Collection values()//返回包含所有值的Collection集合。
- entrySet<Map.Entry<K,V>> //键值匹配的Set集合。
entrySet效率高于keySet。
Map接口使用
/**
* Map接口的使用
* 特点:(1)存储键值对(2)键不能重复,值可以重复(3)无序
*/
public class Demo01 {
public static void main(String[] args) {
//创建Map集合
Map<String, String> map = new HashMap<>();
//1添加元素
map.put("cn", "中国");
map.put("uk", "英国");
map.put("usa", "美国");
// map.put("cn","zhongguo");后添加不会增加元素个数,但会替换value值。
System.out.println("元素个数:" + map.size());
System.out.println(map.toString());
//2删除元素
// map.remove("usa");
// System.out.println("元素个数:"+map.size());
//3遍历元素
//3.1使用keySet()
//Set<String> keyset = map.keySet();
for (String key : map.keySet()) {
System.out.println(key + "-" + map.get(key));
}
//3.2使用entrySet() Map.Entry 映射对(键值对)
//Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "-" + entry.getValue());
}
//4判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("泰国"));
}
}
HashMap使用
-
HashMap【重点】
- JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value。
-
Hashtable:
- JDK1.0版本,线程安全,运行效率慢;不允许用null作为key或是value。
-
Properties:
- Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
-
TreeMap:
- 实现了SortedMap接口(是Map的子接口),可以对key自动排序。
HashMap():构造一个具有默认初始容量(16)和默认加载因子(0.75)的空HashMap。
package Map学习;
public class Student implements Comparable<Student>{
private String name;
private int stuNo;
public Student() {
}
public Student(String name, int stuNo) {
this.name = name;
this.stuNo = stuNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getStuNo() {
return stuNo;
}
public void setStuNo(int stuNo) {
this.stuNo = stuNo;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", stuNo=" + stuNo +
'}';
}
@Override
public int compareTo(Student o) {
int n1=this.stuNo-o.getStuNo();
return n1;
}
}
/**
* HashMap集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 使用key可hashcode和equals作为重复
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
//刚创建hashmap之后没有添加元素table=null size=0 目的节省空间
HashMap<Student, String> students = new HashMap<Student, String>();
//1添加元素
Student s1 = new Student("孙悟空", 100);
Student s2 = new Student("猪八戒", 101);
Student s3 = new Student("沙和尚", 102);
students.put(s1, "重庆");
students.put(s2, "上海");
students.put(s3, "北京");
//students.put(s3,"南京");
System.out.println("元素个数:" + students.size());
System.out.println(students.toString());
//2删除
// students.remove(s1);
// System.out.println("元素个数:"+students.size());
//3遍历
//3.1使用keySet()
for (Student key : students.keySet()) {
System.out.println(key.toString() + "-" + students.get(key));
}
//3.2使用entrySet()
for (Map.Entry<Student, String> entry : students.entrySet()) {
System.out.println(entry.getKey() + "-" + entry.getValue());
}
//4判断
System.out.println(students.containsKey(s1));
System.out.println(students.containsValue("重庆"));
}
}
HashMap源码分析
源码分析
1 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//hashMap初始容量大小
2 static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap的数组最大容量
3 static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
4 static final int TREEIFY_THRESHOLD = 8;//jdk1.8 当链表长度大于8时,调整成红黑树
5 static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8 当链表长度小于6时,调整成链表
6 static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树
7 transient Node<K,V>[] table;//哈希表中的数组
8 size;//元素个数
无参构造
public HashMap(){
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
put方法
public V put(K key,V value){
return putVal(hash(key),key,value,false.true);
}
总结
(1)HashMap刚创建时,table说null,为了节省空间,当添加第一个元素是,table容量调整为16
(2)当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的:减少调整元素的个数
(3)jdk1.8 当每个链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树,目的:提高执行效率
(4)jdk1.8 当链表长度小于6时,调整成链表
(5)jdk1.8以前,链表时头插入,jdk1.8以后时是尾插入
TreeMap的使用
/**
* TreeMap的使用
* 存储结构:红黑树
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合
TreeMap<Student,String> treeMap=new TreeMap<Student,String>();
//1添加元素
Student s1 = new Student("孙悟空", 100);
Student s2 = new Student("猪八戒", 101);
Student s3 = new Student("沙和尚", 102);
treeMap.put(s1, "重庆");
treeMap.put(s2, "上海");
treeMap.put(s3, "北京");
System.out.println("元素个数:"+treeMap.size());
System.out.println(treeMap.toString());
//2删除
// treeMap.remove(s3);
// System.out.println(treeMap.size());
//3遍历
//3.1使用keySet
for (Student key : treeMap.keySet()) {
System.out.println(key+"-"+treeMap.get(key));
}
//3.2使用entryKey
for (Map.Entry<Student,String> entry: treeMap.entrySet()) {
System.out.println(entry.getKey()+"-"+entry.getValue());
}
//4判断
System.out.println(treeMap.containsKey(s1));
}
}
Collections工具类
- 概念:集合工具类,定义了除了存取以外的集合常用方法。
- 方法:
- public static void reverse(List<?> list) //反转集合中元素的顺序
- public static void shuffle(List<?> list) //随机重置集合元素的顺序
- public static void sort(List list) //升序排序(元素类型必须实现Comparable接口)
集合总结
- 集合的概念:
- 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法。
- List集合:
- 有序、有下标、元素可以重复。(ArrayList、LinkenList、Vertor)
- Set集合:
- 无序、无下标、元素不可重复。(HashSet、TreeSet)
- Map集合:
- 存储一对数据,无序、无下标,键不可重复,值可重复。(HashMap、HashTable、TreeMap)
- Collections:
- 集合工具类,定义了除了存取以外的集合常用方法。