一、List
1、数据结构与算法
数据结构:数据的存储方式。
常见的数据结构:栈 队列 数组 链表 二叉树 哈希表
栈的数据结构特点:先进后出,后进先出。弹夹就是典型的栈结构
队列的特点:先进的先出,后进的后出
数组的特点:数组的元素都标有索引,查询快,增删慢。
链表的特点:查询慢,增删快
list接口下的三个子类特点:
Arraylist集合:底层使用的是数组,查询快,增删慢。线程不安全,效率高。
Linkedlist集合:底层使用的是链表,查询慢,增删快。线程不安全,效率高。
Vector:底层使用的是数组,查询快,增删慢。线程安全,效率低。
2、List
List概述及特点:
元素有序(存的顺序和取的顺序一致),但是不连续,允许存储null值,每一个元素都存在一个索引.元素可以重复.
void add ( int index, E element)
在列表的指定位置插入指定元素(可选操作)。
E get(int index)返回列表中指定位置的元素。
int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
int lastIndexOf(Object o)
返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
ListIterator<E> listIterator()
返回此列表元素的列表迭代器(按适当顺序)。
E remove(int index)
移除列表中指定位置的元素(可选操作)。
E set(int index, E element)
用指定元素替换列表中指定位置的元素(可选操作)。
List<E> subList(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
list的反向遍历:
ListIterator 继承自Iterator 可以使用Iterator中的方法
A:ListIterator的特有功能
boolean hasPrevious(): 是否存在前一个元素
E previous(): 返回列表中的前一个元素
以上两个方法可以实现反向遍历 但是注意 要完成反向遍历之前 要先进行正向遍历 这样指针才能移到最后
如果直接反向遍历是没有效果的 因为指针默认位置就在最前面 他前面没有元素
(1)添加与获取
package org.westos.demo2;
import java.util.ArrayList;
import java.util.List;
public class MyTest {
public static void main(String[] args) {
List list=new ArrayList();
list.add(100);
list.add(800);
list.add(300);
list.add("asaa");
list.add(3.15);
// void add ( int index, E element)
// 在列表的指定位置插入指定元素(可选操作)。
System.out.println(list);
System.out.println("----------");
list.add(0,"李白");
System.out.println(list);
list.add(1,"王维");
System.out.println(list);
System.out.println("========");
/* E get(int index)
返回列表中指定位置的元素。*/
Object o = list.get(0);
Object o1 = list.get(1);
System.out.println(o);
System.out.println(o1);
/*
int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
int lastIndexOf(Object o)
返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。*/
int i = list.indexOf(300);
int i1 = list.lastIndexOf(300);
System.out.println(i);
System.out.println(i1);
System.out.println(list.indexOf(100000));//-1
}
}
(2)遍历
package org.westos.demo2;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class MyTest3 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Studnet("李白",22));
list.add(new Studnet("杜甫",24));
list.add(new Studnet("王维",26));
//正向遍历
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
Object next = listIterator.next();
System.out.println(next);
}
//反向遍历:
/* 反向遍历:list的反向遍历:
ListIterator 继承自Iterator 可以使用Iterator中的方法
A:ListIterator的特有功能
boolean hasPrevious(): 是否存在前一个元素
E previous(): 返回列表中的前一个元素
以上两个方法可以实现反向遍历 但是注意 要完成反向遍历之前 要先进行正向遍历 这样指针才能移到最后
如果直接反向遍历是没有效果的 因为指针默认位置就在最前面 他前面没有元素*/
System.out.println("=================");
while (listIterator.hasPrevious()) {
Object previous = listIterator.previous();
System.out.println(previous);
}
}
}
3、ArrayList
List接口的大小可变数组的实现,实现了所有可选列表操作,并允许包括null在内的所有元素。
ArrayList:底层使用的是数组,查询快,增删慢。注意:此实现不是同步的,是线程不安全的。效率高。
元素有序的(存取顺序一致) 元素编有索引,允许元素重复
(1)遍历方式;
ArrayList:底层使用的是数组,查询快,增删慢。此实现不是同步的,是线程不安全的,效率高。
遍历方式有四种:
(1)Iterator iterator = list.iterator();//用hasNext和next方法
(2)ListIterator listIterator = list.listIterator();//自己特有的迭代器
(3)for循环,size()和get()方法
ArrayList集合新的迭代方法:
(4)JDK1.8之后提供了一种迭代方法。
void forEach(Consumer<? super E> action)
执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常。
package org.westos.demo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.function.Consumer;
public class MyTest {
public static void main(String[ ] args) {
//List接口的大小可变数组的实现,实现了所有可选列表操作,并允许包括null在内的所有元素。
//ArrayList:底层使用的是数组,查询快,增删慢。注意:此实现不是同步的,是线程不安全的。效率高。
//元素有序的(存取顺序一致) 元素编有索引,允许元素重复
ArrayList list = new ArrayList();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add("aa");
list.add(null);
System.out.println(list);
//遍历方式一:iterato,用hasNext()和next人()方法
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
System.out.println("---------");
//遍历方式二:用for循环
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
System.out.println(o);
}
System.out.println("========");
//遍历方式三:用listIterator()方法
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
Object next = listIterator.next();
System.out.println(next);
}
/*遍历方式四:JDK1.8之后提供了一种迭代方法。
void forEach(Consumer<? super E> action)
执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常。*/
System.out.println("---------");
list.forEach(new Consumer() {
@Override
public void accept(Object o) {
//o就是集合中的元素
System.out.println(o);
}
});
}
}
(2)排序方法
ArrayList集合新的排序方法
void sort (Comparator < ? super E > c)
分类列表使用提供的 Comparator比较元素。
排序 Comparator 比较器
package org.westos.demo;
import java.util.ArrayList;
import java.util.Comparator;
public class MyTest2 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(900);
list.add(400);
list.add(200);
list.add(100);
//list.add("aaa");
//list.add(3.14);
System.out.println(list);
System.out.println("---------");
//排序方法
/*void sort (Comparator < ? super E > c)
分类列表使用提供的 Comparator比较元素。
排序 Comparator 比较器
* */
list.sort(new Comparator() {
@Override
public int compare(Object a, Object b) {
Integer num= (Integer) a;
Integer num2= (Integer) b;
int i = num.intValue();
int j = num2.intValue();
//升序排列
return i-j;
}
});
System.out.println(list);
}
}
(3)删除和判断
ArrayList集合删除某些元素:
boolean removeIf (Predicate < ? super E > filter)
删除满足给定谓词的这个集合的所有元素。
判断集合为空的方法:isEmpty();
package org.westos.demo4;
import java.util.ArrayList;
import java.util.function.Predicate;
public class MyTest {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
list.add(500);
//根据索引删除 返回的是你删除的那个元素
Object remove = list.remove(0);
System.out.println(remove);
//根据元素删除 返回的是 是否删除成功
boolean remove1 = list.remove(new Integer(200));
System.out.println(remove1);
System.out.println("=======");
ArrayList list1 = new ArrayList();
list1.add(100);
list1.add(200);
list1.add(300);
list1.add(400);
list1.add(500);
list1.removeIf(new Predicate() {
@Override
public boolean test(Object o) {
Integer num= (Integer) o;
return num>300;
}
});
System.out.println(list1);//[100, 200, 300]
//判断集合是否为空
boolean empty = list1.isEmpty();
System.out.println(empty);
//也可以通过判断集合长度来确定集合是否为空
if(list.size()==0){
System.out.println("list集合为空!");
}
}
}
4、Vector
Vector集合与ArrayList集合相同,底层数据结构是数组,查询快,增删慢,但是是线程安全的,即同步的但效率低下。
Vector中的方法:
vector集合的一些方法:
(1)添加元素---->vector.add(“ab”);
----->vector.addelement(“cd”);
(2)遍历元素:A:
vector.forEach(new Consumer() {
@Override
public void accept(Object obj) {
System.out.println(obj);
}
});
B:
Vector容器有一个自己的迭代器,可以遍历集合中的元素。
Enumeration elements(),返回此向量的组件的枚举。
Enumeration 迭代器 hasMoreElements()----->判断还有没有下一个元素
nextElement()----->获取下一个元素
Enumeration<E> elements()
返回此向量的组件的枚举。
(3)取第一个元素:vector.firstElement();
取最后一个元素:vector.lastElement();
根据索引截取一个元素:vector.elementAt(2);
package org.westos.demo4;
import java.util.Enumeration;
import java.util.Vector;
import java.util.function.Consumer;
public class MyTest2 {
public static void main(String[] args) {
Vector vector = new Vector();
//add(E e) 将指定元素添加到此向量的末尾。
vector.add("aaa");
vector.add(111);
vector.add(3.13);
System.out.println(vector);
System.out.println("--------");
/*void addElement(E obj)
将指定的组件添加到此向量的末尾,将其大小增加 1。*/
vector.addElement("cd");
vector.addElement(777);
System.out.println(vector);
System.out.println("--------");
//遍历:方式一,foreach()方法
vector.forEach(new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});
System.out.println("-------------");
// 遍历方式二:采用elements() 方法
Enumeration elements = vector.elements();
while (elements.hasMoreElements()) {
System.out.println(elements.nextElement());
}
System.out.println("--------");
/*
取第一个元素:vector.firstElement();
取最后一个元素:vector.lastElement();
根据索引截取一个元素:vector.elementAt(2);*/
Vector vector1 = new Vector();
vector1.addElement(1);
vector1.addElement("aaa");
vector1.addElement(444);
vector1.addElement(444.33);
Object o = vector1.firstElement();
System.out.println(o);
Object o1 = vector1.lastElement();
System.out.println(o1);
Object o2 = vector1.elementAt(3);
System.out.println(o2);
}
}
5、LinkedList
底层数据结构是链表,增删快,查找慢,线程不安全,效率高,此实现不是同步的
LinkedList集合中的方法:
(1)addFirst():在首位置上增加元素
(2)addLast():在末位置上增加元素
(3)getFirst():返回此列表的第一个元素
(4)getLast():返回此列表的最后一个元素
(5)removeFirst():移除并返回此列表的第一个元素
(6)removeLast():移除并返回此列表的最后一个元素
(7)poll():获取并移除此列表的头(第一个元素)
(8)pollFirst():获取并移除此列表的第一个元素,如果此列表为空,则返回null
(9)pollLast():获取并移除此列表的最后一个元素,如果此列表为空,则返回null
(10)pop():从此列表所表示的堆栈处弹出第一个元素
(11)push():将元素推入此列表所表示的堆栈
package org.westos.demo5;
import java.util.LinkedList;
public class MyTest {
public static void main(String[] args) {
LinkedList list = new LinkedList();
/*(1)addFirst():在链表的首位置上增加元素
(2)addLast():在末位置上增加元素
(3)getFirst():返回此列表的第一个元素
(4)getLast():返回此列表的最后一个元素
(5)removeFirst():移除并返回此列表的第一个元素
(6)removeLast():移除并返回此列表的最后一个元素*/
list.add(11);
list.add(22);
list.add("aaa");
list.add(44.44);
System.out.println(list);
System.out.println("--------");
list.addFirst(true);
list.addFirst(false);
list.addLast(true);
list.addLast(false);
System.out.println(list);
System.out.println("--------");
Object first = list.getFirst();
System.out.println(first);
Object last = list.getLast();
System.out.println(last);
System.out.println("=======");
System.out.println(list);
System.out.println("--------");
Object o = list.removeFirst();
System.out.println("======");
System.out.println(o);
Object o1 = list.removeLast();
System.out.println(o1);
System.out.println(list);
}
}
package org.westos.demo5;
import java.util.LinkedList;
public class MyTest2 {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add(500);
list.add(400);
list.add(300);
list.add(200);
list.add(100);
/*(7)poll():获取并移除此列表的头(第一个元素)
(8)pollFirst():获取并移除此列表的第一个元素,如果此列表为空,则返回null
(9)pollLast():获取并移除此列表的最后一个元素,如果此列表为空,则返回null
(10)pop():从此列表所表示的堆栈处弹出第一个元素
(11)push():将元素推入此列表所表示的堆栈*/
System.out.println(list);
Object poll = list.poll();
System.out.println(poll);
System.out.println("===========");
System.out.println(list);
Object o = list.pollFirst();
System.out.println(o);
Object o1 = list.pollLast();
System.out.println(o1);
System.out.println("===========");
System.out.println(list);
System.out.println("==========");
Object pop = list.pop();
System.out.println(pop);
System.out.println(list);
list.push(333);
System.out.println(list);//[333, 200]
}
}
6、练习题
(1)LinkedList集合框架练习题
需求:请用LinkedList模拟栈数据结构的集合,并测试
先进的后出,后进的先出
package org.westos.demo6;
import java.util.LinkedList;
public class MyTest {
public static void main(String[] args) {
/*需求:请用LinkedList模拟栈数据结构的集合,并测试
先进的后出,后进的先出*/
MyList myList = new MyList();
myList.add(2);
myList.add(33);
myList.add(444);
Object o = myList.get();
System.out.println(o);
o = myList.get();
System.out.println(o);
System.out.println(myList.toString());
}
}
class MyList{
@Override
public String toString() {
return "MyList{" +
"linkedList=" + linkedList +
'}';
}
private final LinkedList linkedList;
public MyList(){
//创建linkedList
linkedList = new LinkedList();
}
//添加元素
public void add(Object o){
linkedList.addFirst(o);
}
//获取元素
// 每次都只能获取栈顶元素
public Object get(){
Object pop = linkedList.pop();
linkedList.addLast(pop);
return pop;
}
}
(2)ArrayList集合框架练习题
去除集合中的重复元素:要求两种方法:
(1)不能创建新的容器,就在本容器中做
(2)创建一个新的容器
package org.westos.demo7;
import java.util.ArrayList;
import java.util.ListIterator;
public class MyTest {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Studnet("李白",22));
list.add(new Studnet("杜甫",3322));
list.add(new Studnet("王维",9999));
list.add(new Studnet("屈原",22));
list.add(new Studnet("屈原",22));
list.add(new Studnet("苏轼",666));
list.add(new Studnet("欧阳修",777));
System.out.println(list);
System.out.println("===========================");
//去除重复元素方式一:创建新集合
ArrayList list2 = new ArrayList();
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
Object next = listIterator.next();
Studnet s= (Studnet) next;
//这里的contains内部采用的是equals方法,因此我们必须重写equals方法
if (!list2.contains(s)){
list2.add(s);
}
}
System.out.println(list2);
//去除重复元素方式二:要求,不能重建新的容器来做,就在本容器中操作
//采用选择排序法的思想:用第一个元素和后面的元素进行对比。
System.out.println("======================");
for (int i = 0; i < list.size()-1; i++) {
for(int j=i+1;j<list.size();j++){
if(list.get(i).equals(list.get(j))){
list.remove(j);
//原来的1位置上的元素去除以后,下一个位置上就变成了1位置。
//但是咱们这时候有一个j++,j就从1变成了2.把此时的1位置就跳过了。直接到了2位置。
//就是这个j必须得和i是连着的。不能是中间跨了一个数。跨了一个数就把一个元素丢了
j--;//j必须--
}
}
}
System.out.println(list);
}
}
7.asList()方法
Arrays工具类的asList(T...t)方法的使用:
将数组转换成集合*/
泛型方法:方法上的泛型,是你在调用方法时,就可以明确方法上泛型的具体数据类型
static <T> List <T> asList(T...a)
返回一个受指定数组支持的固定大小的列表。
package org.westos.demo8;
import java.util.Arrays;
import java.util.List;
public class MyTest2 {
public static void main(String[] args) {
/* Arrays工具类的asList(T...t)方法的使用:
将数组转换成集合*/
//泛型方法:方法上的泛型,是你在调用方法时,就可以明确方法上泛型的具体数据类型
/* static <T> List <T>
asList(T...a)
返回一个受指定数组支持的固定大小的列表。*/
List<String> strings = Arrays.asList("aaa", "ccc", "ddd");
List<Integer> integers = Arrays.asList(99, 2, 111);
//当我传进来的是一个对象数组。他是怎么转换成集合的?他把数组中的元素取出来,再放到集合中
Integer[] arr= {10, 20, 30};
List<Integer> integers1 = Arrays.asList(arr);
System.out.println(integers1.get(0));
System.out.println(integers1);
Integer[] arr2={1,2,3};
Integer[] arr3={5,4,6};
Integer[] arr4={9,8,300};
//传进来多个元素是基本数据类型的数组,转换成的集合是,这个集合中,放了多个数组对象
List<Integer[]> integers2 = Arrays.asList(arr2, arr3, arr4);
System.out.println(integers2);//打印地址值
//通过asList()方法转换过来的集合,有一个弊端,这个转换过来的集合,你不能改变这个集合的长度,
// 也就是说,你不能再次增删集合中的元素。
List<Integer> integers3 = Arrays.asList(100, 222, 777, 444);
//integers3.add(222);//报错
// integers3.remove(0);//报错
//原因:
/* public static <T > List < T > asList(T...a){
//这个方法的内部创建了一个 ArrayList
//但是这个ArrayList 是Arrays里面的一个内部类,不是我们之前学的java.utli包下的ArrayList
return new ArrayList<>(a);
}*/
}
}
8.二维数组
package org.westos.demo8;
import java.util.ArrayList;
import java.util.function.Consumer;
public class MyTest3 {
public static void main(String[] args) {
//二维数组
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("李白",22));
list.add(new Student("杜甫",333));
ArrayList<Student> list2 = new ArrayList<>();
list2.add(new Student("苏轼",66));
list2.add(new Student("苏洵",555));
ArrayList<Student> list3 = new ArrayList<>();
list3.add(new Student("纳兰容若",10));
list3.add(new Student("龚自珍",9999));
//把这三个list放在一个大集合中
ArrayList<ArrayList<Student>> maxList = new ArrayList<>();
maxList.add(list);
maxList.add(list2);
maxList.add(list3);
//遍历集合
for (int i = 0; i < maxList.size(); i++) {
ArrayList<Student> students = maxList.get(i);
for (int j = 0; j < students.size(); j++) {
Student student = students.get(j);
System.out.println(student.getName()+"---"+student.getAge());
}
System.out.println();
}
for (ArrayList<Student> students : maxList) {
for (Student student : students) {
System.out.println(student.getName()+"---"+student.getAge());
}
}
maxList.forEach(new Consumer<ArrayList<Student>>() {
@Override
public void accept(ArrayList<Student> students) {
students.forEach(new Consumer<Student>() {
@Override
public void accept(Student student) {
System.out.println(student.getName()+"---"+student.getAge());
}
});
}
});
}
}
二、Set集合
无序性:存储数据和取出数据的顺序不一致.
唯一性:存储的元素不允许重复
1.HashSet
底层数据结构是哈希表,元素无序(存的顺序和取的顺序不一致),且不允许重复元素,
可以存储null元素,线程不安全,效率高
(1)HashSet的无序性
HashSet存储元素是无序的
package org.westos.demo;
import java.util.HashSet;
public class MyTest {
public static void main(String[] args) {
//HashSet存储元素是无序的
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(100);
hashSet.add(300);
hashSet.add(500);
hashSet.add(700);
hashSet.add(900);
System.out.println(hashSet);
}
}
(2)HashSet的唯一性
HashSet 底层数据结构是哈希表. HashSet 不是线程安全的 集合元素可以是 null
哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) (JDK1.7之前)
当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,
然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
HashSet 集合判断两个元素相等的标准:
两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。
当我们往hashset集合存储对象的时候,会调用对象的hashCode方法,算出一个值,这个值就是确定这个对象放到表中的位置。
那假如有两个对象,算出的位置值是一样的,就会调用equals()方法,去比较两个对象的地址值是否一样,如果一样证明证明是同一个对象.
如果不一样那就存储进去,形成链表结构
为了减少碰撞,我们应该合理的去重写hashCode方法,来减少碰撞(减少调用euquals方法的次数)尽量是元素在哈希表中横向排列,减少链表的形成
package org.westos.demo;
import java.util.HashSet;
public class MyTest2 {
public static void main(String[] args) {
//HashSet保证存储元素的唯一性
HashSet<Student> hashSet = new HashSet<>();
/*
* 当向HashSet集合中存储元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,
根据hashCode值再计算出一个位置值,这个值就是存储的元素在集合中的位置
* */
hashSet.add(new Student("李白",22));
hashSet.add(new Student("杜甫",26));
hashSet.add(new Student("王维",27));
hashSet.add(new Student("李白",20000));
hashSet.add(new Student("李白",22));
//此时的HashSet会存储重复元素,因为Student没有重写equals()方法和hashcode()方法
System.out.println(hashSet);
/*
* 存储元素时,如果将Student类中的hashcode()方法的返回值设置为死值,那么所有对象的hashcode()方法
* 的返回值都相同,这样就会带来一个问题,所有的对象都存储在一个位置,会造成碰撞次数过多
*
* 如何解决?
* 原理:先调用hashcode方法计算hashCode值
* 如果hashCode不同则表示不重复, 如果hashCode相同再调用equals方法进一步检查,
* equals返回真表示重复,否则表示不重复。
*
* 如何重写equals()方法?
* 因为成员变量值影响了哈希值,所以我们把成员变量值相加即可
* 如:
* return this.name.hashCode() + this.age;
这样存在缺陷
s1:name.hashCode()=40,age=30
s2:name.hashCode()=20,age=50
因此可以先比较hashCode值,再通过用equals方法进一步检查
* */
}
}
package org.westos.demo;
public class Student {
private String name;
private int age;
@Override
public int hashCode() {
//这样会造成碰撞次数过多
//return 0;
return this.name.hashCode()+this.age;
}
@Override
public boolean equals(Object obj){
//这里比较地址值其实就是比较hash值
if (this==obj){
return true;
}
//判断obj是否是Studnet类的实例化对象
if (!(obj instanceof Student)){
return false;
}
Student s = (Student) obj;
return this.name.equals(s.name) && this.age == s.age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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;
}
public Student() {
}
}
package org.westos.demo;
import java.util.HashSet;
public class MyTest3 {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
//Integer和String类型重写了hashcode()和equals()方法
hashSet.add(100);
hashSet.add(200);
hashSet.add(300);
hashSet.add(100);
hashSet.add("aaa");
hashSet.add("bbb");
hashSet.add("ccc");
hashSet.add("aaa");
System.out.println(hashSet);
}
}
(3)去重
构造一个包含指定 collection 中的元素的新 set。你把List集合传进来,构建一个HashSet集合,就帮你去重了
ArrayList<Integer> objects = new ArrayList<> ();
objects.add (100);
objects.add (200);
objects.add (100);
objects.add (200);
HashSet<Integer> integers = new HashSet<> (objects);
System.out.println (integers);
2.LinkedHashSet
数据结构 有两个 链表和哈希表
链表保证有序 哈希表保证元素唯一
LinkedHashSet集合的特点:元素有序 , 并且唯一
package org.westos.demo;
import java.util.Iterator;
import java.util.LinkedHashSet;
public class MyTest4 {
public static void main(String[] args) {
LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add(100);
linkedHashSet.add(100);
linkedHashSet.add(120);
linkedHashSet.add(300);
linkedHashSet.add(600);
linkedHashSet.add(900);
linkedHashSet.add(100000);
Iterator<Integer> iterator = linkedHashSet.iterator();
while (iterator.hasNext()){
Integer next = iterator.next();
System.out.println(next);
}
}
}
3.TreeSet
TreeSet集合的特点: 元素唯一,并且可以对元素进行排序
TreeSet排序
排序:
a: 自然排序 使用的是无参构造
要求元素实现Comparable这个接口重写compareTo()方法,根据比较的方法返回值的正负0 来决定元素在二叉树中放置的位置
注意:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素
必须实现Comparable接口 否则无法进行自然排序
Comparable接口中需要重写comparaTo方法, 保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等,则不重复存储
b: 使用比较器排序,使用有参构造
到底使用的是哪一种的排序取决于,构造方法.
(1)自然排序
使用无参构造
自然排序 使用的是无参构造
要求元素实现Comparable这个接口重写compareTo()方法,
根据比较的方法返回值的正负0 来决定元素在二叉树中放置的位置
注意:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素
必须实现Comparable接口 否则无法进行自然排序
保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等
则不重复存储
package org.westos.demo3;
import java.util.TreeSet;
public class MyTest {
public static void main(String[] args) {
//1.自然排序,必须实现Comparable接口,重写comparaTo方法,
TreeSet<Student> treeSet = new TreeSet<>();
treeSet.add(new Student("李白",2222));
treeSet.add(new Student("杜甫",333));
treeSet.add(new Student("王维",443));
treeSet.add(new Student("孟浩然",155));
treeSet.add(new Student("苏轼",66));
treeSet.add(new Student("欧阳修",66));
treeSet.add(new Student("马飞飞",8888));
treeSet.add(new Student("卢本伟",99999));
System.out.println(treeSet);
}
}
--------------------------
package org.westos.demo3;
import java.util.Objects;
public class Student implements Comparable<Student>{
private String name;
private int 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);
}
@Override
public int hashCode() {
return Objects.hash(name, 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;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public int compareTo(Student o) {
//根据年龄进行排序
//这样存在缺陷,只比较年龄不能说明是同一个对象
//return this.age-o.age;
int num= this.age-o.age;
int num2=num==0?this.name.compareTo(o.name):num;
return num2;
//return -num2;
//返回0表示相同,不用排序,也不用添加
//return 0;
}
}
-----------------------------
package org.westos.demo2;
import java.util.TreeSet;
public class MyTest {
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>();
//Integer默认重写了comparaTo方法
treeSet.add(100);
treeSet.add(200);
treeSet.add(300);
treeSet.add(400);
treeSet.add(0);
System.out.println(treeSet);
}
}
按照姓名长度进行排序
package org.westos.demo4;
import java.util.TreeSet;
public class MyTest {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<>();
treeSet.add(new Student("李白",222));
treeSet.add(new Student("杜甫",33));
treeSet.add(new Student("王维",44));
treeSet.add(new Student("孟浩然222",55));
treeSet.add(new Student("苏轼sssssssssssssssss",66));
treeSet.add(new Student("欧阳修aaaaaaa",66));
treeSet.add(new Student("马飞飞",8888));
treeSet.add(new Student("卢本伟",99999));
for (Student student : treeSet) {
System.out.println(student);
}
}
}
---------------------------------------------------------
package org.westos.demo4;
import java.util.Objects;
public class Student implements Comparable<Student>{
private String name;
private int 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);
}
@Override
public int hashCode() {
return Objects.hash(name, 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;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
//根据姓名长度进行排序
int num=this.name.length()-o.name.length();
int num2=num==0?this.name.compareTo(o.name):num;
int num3=num2==0?(this.age-o.age):num2;
return num3;
}
}
(2)比较器排序
使用有参构造
构造方法摘要
TreeSet()
构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。*/
TreeSet(Comparator < ? super E > comparator)
构造一个新的空 TreeSet,它根据指定比较器进行排序。*/
Comparator 接口 强行对某个对象 collection 进行整体排序 的比较函数。
采用比较器排序,根据比较器中的compare()这个方法的返回值的正负0 来决定元素在二叉树中放置的位置
package org.westos.demo5;
import java.util.Comparator;
import java.util.TreeSet;
public class MyTest {
public static void main(String[] args) {
/* 构造方法摘要
TreeSet()
构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。*/
/* TreeSet(Comparator < ? super E > comparator)
构造一个新的空 TreeSet,它根据指定比较器进行排序。*/
// Comparator 接口 强行对某个对象 collection 进行整体排序 的比较函数。
//采用比较器排序,根据比较器中的compare()这个方法的返回值的正负0 来决定元素在二叉树中放置的位置
TreeSet<Integer> treeSet = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
//采用比较器排序,根据比较器中的compare()这个方法的返回值的正负0 来决定元素在二叉树中放置的位置
return a-b;
}
});
treeSet.add(100);
treeSet.add(2);
treeSet.add(30);
treeSet.add(99999999);
treeSet.add(1);
treeSet.add(1);
for (Integer integer : treeSet) {
System.out.println(integer);
}
}
}
根据年龄和姓名长度进行排序
package org.westos.demo5;
import java.util.Comparator;
import java.util.TreeSet;
public class MyTest2 {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student a, Student b) {
//根据年龄大小进行排序
return a.getAge()-b.getAge();
//根据姓名的长度进行排序
/*int num = a.getName().length() - b.getName().length();
int num2=num==0?a.getName().compareTo(b.getName()):num;
int num3=num2==0?a.getAge()-b.getAge():num2;
return num3;*/
}
});
treeSet.add(new Student("李白",222));
treeSet.add(new Student("杜甫",33));
treeSet.add(new Student("王维",44));
treeSet.add(new Student("孟浩然222",55));
treeSet.add(new Student("苏轼sssssssssssssssss",66));
treeSet.add(new Student("欧阳修aaaaaaa",66));
treeSet.add(new Student("马飞飞",8888));
treeSet.add(new Student("卢本伟",99999));
for (Student student : treeSet) {
System.out.println(student);
}
}
}
案例一:
编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
并把最终的随机数输出到控制台。
选HashSet 可以不重复
选TreeSet 不重复还可以排序
package org.westos.demo6;
import java.util.Random;
import java.util.TreeSet;
public class MyTest {
public static void main(String[] args) {
/*编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
并把最终的随机数输出到控制台。
选HashSet 可以不重复
选TreeSet 不重复还可以排序*/
TreeSet<Integer> treeSet = new TreeSet<>();
Random random = new Random();
while (treeSet.size()<10){
int num = random.nextInt(20) + 1;
treeSet.add(num);
}
for (Integer integer : treeSet) {
System.out.println(integer);
}
}
}
案例二:
键盘录入3个学生信息(姓名, 语文成绩, 数学成绩, 英语成绩), 按照总分从高到低输出到控制台
package org.westos.demo6;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class MyTest2 {
public static void main(String[] args) {
//键盘录入3个学生信息(姓名, 语文成绩, 数学成绩, 英语成绩), 按照总分从高到低输出到控制台
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student a, Student b) {
double num= (a.add()-b.add());
double num2=num==0?a.getName().compareTo(b.getName()):num;
//降序排列
return (int) -num2;
}
});
for (int i = 1; i <= 3; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
System.out.println("请输入第"+i+"个学生的语文成绩");
int ch = sc.nextInt();
System.out.println("请输入第"+i+"个学生的数学成绩");
int ma = sc.nextInt();
System.out.println("请输入第"+i+"个学生的英语成绩");
int en = sc.nextInt();
//创建学生对象,把录入的信息,封装到学生学生对象里面
Student student = new Student(name, ch, ma, en);
treeSet.add(student);
}
for (Student student : treeSet) {
System.out.println(student);
}
//按照总分高低排序,输出学生的信息。
System.out.println("名次\t姓名\t语文\t数学\t英语\t总分");
int i=0;
for (Student student : treeSet) {
System.out.println((++i)+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore()+"\t"+student.add());
}
}
}
二.Map
1.Map集合概述和特点
键值映射:
键---------值
学号--------姓名
s001-------张三
s002-------李四
s003-------王五
A:
Map接口概述
查看API可以知道:
将键映射到值的对象
一个映射不能包含重复的键
每个键最多只能映射到一个值
B:
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
C:
Map集合 就是用来存储 这种 键值映射关系的数据 。 Map 是双列集合
一个键只能只能映射一个值,键是唯一的。
多次存储相同的键,就会发生键相同值覆盖。
Map集合的数据结构只跟键有关,跟值没关系。
Collection 单列集合
存储键是String类型 值是Student类型
HashMap 键的数据结构是哈希表,键的唯一性,要靠键重写hashCode()和equals()方法才能保证,如果不重写,则无法保证键的唯一性。
String 类重写hashCode()和equals()方法
注意:
重写hashCode()和equals()方法后,如果键相同,会发生值覆盖.
package org.westos.demo;
import java.util.Collection;
import java.util.HashMap;
import java.util.function.BiConsumer;
public class MyTest {
public static void main(String[] args) {
/* 存储键是String类型,值是Student类型, HashMap 键的数据结构是哈希表,键的唯一性靠重写
hashCode()和equals()方法才能保证,如果不重写,则无法保证键的唯一性。*/
HashMap<String, Student> hashMap = new HashMap<>();
//String默认重写了hashCode()和equals()方法
//键相同,会发送值覆盖
hashMap.put("aaa",new Student("李四",22));
hashMap.put("bbb",new Student("李四",22));
hashMap.put("aaa",new Student("李四",22));
hashMap.put("aaa",new Student("李四",22));
System.out.println(hashMap);
System.out.println("===========================");
HashMap<Student, String> hashMap2 = new HashMap<>();
/*
* 当Student没有重写hashCode()和equals()方法时,会存储重复元素,不能保证唯一性
* 重写后,如果键相同,会发生值覆盖
* */
hashMap2.put(new Student("李白",22),"aaa");
hashMap2.put(new Student("杜甫",33),"bbb");
hashMap2.put(new Student("苏轼",44),"aaa");
hashMap2.put(new Student("李白",22),"ccc");
System.out.println(hashMap2);
}
}
2.HashMap集合的功能
a:添加功能
V put(K key,V value):添加元素。这个其实还有另一个功能?替换
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
b:删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
c:判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
d:获取功能
Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合
e:长度功能
int size():返回集合中的键值对的对数
(1)添加功能
package org.westos.demo;
import java.util.HashMap;
public class MyTest2 {
public static void main(String[] args) {
/*
a:添加功能
V put(K key,V value):添加元素。这个其实还有另一个功能?替换
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值*/
HashMap<Student, String> hashMap = new HashMap<>();
String put = hashMap.put(new Student("李白", 100), "诗仙");
System.out.println(put);//null
String put1 = hashMap.put(new Student("杜甫", 200), "诗人");
System.out.println(put1);//null
String put2 = hashMap.put(new Student("杜甫", 200), "唐朝大诗人");
System.out.println(put2);//诗人
String put3 = hashMap.put(new Student("杜甫", 200), "石壕吏");
System.out.println(put3);//唐朝大诗人
System.out.println("--------------------------");
HashMap<String, Student> hm = new HashMap<>();
Student 李白 = hm.put("111", new Student("李白", 111));
System.out.println(李白);//null
Student 杜甫 = hm.put("222", new Student("杜甫", 222));
System.out.println(杜甫);//null
Student 王五 = hm.put("333", new Student("王五", 333));
System.out.println(王五);//null
Student 马飞 = hm.put("111", new Student("马飞", 999));
System.out.println(马飞);//Student{name='李白', age=111}
System.out.println(hm);//{111=Student{name='马飞', age=999}, 222=Student{name='杜甫', age=222},
// 333=Student{name='王五', age=333}}
}
}
(2)删除功能
package org.westos.demo;
import java.util.HashMap;
public class MyTest3 {
public static void main(String[] args) {
HashMap<String, Student> hm = new HashMap<>();
hm.put("aaa",new Student("张三",22));
hm.put("bbb",new Student("李四",24));
hm.put("ccc",new Student("王五",26));
hm.put("aaa",new Student("张三",29));
System.out.println(hm);
System.out.println("=====================");
/* b:删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回*/
//根据键来删除一对键值对 返回的是这个键所对应的的值
Student ccc = hm.remove("ccc");
System.out.println(ccc);
System.out.println(hm);
hm.clear();
System.out.println(hm);
System.out.println("==================================================");
HashMap<Student, String> hm2 = new HashMap<>();
hm2.put(new Student("张三",23),"111");
hm2.put(new Student("李四",33),"222");
hm2.put(new Student("王五",43),"444");
hm2.put(new Student("张三",23),"999");
System.out.println(hm2);
String 李四 = hm2.remove(new Student("李四", 33));
System.out.println(李四);
String 王五 = hm2.remove(new Student("王五", 43));
System.out.println(王五);
System.out.println(hm2);
hm2.clear();
System.out.println(hm2);
}
}
(3)判断功能
package org.westos.demo;
import java.util.HashMap;
public class MyTest4 {
public static void main(String[] args) {
/*c:判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空*/
HashMap<String, Student> hm = new HashMap<>();
hm.put("aaa",new Student("张三",22));
hm.put("bbb",new Student("李四",24));
hm.put("ccc",new Student("王五",26));
hm.put("aaa",new Student("张三",29));
boolean aaa = hm.containsKey("aaa");
System.out.println(aaa);//true
boolean 王五 = hm.containsValue(new Student("王五", 26));
System.out.println(王五);//true
boolean 张三 = hm.containsValue(new Student("张三", 22));
System.out.println(张三);//false
boolean empty = hm.isEmpty();
System.out.println(empty);//false
System.out.println("=======================");
HashMap<Student, String> hm2 = new HashMap<>();
hm2.put(new Student("张三",23),"111");
hm2.put(new Student("李四",33),"222");
hm2.put(new Student("王五",43),"444");
hm2.put(new Student("张三",23),"999");
System.out.println(hm2);
boolean 张三2 = hm2.containsKey(new Student("张三", 23));
System.out.println(张三2);//true
boolean b = hm2.containsValue("444");
System.out.println(b);//true
boolean b1 = hm2.containsValue("111");
System.out.println(b1);//false
boolean empty1 = hm2.isEmpty();
System.out.println(empty1);//false
}
}
(4)获取功能
package org.westos.demo;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MyTest5 {
public static void main(String[] args) {
/*d:获取功能
Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合
*/
HashMap<String, Student> hm = new HashMap<>();
hm.put("aaa",new Student("张三",22));
hm.put("bbb",new Student("李四",24));
hm.put("ccc",new Student("王五",26));
hm.put("aaa",new Student("张三",29));
Student ccc = hm.get("ccc");
System.out.println(ccc);
Set<String> strings = hm.keySet();
for (String string : strings) {
System.out.println(string);
}
System.out.println("==========");
Set<Map.Entry<String, Student>> entries = hm.entrySet();
Collection<Student> values = hm.values();
for (Student value : values) {
System.out.println(value);
}
//获取集合中键值对的对数
int size = hm.size();
System.out.println(size);
}
}
3.HashMap集合的遍历
A:键找值:
获取所有键的集合
遍历键的集合,获取到每一个键
根据键找值
B:键值对对象找键和值思路:
获取所有键值对对象的集合
遍历键值对对象的集合,获取到每一个键值对对象
根据键值对对象找键和值
C:
JDK1.8 提供的遍历方式forEach()方法
package org.westos.demo;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class MyTest6 {
public static void main(String[] args) {
//HashMap集合的遍历
//遍历方式1:通过键找值的方式来遍历
HashMap<String, Student> hm = new HashMap<>();
hm.put("aaa",new Student("张三",22));
hm.put("bbb",new Student("李四",24));
hm.put("ccc",new Student("王五",26));
hm.put("aaa",new Student("张三",29));
Set<String> strings = hm.keySet();//获取所有的键的集合
System.out.println(strings);
for (String key : strings) {
Student value=hm.get(key);
System.out.println(key+"===="+value);
}
System.out.println("=======================");
//遍历方式2:键值对对象找键和值,
// Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
Set<Map.Entry<String, Student>> entries = hm.entrySet();
for (Map.Entry<String, Student> entry : entries) {
String key = entry.getKey();
Student value = entry.getValue();
System.out.println(key+"===="+value);
}
System.out.println("=======================");
//遍历方式三:采用jdk1.8之后的forEach(方法)
hm.forEach(new BiConsumer<String, Student>() {
@Override
public void accept(String key, Student value) {
System.out.println(key+"===="+value);
}
});
}
}
4.LinkedHashMap
A:LinkedHashMap的概述: Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序
B:LinkedHashMap的特点: 底层的数据结构是链表和哈希表 元素有序 并且唯一
元素的有序性由链表数据结构保证 唯一性由 哈希表数据结构保证
Map集合的数据结构只和键有关
HashMap 键的数据结构是哈希表 保证键唯一,键无序
LinkedHashMap 键的数据结构链表和哈希表。链表保证了键有序,哈希表保证了键唯一。
package org.westos.demo2;
import java.util.LinkedHashMap;
public class myTest {
public static void main(String[] args) {
//LinkedHashMap底层是哈希表和链表,保证元素的有序性和唯一性
LinkedHashMap<String, Integer> lh = new LinkedHashMap<>();
Integer aaa = lh.put("aaa", 111);
System.out.println(aaa);//null
Integer bbb = lh.put("bbb", 222);
System.out.println(bbb);//null
Integer ccc = lh.put("ccc", 333);
System.out.println(ccc);//null
lh.put("ccc",999);
System.out.println(lh);
}
}
5.TreeMap
TreeMap 键允许插入空值
不允许插入null键,会抛 NullPointerException 异常;
这样的话,程序健壮性不强,可以在排序时对其进行优化
1.当未实现 Comparator 接口时,key 不可以为null,
否则抛 NullPointerException 异常;
2.当实现 Comparator 接口时,若未对 null 情况进行判断,则可能抛
NullPointerException 异常。如果针对null情况实现了,
可以存入,但是却不能正常使用get()访问,只能通过遍历去访问。
A: TreeMap: 键的数据结构是红黑树,可保证键的排序和唯一性
排序分为自然排序和比较器排序
线程是不安全的效率比较高
排序:
package org.westos.demo2;
import java.util.TreeMap;
public class MyTest2 {
public static void main(String[] args) {
TreeMap<String, Student> treeMap = new TreeMap<>();
//treeMap不允许存储null键
treeMap.put("111",new Student("aaa",111));
treeMap.put("222",new Student("bbb",222));
treeMap.put("333",new Student("ccc",333));
//treeMap允许存储null值
treeMap.put("444",new Student(null,0));
System.out.println(treeMap);
//NullPointerException异常,这样的话,程序健壮性不强,可以在比较器排序时对其进行优化
/*
treeMap.put(null,new Student("连",22));
System.out.println(treeMap);
*/
}
}
package org.westos.demo2;
import java.util.Comparator;
import java.util.TreeMap;
public class MyTest3 {
public static void main(String[] args) {
//1.自然排序,String类默认实现了Comparable接口,重写了compareTo方法
// 仍然无法插入空键,程序报NullPointerException异常
TreeMap<String, Student> treeMap = new TreeMap<>();
treeMap.put("111",new Student("aaa",111));
treeMap.put("222",new Student("bbb",222));
treeMap.put("333",new Student("ccc",333));
// treeMap.put(null,new Student("连",22));
System.out.println(treeMap);
//2.比较器排序
TreeMap<String, Student> treeMap2 = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String a, String b) {
Integer i = Integer.valueOf(a);
Integer j = Integer.valueOf(b);
return i-j;
}
});
treeMap2.put("111",new Student("aaa",111));
treeMap2.put("333",new Student("ccc",333));
treeMap2.put("222",new Student("bbb",222));
System.out.println(treeMap2);
}
}
package org.westos.demo2;
import java.util.Comparator;
import java.util.TreeMap;
public class MyTest4 {
public static void main(String[] args) {
//自然排序,需要键对应的类型实现Comparable接口,重写compareTo方法
TreeMap<Student, Integer> treeMap = new TreeMap<>();
treeMap.put(new Student("李白",22222),100);
treeMap.put(new Student("成绩思涵",24),200);
treeMap.put(new Student("武则天aaaaaaa",126),300);
treeMap.put(new Student("疾风剑豪",28),400);
System.out.println(treeMap);
//比较器排序
TreeMap<Integer, String> treeMap2 = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
treeMap2.put(100,"aaa");
treeMap2.put(10,"bbb");
treeMap2.put(30,"a");
treeMap2.put(1,"mama");
System.out.println(treeMap2);
System.out.println("==================================");
TreeMap<Student, Integer> treeMap3 = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student a, Student b) {
//根据年龄进行比较
int num=a.getAge()-b.getAge();
int num2=num==0?a.getName().compareTo(b.getName()):num;
return num2;
//根据姓名进行比较
/*int num=a.getName().length()-b.getName().length();
int num2=num==0?a.getName().compareTo(b.getName()):num;
int num3=num2==0?a.getAge()-b.getAge():num2;
return num3;*/
}
});
treeMap3.put(new Student("压缩",22),100);
treeMap3.put(new Student("疾风剑豪",32),200);
treeMap3.put(new Student("武则天aaaaaa",2),900);
treeMap3.put(new Student("从",2),400);
treeMap3.put(new Student("难道",2992),500);
System.out.println(treeMap3);
}
}
---------------------------------------------------------
package org.westos.demo2;
import java.util.Objects;
public class Student implements Comparable<Student>{
private String name;
private int 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);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public int compareTo(Student s) {
//根据年龄进行排序
/*int num=this.age-s.age;
//如果年龄相同,不能认为是同一个对象,再去比较姓名
int num2=num==0?this.name.compareTo(s.name):num;
return num2;*/
/*根据姓名排序
* */
int num=this.name.length()-s.name.length();
int num2=num==0?this.name.compareTo(s.name):num;
int num3=num2==0?this.age-s.age:num2;
return num3;
}
}
6.HashTable
HashMap 允许存储null值和null键 线程不安全 但是效率高
Hashtable 不允许存储null值和null键 线程安全 效率低
package org.westos.demo3;
import java.util.Hashtable;
public class MyTest {
public static void main(String[] args) {
Hashtable<String, Integer> hashtable = new Hashtable<>();
hashtable.put("aaa",100);
hashtable.put("bbb",200);
hashtable.put("ccc",300);
//报错,Hashtable不允许存null键和值
hashtable.put(null,100);
}
}
7.案例
1. 需求:随机输入一个字符串,统计字符串中每个字符出现的次数
如:"aababcabcdabcde", 获取字符串中每一个字母出现的次数要求结果:a(5) b(4) c(3) d(2) e(1)
package org.westos.demo4;
import java.util.*;
public class MyTest {
public static void main(String[] args) {
//随机输入一个字符串,统计字符串中每个字符出现的次数
//如:"aababcabcdabcde", 获取字符串中每一个字母出现的次数要求结果:a(5) b(4) c(3) d(2) e(1)
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String s = sc.nextLine();
//定义hashmap存储字符和出现次数
HashMap<Character, Integer> hashMap = new HashMap<>();
Character c=' ';
for (int i = 0; i < s.length(); i++) {
c = s.charAt(i);
if (!hashMap.containsKey(c)){
//不包含字符,就将该字符当作键,值为1存储;
hashMap.put(c,1);
}
if (hashMap.containsKey(c)){
hashMap.put(c,hashMap.get(c)+1);
}
}
System.out.println(hashMap);
}
}
2.集合嵌套之HashMap嵌套HashMap
基础班
张三 20
李四 22
就业班
王五 21
赵六 23
package org.westos.demo5;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class MyTest {
public static void main(String[] args) {
/* 集合嵌套之HashMap嵌套HashMap
基础班
张三 20
李四 22
就业班
王五 21
赵六 23*/
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("张三",20);
hashMap.put("李四",22);
HashMap<String, Integer> hashMap1 = new HashMap<>();
hashMap1.put("王五",21);
hashMap1.put("赵六",23);
HashMap<String, HashMap<String, Integer>> hashMap2 = new HashMap<>();
hashMap2.put("基础班",hashMap);
hashMap2.put("就业班",hashMap1);
System.out.println(hashMap2);
Set<Map.Entry<String, HashMap<String, Integer>>> entries = hashMap2.entrySet();
for (Map.Entry<String, HashMap<String, Integer>> entry : entries) {
String key = entry.getKey();
System.out.println(key);
HashMap<String, Integer> value = entry.getValue();
Set<Map.Entry<String, Integer>> entries1 = value.entrySet();
for (Map.Entry<String, Integer> stringIntegerEntry : entries1) {
String key1 = stringIntegerEntry.getKey();
Integer value1 = stringIntegerEntry.getValue();
System.out.println("\t"+key1+"\t"+value1);
}
System.out.println();
}
}
}
3.集合嵌套之HashMap嵌套ArrayList
三国演义
吕布
周瑜
笑傲江湖
令狐冲
林平之
神雕侠侣
郭靖
杨过
package org.westos.demo6;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MyTest {
public static void main(String[] args) {
/*
* 三国演义
吕布
周瑜
笑傲江湖
令狐冲
林平之
神雕侠侣
郭靖
杨过 */
ArrayList<String> strings = new ArrayList<>();
strings.add("吕布");
strings.add("周瑜");
ArrayList<String> strings2 = new ArrayList<>();
strings2.add("令狐冲");
strings2.add("林平之");
ArrayList<String> strings3 = new ArrayList<>();
strings3.add("郭靖");
strings3.add("杨过");
HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
hashMap.put("三国演义",strings);
hashMap.put("笑傲江湖",strings2);
hashMap.put("神雕侠侣",strings3);
//遍历hashmap
Set<Map.Entry<String, ArrayList<String>>> entries = hashMap.entrySet();
for (Map.Entry<String, ArrayList<String>> entry : entries) {
String key = entry.getKey();
System.out.println(key);
ArrayList<String> value = entry.getValue();
for (String s : value) {
System.out.println("\t"+s);
}
System.out.println();
}
}
}
4.集合嵌套之ArrayList嵌套HashMap
假设ArrayList集合的元素是HashMap。有3个。
每一个HashMap集合的键和值都是字符串。
周瑜---小乔
吕布---貂蝉
郭靖---黄蓉
杨过---小龙女
令狐冲---任盈盈
林平之---岳灵珊
package org.westos.demo6;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MyTest2 {
public static void main(String[] args) {
/*集合嵌套之ArrayList嵌套HashMap
假设ArrayList集合的元素是HashMap。有3个。
每一个HashMap集合的键和值都是字符串。
周瑜---小乔
吕布---貂蝉
郭靖---黄蓉
杨过---小龙女
令狐冲---任盈盈
林平之---岳灵珊*/
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("周瑜","小乔");
hashMap.put("吕布","貂蝉");
HashMap<String, String> hashMap2 = new HashMap<>();
hashMap2.put("郭靖","黄蓉");
hashMap.put("杨过","小龙女");
HashMap<String, String> hashMap3 = new HashMap<>();
hashMap.put("令狐冲","任盈盈");
hashMap.put("林平之","岳灵珊");
ArrayList<HashMap<String, String>> arrayList = new ArrayList<>();
arrayList.add(hashMap);
arrayList.add(hashMap2);
arrayList.add(hashMap3);
for (HashMap<String, String> stringStringHashMap : arrayList) {
Set<Map.Entry<String, String>> entries = stringStringHashMap.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("\t"+key+"==="+"\t"+value);
}
System.out.println();
}
}
}
8.Collections工具类
A:
它是集合的工具类,所有的方法都是静态方法,可以直接类名调方法
B:
常见方法:
public static < T > void sort(List< T > list):按照自然顺序排序集合
public static < T> int binarySearch(List< ? > list,T key):二分法查找。
public static < T > T max(Collection< ? > coll):获取集合中的最大值
public static void reverse(List< ? > list):反转集合
public static void shuffle(List< ? > list):随机打乱集合
斗地主案例
package org.westos.demo8;
import java.util.ArrayList;
import java.util.Collections;
public class MyTest {
public static void main(String[] args) {
//斗地主案例
//先创建两个可以组成52张牌的集合
String []shape={"♠","♥","♦","♣"};
String [] num={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
//建立集合存储牌
ArrayList<String> list = new ArrayList<>();
//将牌放进list集合
for (String s1 : num) {
for (String s2 : shape) {
String s = s1.concat(s2);
list.add(s);
}
}
list.add("☀");//大王
list.add("☼");//小王
//洗牌
Collections.shuffle(list);
Collections.shuffle(list);
Collections.shuffle(list);
//需要三个玩家参与斗地主,还得留三张底牌
ArrayList<String> palyer1 = new ArrayList<>();
ArrayList<String> palyer2 = new ArrayList<>();
ArrayList<String> palyer3 = new ArrayList<>();
ArrayList<String> diPai = new ArrayList<>();
//发牌方式1: 一人数个10来张发给你
//palyer1 = (ArrayList<String>) list.subList(0, 11);
// 方式2:传统发牌 一人一张转着发
//用牌的索引对3取余
/* 玩家1 0 3 6 9 余数 0
玩家2 1 4 7 10 余数 1
玩家3 2 5 8 11 余数 2 */
for (int i = 0; i < list.size(); i++) {
if (i>=list.size()-3){
diPai.add(list.get(i));
}else if (i%3==0){
palyer1.add(list.get(i));
}else if (i%3==1){
palyer2.add(list.get(i));
}else if (i%3==2){
palyer3.add(list.get(i));
}
}
//做一个斗地主排序版,牌发好之后,从小到大排好
Collections.sort(palyer1);
Collections.sort(palyer2);
Collections.sort(palyer3);
//看牌
see("卢本伟",palyer1);
see("马飞飞",palyer2);
see("阿姨",palyer3);
}
public static void see(String name, ArrayList<String> list){
for (String poker : list) {
System.out.print(poker+"\t");
}
System.out.println();
}
}
斗地主有序版
package org.westos.demo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
public class MyTest {
public static void main(String[] args) {
//创建一个hashmap,键为索引,值为牌,用来存储牌
HashMap<Integer, String> hm = new HashMap<>();
String []shape={"♠","♥","♦","♣"};
String [] num={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
//创建一个单列集合,存放牌的索引
ArrayList<Integer> list = new ArrayList<>();
int index = 0;
//往牌盒里存储牌
//注意外层num,内存shape
for (String str : num) {
for (String s : shape) {
hm.put(index,s.concat(str));
//把索引放在索引集合中
list.add(index);
index++;
}
}
System.out.println(index);
//手动添加大小王
hm.put(index,"●");
list.add(index);
index++;
hm.put(index, "○");
list.add(index);
//洗牌,洗的是索引集合
Collections.shuffle(list);
//发牌,要有序,用TreeSet集合
TreeSet<Integer> 卢本伟 = new TreeSet<>();
TreeSet<Integer> 马飞飞 = new TreeSet<>();
TreeSet<Integer> 卡布奇诺阿姨 = new TreeSet<>();
TreeSet<Integer> 底牌 = new TreeSet<>();
for (int i = 0; i < list.size(); i++) {
//留底牌
if (i >= list.size() - 3) {
底牌.add(list.get(i));
} else if (i % 3 == 0) {
卢本伟.add(list.get(i));
} else if (i % 3 == 1) {
马飞飞.add(list.get(i));
} else {
卡布奇诺阿姨.add(list.get(i));
}
}
//看牌
look("卢本伟",卢本伟,hm);
look("马飞飞",马飞飞,hm);
look("卡布奇诺阿姨",卡布奇诺阿姨,hm);
look("底牌",底牌,hm);
}
private static void look(String name,TreeSet<Integer> treeSet,HashMap<Integer, String> hm){
System.out.println(name);
for (Integer key : treeSet) {
String value = hm.get(key);
System.out.print(value+"\t");
}
System.out.println();
}
}