集合的概念
概念
对象的容器,定义了对多个对象进行操作的常用方法;可实现数组的功能
###与数组的区别
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
Collection体系集合
Collection父接口
方法
- add() 添加一个对象
collection.add("忻州");
collection.add("太原");
collection.add("大同");
collection.add("运城");
- addAll() 将一个集合中的所有对象添加到此集合中
Collection collection = new ArrayList();
Collection collection2 = new ArrayList();
((ArrayList) collection).add("zhangsan");
((ArrayList) collection).add("list");
((ArrayList) collection).add("wangwu");
((ArrayList) collection2).addAll(collection);
System.out.println(collection2.toString());
- remove() 在此集合中移除o对象
collection.remove("运城");
- size() 返回此集合中的元素个数
System.out.println("删除之后元素个数"+collection.size());
- isEmpty() 判断此集合是否为空
System.out.println("是否为空"+collection.isEmpty());
- clear() 清空此集合中的所有对象
collection.clear();
- comtains() 检查此集合中是否包含o对象
System.out.println("是否存在"+collection.contains("北京"));
- equals() 比较此集合是否与指定对象相等
boolean val=collection.equals(collection1);
循环
- 增强for ,使用iter快速输入
for (Object o : collection) {
System.out.println(o);
}
- 使用迭代器,用来遍历集合的一种统一方式
Iterator it = collection.iterator();
while(it.hasNext()){
Object o = it.next();
System.out.println(o);
//删除
it.remove();
}
//注意事项
//(1)it.next()不能调用多次
//(2)在迭代过程中不能使用集合的删除方式(collection.remove(o));,只能使用迭代器的删除方式
List接口与实现类
特点
有序,有下标,元素可以重复
方法
- add() 添加一个对象
//创建集合
List list = new ArrayList();
//(1)添加
list.add("华为");
list.add("小米");
list.add("苹果");
list.add("vivo");
list.add("华为");
list.add("华为");
list.add(0,"三星");
- remove() 在此集合中移除o对象
list.remove("华为");//删除第一个华为
list.remove(1);//index 位置
- size() 返回此集合中的元素个数
System.out.println("元素个数:"+list.size());
- isEmpty() 判断此集合是否为空
System.out.println(list.isEmpty());
- clear() 清空此集合中的所有对象
list.clear();
- comtains() 检查此集合中是否包含o对象
System.out.println(list.contains("华为"));
- indexOf() 获取位置
System.out.println(list.indexOf("华为"));
System.out.println(list.lastIndexOf("华为"));
循环
- 增强for
for (Object o : list) {
System.out.println(o);
}
- 使用迭代器
Iterator it = list.iterator();
while(it.hasNext()){
Object o = it.next();
System.out.println(o);
}
- 使用for
for (int i = 0; i <list.size() ; i++) {
System.out.println(list.get(i));
}
- 使用列表迭代器【功能更加强大,可以逆序遍历,可以添加,删除,修改】
ListIterator lit = list.listIterator();
while(lit.hasNext()){
System.out.println(lit.nextIndex()+"..."+lit.next());
}
System.out.println("-------逆序遍历-------");
while (lit.hasPrevious())
System.out.println(lit.previousIndex()+"..."+lit.previous());
Student类型的对象作为元素
public class TestList2 {
public static void main(String[] args) {
List list = new ArrayList();
Student s1 = new Student("张三",20);
Student s2 = new Student("李四",21);
Student s3 = new Student("王五",22);
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println("元素个数"+list.size());
System.out.println("之间打印"+list.toString());
//2删除
//删除的依据:比较equals方法
//面试题:equals与==的区别?
//(1)==如果是基本类型比较的数据,引用类型比较的是地址
//(2)equals方法默认比较的是地址,如果想改变比较规则,可以重写equals方法
//重写?
//(1)在子类和父类中,方法名,参数列表,返回值类型必须和父类的方法相同
//(2)访问修饰符可以和父类相同,或者比父类更宽松
// list.remove(s3);
// System.out.println("删除之后"+list.toString());
list.remove(new Student("王五",22));
System.out.println("删除之后"+list.toString());
//3.遍历
//3.1增强for
for (Object o : list) {
System.out.println(o);
}
//3.2使用迭代器
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//3.3使用for
for (int i = 0; i <list.size() ; i++) {
System.out.println(list.get(i));
}
//3.4列表迭代器
ListIterator lit = list.listIterator();
while(lit.hasNext()){
System.out.println(lit.nextIndex()+"..."+lit.next());
}
while(lit.hasPrevious()){
System.out.println(lit.previousIndex()+"..."+lit.previous());
}
//4.判断【依据equals方法】
System.out.println(list.contains(new Student("张三",20)));
System.out.println(list.isEmpty());
//5.查找位置
System.out.println(list.indexOf(s1));
System.out.println(list.indexOf(new Student("王五",19)));
}
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
}
}
Integer类型作为元素
注:
- 不能直接list.remove(value);value会被当成下标,出现IndexOutOfBoundsException错误
- 应该list.remove(new Integer(value));
public class TestList3 {
public static void main(String[] args) {
List list = new ArrayList();
//自动装箱Integer类型
list.add(10);
list.add(30);
list.add(20);
list.add(40);
//删除:IndexOutOfBoundsException
//list.remove(10);//当成下标
list.remove(new Integer(10));
System.out.println("删除之后:"+list.toString());
}
}
List实现类
ArrayList【重点】
- 特点
存储结构:数组,查询快,增删慢
DK1.2提供,线程不安全 - 代码
public class TestArrayList {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList();
Student s1 = new Student("刘备", 18);
Student s2 = new Student("曹操", 18);
Student s3 = new Student("孙权", 18);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println(arrayList.size());
System.out.println(arrayList.toString());
//删除
arrayList.remove(new Student("孙权",18));
System.out.println(arrayList.toString());
//3.遍历
//3.1使用增强for
for (Object o : arrayList) {
System.out.println(o);
}
//3.2迭代器
Iterator it = arrayList.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//3.3使用for
for (int i = 0; i <arrayList.size() ; i++) {
System.out.println(arrayList.get(i));
}
//3.4列表迭代器【指针默认指向0 】
ListIterator lit = arrayList.listIterator(arrayList.size());
while(lit.hasPrevious()){
System.out.println(lit.previousIndex()+"..."+lit.previous());
}
//4.判断
System.out.println(arrayList.isEmpty());
System.out.println(arrayList.contains(new Student("孙权",19)));
//5.获取位置
System.out.println(arrayList.indexOf(new Student("孙权",19)));
}
static class Student extends Object {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestArrayList.Student student = (TestArrayList.Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
}
}
ArrayList源码分析
LinkedList
- 特点
存储结构:双向链表,增删快,查询慢 - 代码
public class TestLinkedList {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
Student s1 = new Student("张三",19);
Student s2 = new Student("李四",19);
Student s3 = new Student("王五",19);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
System.out.println("元素个数"+linkedList.size());
System.out.println("直接打印"+linkedList.toString());
//2.删除
linkedList.remove(new Student("王五",19));
System.out.println(linkedList.toString());
//3.遍历
//3.1使用增强for
for (Object o : linkedList) {
System.out.println(o);
}
//3.2迭代器
Iterator it = linkedList.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//3.3使用for
for (int i = 0; i <linkedList.size() ; i++) {
System.out.println(linkedList.get(i));
}
//3.4列表迭代器【指针默认指向0 】
// ListIterator lit = linkedList.listIterator(linkedList.size());
// while(lit.hasPrevious()){
// System.out.println(lit.previousIndex()+"..."+lit.previous());
// }
//4.判断
System.out.println(linkedList.isEmpty());
System.out.println(linkedList.contains(new Student("张三",19)));
//5.获取位置
System.out.println(linkedList.indexOf(new Student("张三",19)));
}
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
}
}
Vector【废弃】:向量集合
- 特点
(1)存储结构:数组,查询快,增删慢
(2)jdk1.0提供 ,效率低,线程安全
- 操作
(1)添加:vector.add();
(2)删除:vector.remove();
- 代码
public class TestVector {
public static void main(String[] args) {
Vector vector = new Vector();
vector.add("西瓜");
vector.add("苹果");
vector.add("桃子");
System.out.println("元素个数:"+vector.size());
System.out.println("打印"+vector.toString());
//2.删除
vector.remove("桃子");
System.out.println(vector.toString());
//遍历
//3.遍历
//3.1使用增强for
//3.2迭代器
//3.3使用for
//3.4列表迭代器【指针默认指向0 】
//3.5使用枚举器【类似与迭代器】区别:(1)迭代器可以删除元素,枚举器不能删除 (2)迭代器优化了方法名称
Enumeration elements = vector.elements();
while(elements.hasMoreElements()){
System.out.println(elements.nextElement());
}
//4判断
System.out.println(vector.isEmpty());
System.out.println(vector.contains("西瓜"));
//5获取位置
System.out.println(vector.indexOf("西瓜"));
}
}
Stack
- 继承Vector类
- LinkedList也实现了栈结构
- 操作
(1)入栈:stack.push();
(2)出栈:stack.pop();
- 代码
public class TestStack {
public static void main(String[] args) {
//创建栈
//Stack stack = new Stack();
//LinkedList实现了栈结构
LinkedList stack = new LinkedList();
//入栈
stack.push("泰山");
stack.push("嵩山");
stack.push("华山");
//出栈
int count = stack.size();
for (int i = 0; i < count ; i++) {
System.out.println(stack.pop());//删除
}
}
}
Queue
- JDK1.5添加Queue接口:继承Collection接口
- LinkedList实现了Queue接口
- 方法
(1)入队:queue.offer();
(2)出队:queue.poll();
- 代码
public class TestQueue {
public static void main(String[] args) {
//创建队列
Queue queue = new LinkedList();
//1.入队
queue.offer("狗");
queue.offer("猫");
//2.出队
int count = queue.size();
for (int i = 0; i < count; i++) {
System.out.println(queue.poll());
}
}
}
泛型集合与工具类
概念
Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递
语法
(1)<T,…> :T称为类型占位符,表示一种引用类型,使用一个大写字母表示
(2)如果有了多个类型占位符,使用逗号隔开
好处
(1)提高代码的重用性
(2)防止类型转换异常,提高代码的安全性
常见形式
泛型类
在类名后面加上一个尖号<T,…>,称为泛型类
public class Generic<T> {
private String name;
private int age;
//使用泛型类声明成员变量
private T t;
private T[] ts;
//泛型类的类型作为方法的参数和返回值类型
public T show(String gender,T t){
System.out.println(name+"..."+age+"..."+gender+"..."+t);
return t;
}
}
public class TestGeneric {
public static void main(String[] args) {
// 声明泛型类对象,jdk1.7 new后面泛型可以省略
Generic<String> generic = new Generic<>();
String r1 = generic.show("男","上海");
Generic<Integer> generic2 = new Generic<>();
Integer r2 = generic2.show("女",1001);
}
}
//在类中不能使用泛型声明参数个数相同的重载方法
public class Generic2<T,E> {
public void show(T t){
System.out.println(t);
}
// public void show(E e){
// System.out.println(e);
// }
}
泛型接口
泛型接口:在接口名的后面加上<T,…>,称为泛型接口
public interface Usb<T> {
//泛型接口类型不能声明静态常量
//T t;
//泛型接口的类型可以作为方法的参数或返回值类型
public T show(String name ,T t);
}
实现泛型接口
public class Upan implements Usb<Integer> {
@Override
public Integer show(String name, Integer s) {
System.out.println(name +"..."+s);
return null;
}
}
泛型类实现泛型接口
public class Mouse<A> implements Usb<A>{
@Override
public A show(String name, A a) {
System.out.println(name +"..."+a);
return a;
}
}
创建对象,调用方法
public class TestUsb {
public static void main(String[] args) {
//用法1:实现类不是泛型类
Upan upan = new Upan();
upan.show("张三",121);
//用法2:实现类也是泛型类
Mouse<Double> mouse = new Mouse<Double>();
mouse.show("李四",11.1);
}
}
泛型方法
在返回值类型的前面加上<T,…>,称为泛型方法
public class Student {
//泛型方法:在返回值类型的前面加上<T,...>,称为泛型方法
//泛型方法的类型作为方法的参数和返回值类型
public static <T>T study(String name,T t){
System.out.println(name +"好好学习"+t);
return t;
}
}
调用泛型方法
public class TestStudent {
public static void main(String[] args) {
Student.study("张三",20);
Student.study("张三","java");
Student.study("张三",20.3);
}
}
泛型类的使用
public class TestArrayList {
public static void main(String[] args) {
// ArrayList arrayList = new ArrayList();
// arrayList.add(100);
// arrayList.add("hello");
// arrayList.add(3.23);
ArrayList<String> arrayList = new ArrayList<>();
ArrayList<Integer> arrayList2 = new ArrayList<>();
arrayList.add("123");
arrayList.add("123qff");
arrayList.add("ads");
System.out.println("-----增强for-----");
for (String s : arrayList) {
System.out.println(s);
}
System.out.println("------迭代器------");
Iterator<String> iterator = arrayList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//for
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
//列表迭代器
ListIterator lit = arrayList.listIterator();
while(lit.hasNext()){
System.out.println(lit.next());
}
}
}
泛型方法的使用
创建Student类
public class Student {
}
创建CollegeStudent类继承Student类
public class CollegeStudent extends Student {
}
创建对象,调用方法
public class TestArrayList2 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
//printList(list);
System.out.println(list.toString());
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(10);
list2.add(20);
list2.add(30);
//printList(list2);
ArrayList<Student> list3 = new ArrayList<>();
ArrayList<CollegeStudent> list4 = new ArrayList<>();
ArrayList<Object> list5 = new ArrayList<>();
printList(list3);
//printList(list4);
printList(list5);
}
//第一种方法:泛型方法
public static<T> void printList(ArrayList<T> list){
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
//第二种方法:使用泛型通配符?,?表示任何类型
//泛型上限 ?extends Student Student类型或Student子类
//泛型下限 ?super Student Student类型或Student父类
public static void printList(ArrayList<? super Student> list){
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
注意事项
- 泛型不能在类中声明静态属性
- static修饰的属性是静态属性先于对象,泛型类型取决于创建对象时传入的实际类型
- 泛型不能在类中初始化对象或数组,但是可以声明引用或数组
- 实例化对象需要分配空间,没有明确类型不能开辟空间
- 初始化数组时需要给元素分配空间,泛型类型不确定无法分配空间
- 在类中不能使用泛型声明参数个数相同的重载方法
- 使用不同实际类型创建出的泛型类对象的引用不可以相互赋值
Collection工具类
- 概念
集合工具类,定义了除了存取以外的集合常用方法 - 方法
Collections.sort(); 排序
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
Collections.sort(list);
Collections.binarySearch(); 二分查找
int pos = Collections.binarySearch(list, 20);
Collections.copy(); 复制集合
List<Integer> list2 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
list2.add(0);
}
Collections.copy(list2,list);
Collections.fill(); 填充
Collections.fill(list,100);
Collections.frequency(); 查找指定元素出现的次数
int count = Collections.frequency(list,20);
Collections.max();最大值
Collections.min();最小值
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));
Collections.reverse(List<?> list) 反转集合中元素的顺序
Collections.reverse(list);
Collections.shuffle(List<?> list) 随机重置集合元素的位置
Collections.shuffle(list);
集合转成数组
注意事项:
- 数组的长度如果小于等于集合的大小,返回实际集合的元素个数
- 数组的长度如果大于集合的大小,返回指定的长度数组
Integer[] arr = list.toArray(new Integer[6]);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
数组转成集合
注意事项
- 此集合可以修改,不能添加和删除元素,因为数组创建后长度不能修改
Integer[] nums = new Integer[]{100,200,300};
//集合不能添加和删除元素
List<Integer> list3 = Arrays.asList(nums);
System.out.println(list3.toString());
Set接口与实现类
特点
无序无下标,元素不可重复
方法
全部继承自Collection中的方法
public class TestSet {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
//(1)添加元素
set.add("xigua");
set.add("xiangjiao");
set.add("pinguo");
set.add("yingtao");
set.add("xigua");
System.out.println("元素个数:"+set.size());
System.out.println("打印:"+set.toString());
//删除
set.remove("pinguo");
System.out.println("删除之后"+set.toString());
//遍历
//3.1增强for
for (String s:set){
System.out.println(s);
}
//3.2迭代器
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//4.判断
System.out.println(set.isEmpty());
System.out.println(set.contains("yingtao"));
}
}
Set实现类
HashSet【重点】
- 存储结构:哈希表【数组+链表】,基于hashCode,equals实现元素不重复
- 存储的过程
- 根据元素的hashCode()方法的hash值计算位置,如果这个位置没有元素直接加入
- 如果有元素会调用equals()进行判断,结果为true,拒绝存入,如果为false,形成链表
public class TestHashSet {
public static void main(String[] args) {
HashSet<Student> hashSet = new HashSet<Student>();
//LinkedHashSet<Student> hashSet = new LinkedHashSet<Student>();有序
Student s1 = new Student("张三", 20);
Student s2 = new Student("李四", 22);
Student s3 = new Student("王五", 18);
//1.添加元素
hashSet.add(s1);
hashSet.add(s2);
hashSet.add(s3);
//如果两个对象的名字和年龄相同,认为同一个人
hashSet.add(new Student("王五", 18));
System.out.println("元素个数" + hashSet.size());
System.out.println("打印:" + hashSet.toString());
//(2)删除
//hashSet.remove(new Student("王五", 18));
//System.out.println("删除之后:"+hashSet.toString());
//(3)遍历
for (Student student : hashSet) {
System.out.println(student.toString());
}
System.out.println("-------------");
Iterator<Student> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//(4)判断
System.out.println(hashSet.isEmpty());
System.out.println(hashSet.contains(new Student("王五", 18)));
}
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 +
'}';
}
//重写hashcode和equals方法参与的属性保持一致。
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return name.hashCode()+age;
}
}
}
LinkedHashSet【不重要】
双向链表实现的HashSet,按照链表进行存储,即可保留元素的插入顺序
//HashSet<Student> hashSet = new HashSet<Student>(); 无序
LinkedHashSet<Student> hashSet = new LinkedHashSet<Student>(); 有序
TreeSet
public class TestTreeSet {
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>();
//1.添加元素
treeSet.add(10);
treeSet.add(8);
treeSet.add(15);
treeSet.add(9);
treeSet.add(6);
treeSet.add(20);
treeSet.add(6);
System.out.println("元素个数:"+treeSet.size());
System.out.println("打印:"+treeSet.toString());
//2删除
treeSet.remove(10);
System.out.println("删除之后:"+treeSet.toString());
//3遍历
//3.1 增强for
for (Integer integer : treeSet) {
System.out.println(integer);
}
//3.2 迭代器
Iterator<Integer> it = treeSet.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
//4判断
System.out.println(treeSet.isEmpty());
System.out.println(treeSet.contains(20));
}
}
制定比较规则的TreeSet
public class TestTreeSet2 {
public static void main(String[] args) {
//创建比较器,定制比较规则【匿名内部类】
Comparator<Student> comp = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int n1 = o1.name.compareTo(o2.name);
int n2 = o1.age - o2.age;
return n1 == 0 ? n2 : n1;
}
};
// 创建集合,并传递比较器
TreeSet<Student> treeSet = new TreeSet<Student>(comp);
Student s1 = new Student("张三", 19);
Student s2 = new Student("李四", 20);
Student s3 = new Student("王五", 18);
//添加
//ClassCastException 类型转换异常,Student cannot be cast to java.lang.Comparable,Student类没有实现Comparable<T>接口,没有comparTo的比较方法,所以无法添加
//要求:(1)元素实现Comparable接口,实现compareTo方法,编写比较规则,返回0,认为是重复元素
//要求:(2)使用Comparator定制比较规则,创建集合通过构造方法传入。优先级高于自然排序
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(new Student("王五", 18));
System.out.println("元素个数:" + treeSet.size());
System.out.println("打印:" + treeSet.toString());
treeSet.remove(new Student("王五", 18));
//3.遍历
//3.1增强for
for (Student student : treeSet) {
System.out.println(student.toString());
}
//3.2迭代器
Iterator<Student> it = treeSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4.判断
System.out.println(treeSet.isEmpty());
System.out.println(treeSet.contains(new Student("王五", 18)));
}
static class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 +
'}';
}
// 自然排序
// 指定比较规则:返回值 >0 ==0 表示重复 <0
@Override
public int compareTo(Student o) {
//先比年龄
int n1 = this.age - o.age;
//再比姓名
int n2 = this.name.compareTo(o.name);
return n1 == 0 ? n2 : n1;
}
}
}
练习:TreeSet实现字符串按照长度排序,如果长度相同,按照编码顺序
public class TestTreeSet3 {
public static void main(String[] args) {
//创建比较器
Comparator<String> comp = 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<String> treeSet = new TreeSet<>(comp);
treeSet.add("afbaidasnl");
treeSet.add("ffdasnl");
treeSet.add("basnl");
treeSet.add("idal");
treeSet.add("fbaidahhsn");
System.out.println(treeSet.toString());
}
}
二叉查找树
- 代码
public class BinarySearchTree {
//根节点
private Node root;
//添加元素
public void add(int v) {
if (this.root == null) {
this.root = new Node(v);
System.out.println("添加了根节点:" + v);
} else {//不为空
this.root.addChild(v);
}
}
//中序遍历
public void middlelist(){
this.root.print();
}
//节点类
static class Node {
//数据
private int value;
//左节点
private Node left;
//右节点
private Node right;
public Node(int value) {
this.value = value;
}
//添加孩子方法
public void addChild(int v) {
if (v < this.value) {
if (this.left == null) {
this.left = new Node(v);
System.out.println(v + "加在了" + this.value + "左边");
} else {
//递归
this.left.addChild(v);
}
} else if (v > this.value) {
if (this.right == null) {
this.right = new Node(v);
System.out.println(v + "加在了" + this.value + "右边");
} else {
//递归
this.right.addChild(v);
}
}else{
System.out.println("重复元素:" + v);
}
}
//打印 左 根 右
public void print(){
//左
if(this.left!=null){
this.left.print();
}
//根
System.out.println(this.value);
//右
if(this.right!=null){
this.right.print();
}
}
}
}
public class TestTree {
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
tree.add(10);
tree.add(5);
tree.add(13);
tree.add(6);
tree.add(40);
tree.add(9);
System.out.println("====中序遍历====");
tree.middlelist();
}
}
Map接口与实现类
Map父接口
特点
- 存储一对数据(Key-Value)
- 键不可重复,值可以重复
- 无序,无下标
方法
- put(); 添加元素
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美丽国");
map.put("usa","漂亮国");
- remove(); 删除元素
map.remove("uk");
- Set keySet(); 返回所有的key
Set<String> set = map.keySet();
- Object get(Object key); 根据键获取对应的值
System.out.println(map.get("cn"));
- Collection values(); 返回包含所有值的Collection集合
Collection<String> coll = map.values();
- Set<Map.entry<K,V>> entrySet(); 键值匹配的Set集合
Set<Map.Entry<String,String>> entries = map.entrySet();
- map.containsKey();map.containsValue();是否存在
System.out.println(map.containsKey("kor"));
System.out.println(map.containsValue("美丽国"));
循环
- 使用entrySet();返回包含映射关系的set集合【推荐】
System.out.println(map.get("cn"));
Set<Map.Entry<String,String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey()+"..."+entry.getValue());
}
- 使用keySet();返回包含键的set集合
Set<String> set = map.keySet();
for(String key:set){
System.out.println(key+"..."+map.get(key));
}
实现类
HashMap
- 存储结构哈希表,键重复依据hashCode和equals方法
- JDK1.2版本,线程不安全,运行效率快
- 允许用null作为key或是value
代码
public class TestHashMap {
public static void main(String[] args) {
HashMap<Student,String> hashMap = new HashMap<>();
// LinkedHashMap<Student,String> hashMap=new LinkedHashMap<>();
//1.添加
Student s1 = new Student("张三",15);
Student s2 = new Student("里斯",14);
Student s3 = new Student("王五",17);
hashMap.put(s1,"南京");
hashMap.put(s2,"天津");
hashMap.put(s3,"上海");
hashMap.put(new Student("王五", 17), "南京");
System.out.println("元素个数"+hashMap.size());
System.out.println(hashMap.toString());
//2.删除
hashMap.remove(new Student("王五",17));
System.out.println("删除之后:"+hashMap.toString());
//3.遍历
//3.1 entrySet
System.out.println("=--=-entrySet-=--");
Set<Map.Entry<Student,String>> entries = hashMap.entrySet();
for (Map.Entry<Student, String> entry : entries) {
System.out.println(entry.getKey().toString()+"..."+entry.getValue());
}
//3.2 keySet()
System.out.println("-----keySet()------");
Set<Student> students = hashMap.keySet();
for (Student student : students) {
System.out.println(student.toString()+"..."+hashMap.get(student));
}
//4.判断
System.out.println(hashMap.containsKey(new Student("王五",17)));
System.out.println(hashMap.containsValue("上海"));
}
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 +
'}';
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
}
LinkedHashMap
- 双向链表保存HashMap的顺序,有顺序的HashMap
//HashMap<Student,String> hashMap = new HashMap<>();
LinkedHashMap<Student,String> hashMap=new LinkedHashMap<>();
TreeMap
- 存储结构红黑树,重复依据排序实现
- 可以对key自动排序,key需实现Comparable接口,或使用Comparator定制比较
代码
public class TestTreeMap {
public static void main(String[] args) {
Comparator<Student> comp = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int n1 = o1.name.compareTo(o2.name);
int n2 = o1.age - o2.age;
return n1 == 0?n2 : n1;
}
};
TreeMap<Student,String> treeMap = new TreeMap<Student,String>(comp);
Student s1=new Student("aaa", 20);
Student s2=new Student("xxx", 18);
Student s3=new Student("yyy", 22);
//1添加
treeMap.put(s1, "北京");
treeMap.put(s2, "上海");
treeMap.put(s3, "广州");
treeMap.put(new Student("yyy", 22), "深圳");
System.out.println(treeMap.size());
System.out.println(treeMap.toString());
//2删除
// treeMap.remove(new Student("yyy", 22));
// System.out.println(treeMap.toString());
//3遍历
//3.1 使用entrySet
Set<Map.Entry<Student, String>> entries = treeMap.entrySet();
for (Map.Entry<Student, String> entry : entries) {
System.out.println(entry.getKey()+"..."+entry.getValue());
}
System.out.println("-------------");
//3.2 使用keySet
Set<Student> students = treeMap.keySet();
for (Student student : students) {
System.out.println(student.toString()+"..."+treeMap.get(student));
}
//4判断
System.out.println(treeMap.containsKey(new Student("yyy", 22)));
System.out.println(treeMap.containsValue("深圳"));
}
static class Student implements Comparable<Student>{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 +
'}';
}
@Override
public int compareTo(Student o) {
int n1=this.age-o.age;
int n2=this.name.compareTo(o.name);
return n1==0?n2:n1;
}
}
}
Hashtable【了解】
- JDK1.0版本,线程安全,运行效率慢
- 不允许null作为key或者value
Properties:属性集合
- Hashtable的子类
- 特点
- 存储属性名和属性值
- key和value都是String,通常用于读取配置文件
- 没有泛型
- 和IO流有关系
方法
- setProperty();添加元素
properties.setProperty("username","张三");
properties.setProperty("age","20");
properties.setProperty("gender","男");
- stringPropertyNames(); 获取属性名
Set<String> set = properties.stringPropertyNames();
- getProperty(key); 获取属性值
properties.getProperty(s)
循环
- entrySet();返回映射关系的Set集合
Set<Map.Entry<Object,Object>> entries = properties.entrySet();
for(Map.Entry<Object,Object> entry:entries){
System.out.println(entry.getKey()+"..."+entry.getValue());
}
- keySet();返回key的Set集合
Set<Object> keySet = properties.keySet();
for(Object o:keySet){
System.out.println(o+"..."+properties.get(o));
}
- stringPropertyName();返回一组键值【推荐】
Set<String> set = properties.stringPropertyNames();
for(String s:set){
System.out.println(s+"..."+properties.getProperty(s));
}
代码
public class TestProperties {
public static void main(String[] args) {
//创建属性集合
Properties properties = new Properties();
//1.添加元素
properties.setProperty("username","张三");
properties.setProperty("age","20");
properties.setProperty("gender","男");
System.out.println("元素个数"+properties.size());
System.out.println(properties.toString());
//2.删除
properties.remove("gender");
System.out.println(properties.toString());
//3.遍历
//3.1 entrySet();返回映射关系的Set集合
Set<Map.Entry<Object,Object>> entries = properties.entrySet();
for(Map.Entry<Object,Object> entry:entries){
System.out.println(entry.getKey()+"..."+entry.getValue());
}
//3.2 keySet();返回key的Set集合
Set<Object> keySet = properties.keySet();
for(Object o:keySet){
System.out.println(o+"..."+properties.get(o));
}
//3.3 stringPropertyName();【推荐】
Set<String> set = properties.stringPropertyNames();
for(String s:set){
System.out.println(s+"..."+properties.getProperty(s));
}
//4.判断
System.out.println(properties.isEmpty());
System.out.println(properties.contains("username"));
System.out.println(properties.contains("男"));
}
}