java集合框架
1.集合
1.1、什么是集合
概念
对象的容器,实现类对对象常用的操作
和数组的区别
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
位置
java.util.*;
1.2、Collection体系
1.2.1、Collection父接口
特点:代表一组任意类型的对象,无序,无下标,不能重复
创建集合:Collection collection=new ArrayList();
常用方法:
1.添加元素 collection.add();
2.删除元素 collection.remove(),collection.clear()
3.遍历元素:
1.使用增强for(因为无下标)
for(Object object : collection){ }
2.使用迭代器
//haNext(); 有没有下一个元素
//next(); 获取下一个元素
//remove(); 删除当前元素
Iterator it = collection.iterator();
while(it.hasNext()){
String object = (String)it.next(); //强转
// 可以使用it.remove(); 进行移除元素
// collection.remove(); 不能用collection其他方法 会报并发修改异常
}
4.判断 collection.contains(); collection.isEmpty();
代码测试1:
package com.me;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Collection接口的使用
* (1)添加元素
* (2)删除元素
* (3)遍历元素
* (4)判断
*/
public class CollectionTest {
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("榴莲");
// System.out.println("删除之后:"+collection.size());
//(3)遍历元素(重点)
//3.1使用增强for
System.out.println("----------------3.1使用增强for--------------");
for (Object object : collection) {
System.out.println(object);
}
//3.2使用迭代器(迭代器专门用来遍历集合的一种方式)
//haNext(); 有没有下一个元素
//next(); 获取下一个元素
//remove(); 删除当前元素
System.out.println("----------------3.2使用迭代器--------------");
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
String object = (String) iterator.next();
System.out.println(object); //强转
//collection.remove(object);//不能用collection其他方法 会报并发修改异常
//iterator.remove();//进行移除元素
}
System.out.println("元素个数:"+collection.size());
//(4)判断
System.out.println(collection.contains("西瓜"));
System.out.println(collection.isEmpty());
}
}
代码测试2:
package com.me;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Collection的使用:保存学生信息
*/
public class CollectionTest2 {
public static void main(String[] args) {
//新建collection对象
Collection collection=new ArrayList();
Student s1=new Student("张三",10);
Student s2=new Student("李四",18);
Student s3=new Student("王五",20);
//1,添加数据
collection.add(s1);
collection.add(s2);
collection.add(s3);
collection.add(s3);
System.out.println("元素个数:"+collection.size());
System.out.println(collection.toString());
//2.删除
// collection.remove(s1);
// collection.remove(new Student("王五",22));
// System.out.println("删除之后:"+collection.size());
// System.out.println(collection.toString());
// collection.clear(); //清除(只是删除了集合中的地址)
//3.遍历
//3.1增强for
for (Object object : collection) {
Student s= (Student) object;
System.out.println(s.toString());
}
//3.2迭代器:hasNext() ; next() ; remove(); 迭代过程中不能使用collection的删除方法
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
Student s = (Student) iterator.next();
System.out.println(s.toString());
}
//4.判断
System.out.println(collection.contains(s1));
System.out.println(collection.contains(new Student("张三",10)));
}
}
Student类
package com.me;
/**
* 学生类
*/
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 +
'}';
}
}
1.2.2、List子接口
特点:有序,有下标,元素可重复
创建集合对象:List list=new ArrayList();
常用方法:
-
添加元素
list.add();
,会对基本类型进行自动装箱 -
删除元素,可以使用索引
list.remove(0)
、当删除数字与索引矛盾时对数字强转,或者new一个对象
list.remove((Object) 10)
或list.remove(new Integer(10))
-
遍历
-
使用for遍历
for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); //返回object }
-
使用增强for
for (Object object : list) { System.out.println(object); }
-
使用迭代器
while (iterator.hasNext()){ //可以使用it.remove(); 进行移除元素 // collection.remove(); 不能用collection其他方法 会报并发修改异常 System.out.println(iterator.next()); }
-
使用迭代器列表
ListIterator li = list.listIterator(); while(li.hasNext()){ System.out.println(li.nextIndex() + ":" + li.next()); //从前往后遍历 } while(li.hasPrevious()){ System.out.println(li.previousIndex() + ":" + li.previous()); //从后往前遍历 }
-
-
获取元素位置
list.indexOf()
-
返回子集合
sublist(x,y);
左闭右开List subList = list.subList(1, 3);
返回索引 1、2的元素
测试代码1:
package com.me;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* List子接口的使用
* 特点:1.有序 有下标
* 2.可以重复
*/
public class ListTest {
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遍历
System.out.println("=============3.1使用for遍历=================");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i)); //返回object
}
//3.2使用增强for
System.out.println("=============3.2使用增强for===================");
for (Object object : list) {
System.out.println(object);
}
//3.3使用迭代器
Iterator iterator = list.iterator();
System.out.println("============3.3使用迭代器=====================");
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//3.4使用列表迭代器,和Iterator的区别,ListIterator可以向前或向后遍历,添加,删除,修改元素
ListIterator lit = list.listIterator();
System.out.println("=========3.4使用列表迭代器从前往后===================");
while (lit.hasNext()){
System.out.println(lit.nextIndex()+":"+lit.next());
}
System.out.println("=========3.4使用列表迭代器从后往前===================");
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("华为"));
}
}
测试代码2:
package com.me;
import java.util.ArrayList;
import java.util.List;
/**
* List的使用
*/
public class ListTest2 {
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(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());
}
}
1.2.3、List实现类
-
ArrayList 【重点】
-
DEFAULT_CAPACITY = 10 默认容量
注意:如果没有向集合中添加任何元素时,容量为0;添加一个元素之后,容量10 ;每次扩容大小是原来的1.5倍
-
elementDat 存放元素的数组
-
size 实际的元素个数
-
add() 添加元素
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } 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); }
- 数组结构实现,必须要连续空间,查询快、增删慢
- jdk1.2版本,运行效率块、线程不安全
-
测试代码:
package com.me.List;
import com.me.Student;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
/**
* ArrayList的使用
* 存储接口:数组,查找遍历速度快,增删慢
*/
public class ArrayListTest {
public static void main(String[] args) {
//创建集合 size 0 容量 0 扩容原来的1.5倍
ArrayList arrayList=new ArrayList<>();
//1.添加元素
Student s1=new Student("刘德华",20);
Student s2=new Student("郭富城",22);
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);
// arrayList.remove(new Student("刘德华",20)); //删不掉,可以重写equals方法
// System.out.println("删除之后元素个数:"+arrayList.size());
// System.out.println(arrayList.toString());
//3.遍历元素
//3.1使用迭代器
System.out.println("============3.1使用迭代器================");
Iterator it = arrayList.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.toString());
}
//3.2列表迭代器
ListIterator lit = arrayList.listIterator();
System.out.println("===============3.2列表迭代器(从前往后)============================");
while (lit.hasNext()){
Student s = (Student) lit.next();
System.out.println(s.toString());
}
System.out.println("===============3.2列表迭代器(从后往前)============================");
while (lit.hasPrevious()){
Student s = (Student) lit.previous();
System.out.println(s.toString());
}
//4判断
System.out.println(arrayList.contains(s1));
System.out.println(arrayList.contains(new Student("刘德华",20))); //重写了equals方法
System.out.println(arrayList.isEmpty());
//5.查找
System.out.println(arrayList.indexOf(s2));
}
}
- Vector
- 数组结构实现,查询快、增删慢
- jdk1.0版本,运行效率慢、线程安全
测试代码:
package com.me.List;
import java.util.Enumeration;
import java.util.Vector;
/**
* 演示Vector集合的使用
* 存储结构:数组
*/
public class VectorTest {
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()){
Object o = en.nextElement();
System.out.println(o.toString());
}
//4.判断
System.out.println(vector.contains("西瓜"));
System.out.println(vector.isEmpty());
//5.Vector其他的方法
//firstElement、lastElement、elementAt
}
}
- LinkedList
- 双向链表结构实现,无需连续空间,增删快,查询慢
package com.me.List;
import com.me.Student;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
/**
* LinkList的使用
* 存储结构:双向链表
*/
public class LinkListTest {
public static void main(String[] args) {
//创建集合
LinkedList linkedList=new LinkedList<>();
//1.添加元素
Student s1=new Student("刘德华",20);
Student s2=new Student("郭富城",22);
Student s3=new Student("梁朝伟",18);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s3);
System.out.println("元素个数:"+linkedList.size());
System.out.println(linkedList.toString());
//2.删除
// linkedList.remove(s1);
// linkedList.remove(new Student("刘德华",20)); //可以删除,因为重写了equals方法
// System.out.println("删除之后:"+linkedList.size());
//3.遍历
//3.1for遍历
System.out.println("================for=================");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
//3.2增强for
System.out.println("=============增强for====================");
for (Object object : linkedList) {
Student s= (Student) object;
System.out.println(s);
}
//3.3使用迭代器
System.out.println("==============使用迭代器===================");
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()){
Student s= (Student) iterator.next();
System.out.println(s);
}
//3.4使用列表迭代器
System.out.println("==============使用列表迭代器===================");
ListIterator listIterator = linkedList.listIterator();
while (listIterator.hasNext()){
Student s= (Student) listIterator.next();
System.out.println(s);
}
//4.判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
//5获取位置
System.out.println(linkedList.indexOf(s1));
System.out.println(linkedList.indexOf(s2));
}
}
1.3、泛型
- 本质是参数化类型,把类型作为参数传递
- 常见形式有泛型类、泛型接口、泛型方法
- 语法< T,…>成为类型占位符,表示一种引用类型,可以写多个逗号隔开
- 好处 1. 提高代码重用性 2. 防止类型转换异常,提高代码安全性
1.3.1、泛型类
// 写一个泛型类
public class MyGeneric<T>{
//使用泛型T
//1 创建变量
T t;
//2 泛型作为方法的参数
public void show(T t){
sout(t);
}
//3 泛型作为方法的返回值
public T getT(){
return t;
}
}
// 使用泛型类
public class TestGeneric{
public static void main(String[] args){
//使用泛型类创建对象
// 注意: 1. 泛型只能使用引用类型
// 2. 不用泛型类型对象之间不能相互赋值
MyGeneric<String> myGeneric = new MyGeneric<String>();
myGeneric.t = "hello";
myGeneric.show("hello world!");
String string = myGeneric.getT();
MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>();
myGeneric2.t = 100;
myGeneric2.show(200);
Integer integer = myGeneric2.getT();
}
}
1.3.2、泛型接口
语法:接口名
注意:不能泛型静态常量
package com.me.generic;
/**
* 泛型接口
* 语法:接口名<T>
* 注意:不能泛型静态常量
*/
public interface MyGenericInterface<T> {
String name="张三";
T server(T t);
}
package com.me.generic;
public class MyGenericInterfaceImpl implements MyGenericInterface<String> {
@Override
public String server(String t) {
System.out.println(t);
return t;
}
}
package com.me.generic;
public class MyGenericInterfaceImpl2<T> implements MyGenericInterface<T> {
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
测试:
package com.me.generic;
public class TestGeneric {
public static void main(String[] args) {
//使用泛型类创建对象
//注意:1.泛型只能使用引用类型
//2.不用泛型类型对象之间不能相互赋值
MyGeneric<String> myGeneric=new MyGeneric<>();
myGeneric.t="hello";
myGeneric.show("hello world!");
String s = myGeneric.getT();
System.out.println(s);
MyGeneric<Integer> myGeneric2=new MyGeneric<>();
myGeneric2.t=100;
myGeneric2.show(200);
Integer t = myGeneric2.getT();
System.out.println(t);
//泛型接口
MyGenericInterfaceImpl impl = new MyGenericInterfaceImpl();
impl.server("hello");
MyGenericInterfaceImpl2<Integer> impl2 = new MyGenericInterfaceImpl2<>();
impl2.server(1000);
//泛型方法
MyGenericMethod myGenericMethod = new MyGenericMethod();
myGenericMethod.show("字符串"); //自动类型为字符串
myGenericMethod.show(2000);
myGenericMethod.show(3.14);
}
}
1.3.3、泛型方法
语法: 返回值类型
package com.me.generic;
/**
* 泛型方法
* 语法:<T>返回值类型
*/
public class MyGenericMethod {
//泛型方法
public <T> T show(T t){
System.out.println("泛型方法:"+t);
return t;
}
}
1.3.4、泛型集合
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
特点:
- 编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换(拆箱)
- 不同泛型之间应用不能相互赋值,泛型不存在多态
1.4、Set集合
特点:无序、无下标、元素不可重复
方法:全部继承自Collection中的方法
增、删、遍历、判断与collection一致
1.4.1、HashSet
存储结构:哈希表(数组+链表+红黑树)
存储过程(重复依据)
- 根据hashCode计算保存的位置,如果位置为空,直接保存,若不为空,进行第二步
- 再执行equals方法,如果equals为true,则认为是重复,否则形成链表
特点:
- 基于HashCode计算元素存放位置
- 利用31这个质数,减少散列冲突
- 31提高执行效率
31 * i = (i << 5) - i
转为移位操作
- 31提高执行效率
- 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入
- 利用31这个质数,减少散列冲突
新建集合 HashSet<String> hashSet = new HashSet<String>();
添加元素 hashSet.add( );
删除元素 hashSet.remove( );
遍历操作
-
增强for
for( type type : hashSet)
-
迭代器
Iterator<String> it = hashSet.iterator( );
判断 hashSet.contains( );
hashSet.isEmpty();
测试代码1:
package com.me.set;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
*/
public class HashSetTest {
public static void main(String[] args) {
//新建集合
HashSet<String> hashSet=new HashSet<String>();
//1.添加元素
hashSet.add("刘德华");
hashSet.add("梁朝伟");
hashSet.add("林志玲");
hashSet.add("周润发");
hashSet.add("刘德华");
System.out.println("元素的个数:"+hashSet.size());
System.out.println(hashSet.toString());
//2.删除数据
hashSet.remove("刘德华");
System.out.println("删除之后:"+hashSet.size());
System.out.println(hashSet.toString());
//3.遍历
//3.1增强for
System.out.println("=========使用增强for===========");
for (String s : hashSet) {
System.out.println(s);
}
//3.2使用迭代器
System.out.println("===========使用迭代器============");
Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//4.判断
System.out.println(hashSet.contains("梁朝伟"));
System.out.println(hashSet.isEmpty());
}
}
测试代码2:
package com.me.set;
import com.me.Person;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 存储过程(重复的依据)
* (1)根据hashcode计算保存的位置,如果此位置,则直接保存,如果不为空执行第二步
* (2)再执行equals方法,如果equals方法为true,则认为重复,否则,形成链表
*
*/
public class HashSetTest2 {
public static void main(String[] args) {
//创建集合
HashSet<Person> persons=new HashSet<>();
Person p1=new Person("刘德华",20);
Person p2=new Person("林志玲",22);
Person p3=new Person("梁朝伟",25);
//1.添加数据
persons.add(p1);
persons.add(p2);
persons.add(p3);
// persons.add(p3); //重复
persons.add(new Person("梁朝伟",25));//需要重写hashcode和equals方法
System.out.println("元素的个数:"+persons.size());
System.out.println(persons.toString());
//2.删除操作
// persons.remove(p1);
// persons.remove(new Person("刘德华",20));//重写了hashcode和equals方法后可以删除,不重写则不能删除
// System.out.println("删除之后:"+persons.size());
//3.遍历
//3.1增强for
System.out.println("==========3.1增强for===============");
for (Person person : persons) {
System.out.println(person.toString());
}
//3.2使用迭代器
System.out.println("==========3.2使用迭代器===========");
Iterator<Person> iterator = persons.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//4.判断
System.out.println(persons.contains(p1));
System.out.println(persons.contains(new Person("刘德华",20))); //返回了true,因为重写了hashcode和equals方法
System.out.println(persons.isEmpty());
}
}
附Person类
package com.me.set;
import java.util.Objects;
/**
* 人类
*/
public class Person implements Comparable<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 int hashCode() {
// int n1=this.name.hashCode();
// int n2=this.age;
// return n1+n2;
// }
//
// @Override
// public boolean equals(Object obj) {
// if (this==obj){
// return true;
// }
// if (obj==null){
// return false;
// }
// if (obj instanceof Person){
// Person p= (Person) obj;
// if (this.name.equals(p.getName()) && this.age==p.getAge()){
// return true;
// }
// }
// return false;
// }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
return getAge() == person.getAge() && getName().equals(person.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
/**
* 先按姓名比,然后再按年龄比
* @param o
* @return
*/
@Override
public int compareTo(Person o) {
int n1=this.getName().compareTo(o.getName());
int n2=this.age-o.getAge();
return n1==0?n2:n1;
}
/*
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
(1)31是一个质数,减少散列冲突
(2) 31提高执行效率 31*i=(i<<5)-i
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
*/
}
1.4.2、TreeSet
特点
- 基于排列顺序实现元素不重复
- 实现SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable接口,指定排序规则
- 通过CompareTo方法确定是否为重复元素
存储结构:红黑树
创建集合 TreeSet<String> treeSet = new TreeSet<>()
添加元素 treeSet.add();
删除元素 treeSet.remove();
遍历 1. 增强for 2. 迭代器
判断 treeSet.contains();
补充:TreeSet集合的使用
Comparator 实现定制比较(比较器)
Comparable 可比较的
测试代码1:
package com.me.set;
import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet的使用
* 存储结构:红黑树
*/
public class TreeSetTest {
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
System.out.println("==========3.1增强for==================");
for (String s : treeSet) {
System.out.println(s);
}
//3.2使用迭代器
System.out.println("============3.2使用迭代器=============");
Iterator<String> iterator = treeSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//4.判断
System.out.println(treeSet.contains("abc"));
System.out.println(treeSet.isEmpty());
}
}
测试代码2:
package com.me.set;
import com.me.Person;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 使用treeSet保存数据
* 存储结构:红黑树
* 要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
*/
public class TreeSetTest2 {
public static void main(String[] args) {
//创建集合
TreeSet<Person> persons=new TreeSet<>();
Person p1=new Person("xyz",20);
Person p2=new Person("hello",22);
Person p3=new Person("zhangsan",25);
Person p4=new Person("zhangsan",20);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
//2.删除
// persons.remove(p1);
// persons.remove(new Person("zhangsan",25)); //可以删除
// System.out.println("删除之后:"+persons.size());
//3.遍历
//3.1使用增强for
System.out.println("=============3.1增强for================");
for (Person person : persons) {
System.out.println(person.toString());
}
//3.2使用迭代器
System.out.println("==============3.2使用迭代器=============");
Iterator<Person> iterator = persons.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//4.判断
System.out.println(persons.contains(p1));
System.out.println(persons.contains(new Person("zhangsan",25)));
System.out.println(persons.isEmpty());
}
}
测试代码3:
package com.me.set;
import com.me.Person;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet集合的使用
* Comparator:实现定制比较(比较器)
* Comparable:可比较的
*/
public class TreeSetTest3 {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<Person> persons=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",20);
Person p2=new Person("hello",22);
Person p3=new Person("zhangsan",25);
Person p4=new Person("zhangsan",18);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println(persons.toString());
}
}
测试代码4:
package com.me.set;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 要求:使用TreeSet集合实现字符串按照长度进行排序
* helloworld zhang lisi wangwu beijing xian nanjing
* Comparator接口实现定制比较
*/
public class TreeSetTest4 {
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("helloworld");
treeSet.add("pingguo");
treeSet.add("lisi");
treeSet.add("zhangsan");
treeSet.add("beijing");
treeSet.add("cat");
treeSet.add("nanjing");
treeSet.add("xian");
System.out.println(treeSet.toString());
}
}
1.5、Map
Map接口的特点
1. 用于存储任意键值对(key - value)
2. 键:无序、无下标、不允许重复(唯一)
3. 值:无序、无下标、允许重复
方法:
1. V put(K key, V value) 将对象存到集合中,关联键值
2. Object get(Object key) 根据键获得对应的值
3. Set<K> 返回所有的Key
4. Collection<V> values() 返回包含所有值的Collection集合
5. Set<Map.Entry<K, V>> 键值匹配的Set集合
1.5.1、Map接口的使用
package com.me.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Map接口的使用
* 特点:(1)存储键值对 (2)键不能重复,值可以重复 (3)无序
*/
public class MapTest {
public static void main(String[] args) {
//创建map集合
Map<String,String> map=new HashMap<>();
//1添加元素
map.put("CN","中国");
map.put("UK","英国");
map.put("USA","美国");
System.out.println("元素个数:"+map.size());
System.out.println(map.toString());
//2删除
// map.remove("USA");
// System.out.println("删除之后:"+map.size());
//3.遍历
//3.1 使用KeySet
System.out.println("===============3.1 使用KeySet==================");
Set<String> keySet = map.keySet();
for (String key : map.keySet()) {
System.out.println(key+"-----"+map.get(key));
}
//3.2 使用entrySet方法
System.out.println("==================3.2 使用entrySet方法======================");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"-----"+value);
}
//4.判断
System.out.println(map.containsKey("CN"));
System.out.println(map.containsValue("泰国"));
}
}
1.5.2、HashMap
JDK1.2版本,线程不安全,运行效率快,允许用null作为key或者value
存储结构:哈希表(数组+链表+红黑树)
使用key可使hashcode和equals作为重复
增、删、遍历、判断与上述一致
源码分析总结:
- HashMap刚创建时,table是null,节省空间,当添加第一个元素时,table容量调整为16
- 当元素个数大于阈值(16*0.75 = 12)时,会进行扩容,扩容后的大小为原来的两倍,目的是减少调整元素的个数
- jdk1.8 当每个链表长度 >8 ,并且数组元素个数 ≥64时,会调整成红黑树,目的是提高效率
- jdk1.8 当链表长度 <6 时 调整成链表
- jdk1.8 以前,链表时头插入,之后为尾插入
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // hashMap初始容量大小
static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap的数组最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
static final int TREEIFY_THRESHOLD = 8;//jdk1.8 当每个链表长度 >8 ,会调整成红黑树
static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8 当链表长度 <6 时 调整成链表
static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当每个链表长度 >8 ,并且数组元素个数 ≥64时,会调整成红黑树
transient Node<K,V>[] table; //哈希表中的数组
size;//元素个数
测试代码:
package com.me.map;
import com.me.Person;
import java.util.HashMap;
import java.util.Map;
/**
* HashMap集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 使用key的hashcode和equals作为重复
*/
public class HashMapTest {
public static void main(String[] args) {
//创建集合
HashMap<Student,String> students=new HashMap<Student,String>();
//刚创建hashmap之后没有添加元素table=null,size=0 目的是节省空间
//添加元素
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,"南京");
students.put(new Student("沙和尚",102),"杭州"); //为了加不进来,可以重写hashcode和equals方法
System.out.println("元素的个数:"+students.size());
System.out.println(students.toString());
//2删除
// students.remove(s1);
// System.out.println("删除之后:"+students.size());
//3.遍历
//3.1使用keySet()
System.out.println("==============3.1使用keySet()================");
for (Student key : students.keySet()) {
System.out.println(key.toString()+"-------"+students.get(key));
}
//3.2使用entrySet()
System.out.println("==============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.containsKey(new Student("孙悟空",100)));
System.out.println(students.containsValue("杭州"));
System.out.println(students.isEmpty());
}
}
1.5.3、HashTable
JDK1.0版本,线程安全呢,允许效率慢,不允许null为key或者value
1.5.4、Properties
HashTable的子类,要求key和value都是String。通常用于配置文件的读取
1.5.5、TreeMap
实现了SortedMap接口(是map的子接口),可以对key自动排序
测试代码:
package com.me.map;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* TreeMap的使用
* 存储结构:红黑树
*/
public class TreeMapTest {
public static void main(String[] args) {
//创建集合(定制比较)
TreeMap<Student, String> treeMap = new TreeMap<Student,String>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return 0;
}
});
Student s1=new Student("孙悟空",100);
Student s2=new Student("猪八戒",101);
Student s3=new Student("沙和尚",102);
//1.添加元素
treeMap.put(s1,"北京");
treeMap.put(s2,"上海");
treeMap.put(s3,"深圳");
treeMap.put(new Student("沙和尚",102),"南京");
System.out.println("元素个数:"+treeMap.size());
System.out.println(treeMap.toString()); //需要实现Comparable接口
//2.删除
// treeMap.remove(s3);
// treeMap.remove("猪八戒",101);//可以删除
// System.out.println("删除之后:"+treeMap.size());
//3遍历
//3.1使用keySet
System.out.println("=============3.1使用keySet============");
for (Student key : treeMap.keySet()) {
System.out.println(key+"------"+treeMap.get(key));
}
//3.2使用entrySet
System.out.println("============3.2使用entrySet==========");
for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
System.out.println(entry.getKey()+"-----"+entry.getValue());
}
//4判断
System.out.println(treeMap.containsKey(s1));
System.out.println(treeMap.containsKey(new Student("沙和尚",102)));
System.out.println(treeMap.isEmpty());
}
}
1.6、Collections工具类
概念:集合工具类,定义了除了存取以外的集合常用方法
直接二分查找int i = Collections.binarySearch(list, x);
成功返回索引
其他方法 : copy复制、reverse反转、shuffle打乱
package com.me.Collections工具类;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Collections工具类的使用
*/
public class CollectionsTest {
public static void main(String[] args) {
List<Integer> list=new ArrayList<>();
list.add(20);
list.add(5);
list.add(12);
list.add(30);
list.add(6);
System.out.println("排序之前:"+list.toString());
//sort排序
Collections.sort(list);//默认是升序
System.out.println("排序之后"+list.toString());
//binarySearch 二分查找
int i = Collections.binarySearch(list, 132);
System.out.println(i);
//copy复制
List<Integer> dest=new ArrayList<>();
for (int k=0;k<list.size();k++){
dest.add(0);
}
Collections.copy(dest,list);
System.out.println(dest.toString());
//reverser 反转
Collections.reverse(list);
System.out.println("反转之后:"+list.toString());
//shuffle 打乱
Collections.shuffle(list);
System.out.println("打乱之后:"+list.toString());
//补充:list转成数组
System.out.println("==============list转成数组===========");
Integer[] arr = list.toArray(new Integer[0]);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
//数组转为list
System.out.println("=============数组转为list==========");
String[] names={"张三","李四","王五"};
List<String> stringList = Arrays.asList(names); //这个集合是一个受限集合,不能添加和删除
System.out.println(stringList.toString());
//基本类型数组转为集合时,需要修改为包装类型
Integer[] nums={100,200,300,400,500};
List<Integer> numsList = Arrays.asList(nums);
System.out.println(numsList.toString());
}
}
1.7、总结
集合的概念
对象的容器,和数组相似,定义了对多个对象进行操作的常用方法
List集合
有序、有下标、元素可以重复、(ArrayList、LinkList、Vector)
Set集合
无序、无下标、元素不可重复。(HashSet,TreeSet)
Map集合
存储一对数据,无序,无下标,键不可重复,值可以重复(HashMap,HashTable,TreeMap)
Collections
集合工具类,定义了除了存取以外的集合常用方法