集合框架
1.Collection集合
A.数组(存放任意类型,长度固定)
B.集合(存放对象类型,长度可变)
单列集合 Collection
List (ArrayList、LinkedList、Vector)
Set (HashSet、LinkedHashSet、TreeSet)
•public boolean add(E e): 把给定的对象添加到当前集合中 。
•public void clear() :清空集合中所有的元素。
•public boolean remove(E e): 把给定的对象在当前集合中删除。
•public boolean contains(E e): 判断当前集合中是否包含给定的对象。
•public boolean isEmpty(): 判断当前集合是否为空。
•public int size(): 返回集合中元素的个数。
•public Object[] toArray(): 把集合中的元素,存储到数组中。
//创建集合使用多态
Collection<String> coll = new ArrayList<>();
//添加元素add
boolean b = coll.add("李四");
coll.add("张三");
coll.add("张三");
coll.add("王五");
System.out.println(b);//true
System.out.println(coll);//[李四, 张三, 张三, 王五]
//删除元素remove(E e)
coll.remove("张三");
System.out.println(coll);//[李四, 张三, 王五]
//判断当前集合中是否包含给定的对象 contains(E e)
boolean c = coll.contains("张三");
System.out.println(c);//true
//判断当前集合是否为空 isEmpty
System.out.println(coll.isEmpty());//false
//返回集合中元素的个数size
System.out.println(coll.size());//3
// 把集合中的元素,存储到数组中。toArray():
Object[] array = coll.toArray();
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");//李四 张三 王五
}
//清空集合中所有的元素。clear() :
coll.clear();
System.out.println(coll);//[]
2.集合遍历的迭代器
Iterator接口的常用方法如下:
public E next():返回迭代的下一个元素。
public boolean hasNext():如果仍有元素可以迭代,则返回 true。
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Iterator it = c.iterator(); //获取迭代器的引用
while(it.hasNext()) { //集合中的迭代方法(遍历)
System.out.println(it.next());
}
/*Iterator it = list.iterator();
while(it.hasNext()) {
String str = (String)it.next();
if(str.equals("world")) {
list.add("javaee"); //这里会抛出ConcurrentModificationException并发修改异常
}
}*/
3.List
增加:public void add(int index, E element)
查询:public E get(int index)
删除:public E remove(int index)
修改:public E set(int index, E element)
java.util.ArrayList
集合数据存储的结构是数组结构。元素增删慢,查找快
java.util.LinkedList
集合数据存储的结构是链表结构。方便元素添加、删除的集合。
for循环遍历只支持list集合,set集合不可以,因为set集合无索引
4.linkedList集合
LinkedList集合的特点:
1.底层是一个链表结构:查询慢,增删快
2.里面包含了大量操作首尾元素的方法
3.使用LinkedList集合特有的方法,不能使用多态
- public void addFirst(E e):将指定元素插入此列表的开头。
- public void addLast(E e):将指定元素添加到此列表的结尾。
- public void push(E e):将元素推入此列表所表示的堆栈。
- public E getFirst():返回此列表的第一个元素。
- public E getLast():返回此列表的最后一个元素。
- public E removeFirst():移除并返回此列表的第一个元素。
- public E removeLast():移除并返回此列表的最后一个元素。
- public E pop():从此列表所表示的堆栈处弹出一个元素。
- public boolean isEmpty():如果列表不包含元素,则返回true。
public static void main(String[] args) {
show01();
show02();
show03();
}
private static void show03() {
LinkedList<String> linked = new LinkedList<>();
//添加add
linked.add("abc");
linked.add("abc");
linked.add("www");
System.out.println(linked);//[abc, abc, www]
//移除第一个元素 removeFirst pop
String s = linked.removeFirst();
System.out.println("移除第一个元素"+s);//移除第一个元素abc
//移除最后一个元素
String s2 = linked.removeLast();
System.out.println("移除第一个元素"+s2);//移除第一个元素www
System.out.println(linked);//[abc]
}
private static void show02() {
LinkedList<String> linked = new LinkedList<>();
//添加add
linked.add("abc");
linked.add("abc");
linked.add("www");
System.out.println(linked);//[abc, abc, www]
//linked.clear();//清空 报错 NoSuchElementException
if (!linked.isEmpty()) {//判断是否为空
//获取第一个元素
String first = linked.getFirst();
System.out.println(first);//abc
//获取最后一个元素
String last = linked.getLast();
System.out.println(last);//www
}
}
private static void show01() {
LinkedList<String> linked = new LinkedList<>();
//添加add
linked.add("abc");
linked.add("abc");
linked.add("abc");
System.out.println(linked);//[abc, abc, abc]
//头添加元素addFirst(E e) push()
linked.addFirst("www");
System.out.println(linked);//[www, abc, abc, abc]
linked.push("aaa");
System.out.println(linked);//[aaa, www, abc, abc, abc]
//尾部添加addLast()
linked.addLast("com");
System.out.println(linked);//[aaa, www, abc, abc, abc, com]
}
5.ListIterator
如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
- boolean hasNext()是否有下一个
- boolean hasPrevious()是否有前一个
- Object next()返回下一个元素
- Object previous();返回上一个元素
ListIterator lit = list.listIterator();
while(lit.hasNext()) {
String str = (String)lit.next();
if(str.equals("world")) {
lit.add("javaee");
//list.add("javaee");
}
}
6.Vector
Vector v = new Vector(); //创建集合对象,List的子类
v.addElement("a");
v.addElement("b");
v.addElement("c");
v.addElement("d");
//Vector迭代
Enumeration en = v.elements(); //获取枚举
while (en.hasMoreElements()) { //判断集合中是否有元素
System.out.println(en.nextElement());//获取集合中的元素
}
7.List的三个子类的特点
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
Vector和ArrayList的区别
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
ArrayList和LinkedList的区别
ArrayList底层是数组结果,查询和修改快
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
B:List有三个儿子,我们到底使用谁呢?
查询多用ArrayList
增删多用LinkedList
如果都多ArrayList
8.ArrayList去重复
public static ArrayList getSingle(ArrayList list) {
ArrayList newList = new ArrayList(); //创建一个新集合
Iterator it = list.iterator(); //获取迭代器
while(it.hasNext()) { //判断老集合中是否有元素
String temp = (String)it.next(); //将每一个元素临时记录住
if(!newList.contains(temp)) { //如果新集合中不包含该元素
newList.add(temp); //将该元素添加到新集合中
}
}
return newList; //将新集合返回
}
9.泛型
1.定义和使用含有泛型的类
public class GenericClass<E> {
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
GenericClass gc = new GenericClass();
gc.setName("张三");
Object name = gc.getName();
System.out.println(name);//张三
//泛型使用Integer
GenericClass<Integer> gc2 = new GenericClass<>();
gc2.setName(100);
Integer name2 = gc2.getName();
System.out.println(name2);//100
//泛型使用String
GenericClass<String> gc3 = new GenericClass<>();
gc3.setName("李四");
String name3 = gc3.getName();
System.out.println(name3);//李四
2.含有泛型的方法
public class GenericMethod {
//定义一个含有泛型的方法
public <M> void method(M m){
System.out.println(m);
}
//定义一个含有泛型的静态方法
public static <S> void method2(S s){
System.out.println(s);
}
}
GenericMethod gm = new GenericMethod();
gm.method(123);//123
gm.method("abc");//abc
gm.method(true);//true
gm.method('a');//a
gm.method2("静态方法");//静态方法
GenericMethod.method2("abc");//abc
GenericMethod.method2(123);//123
3.含有泛型的接口
public interface GenericInterface<I> {
public abstract void method(I i);
}
//类不是泛型
public class InterfaceClass implements GenericInterface<String> {
@Override
public void method(String s) {
System.out.println(s);
}
}
//类是泛型
public class InterfaceClass2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
InterfaceClass ic = new InterfaceClass();
ic.method("字符串");//字符串
InterfaceClass2<Integer> ic2 = new InterfaceClass2<>();
ic2.method(10);//10
InterfaceClass2<String> ic3 = new InterfaceClass2<>();
ic3.method("abc");//abc
4.泛型通配符
ArrayList<String> list = new ArrayList<>();
list.add("efg");
list.add("abc");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(123);
list2.add(456);
printArray(list);
printArray(list2);
}
public static void printArray(ArrayList<?> list) {
Iterator<?> it = list.iterator();
while (it.hasNext()) {
Object obj = it.next();
System.out.println(obj);//efg abc 123 456
}
}
泛型的上限:
格式: 类型名称 <? extends 类 > 对象名称
意义: 只能接收该类型及其子类
泛型的下限:
格式: 类型名称 <? super 类 > 对象名称
意义: 只能接收该类型及其父类型
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
getElement1(list1);
//getElement1(list2);//报错
getElement1(list3);
//getElement1(list4);//报错
//getElement2(list1);//报错
//getElement2(list2);//报错
getElement2(list3);
getElement2(list4);
}
/*
类与类之间的继承关系
Integer extends Number extends Object
String extends Object
*/
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}
}
10.HashSet
存储自定义对象保证元素唯一性(去重复)
1.HashSet原理
- 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
- 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
- 如果没有哈希值相同的对象就直接存入集合
- 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
2.将自定义类的对象存入HashSet去重复
- 类中必须重写hashCode()和equals()方法
- hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
- equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储
11.LinkedHashSet
可以保证怎么存就怎么取 产生10个1-20的随机不重复
HashSet<Integer> hs = new HashSet<>(); //创建集合对象
Random r = new Random(); //创建随机数对象
while(hs.size() < 10) {
int num = r.nextInt(20) + 1; //生成1到20的随机数
hs.add(num);
}
for (Integer integer : hs) { //遍历集合
System.out.println(integer); //打印每一个元素
}
//去重复
public static void getSingle(List<String> list) {
LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.addAll(list); //将list集合中的所有元素添加到lhs
list.clear(); //清空原集合
list.addAll(lhs); //将去除重复的元素添回到list中
}
12.TreeSet
- 1.特点
- TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
- 2.使用方式
- a.自然顺序(Comparable)
- TreeSet类的add()方法中会把存入的对象提升为Comparable类型
- 调用对象的compareTo()方法和集合中的对象比较
- 根据compareTo()方法返回的结果进行存储
- b.比较器顺序(Comparator)
- 创建TreeSet的时候可以制定 一个Comparator
- 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
- add()方法内部会自动调用Comparator接口中compare()方法排序
- c.两种方式的区别
- TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
- TreeSet如果传入Comparator, 就优先按照Comparator
- a.自然顺序(Comparable)
//对集合中的元素排序,并保留重复
public static void sort(List<String> list) {
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() { //定义比较器(new Comparator(){}是Comparator的子类对象)
@Override
public int compare(String s1, String s2) { //重写compare方法
int num = s1.compareTo(s2); //比较内容
return num == 0 ? 1 : num; //如果内容一样返回一个不为0的数字即可
}
});
ts.addAll(list); //将list集合中的所有元素添加到ts中
list.clear(); //清空list
list.addAll(ts);
}
//从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); //创建键盘录入对象
System.out.println("请输入一行字符串:");
String line = sc.nextLine(); //将键盘录入的字符串存储在line中
char[] arr = line.toCharArray(); //将字符串转换成字符数组
TreeSet<Character> ts = new TreeSet<>(new Comparator<Character>() {
@Override
public int compare(Character c1, Character c2) {
//int num = c1.compareTo(c2);
int num = c1 - c2; //自动拆箱
return num == 0 ? 1 : num;
}
});
for(char c : arr) {
ts.add(c);
}
for(Character ch : ts) {
System.out.print(ch);
}
}
13.Collections
- java.utils.Collections是集合工具类,用来对集合进行操作。部分方法如下:
- public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
- public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
- public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
- public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。
Comparable:强行对实现它的每个类的对象进行整体排序。
Comparator:强行对某个对象进行整体排序
public static void sort(List list,Comparator<? super T> ):将集合中元素按照指定规则排序。
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("a张三",20));
list.add(new Person("c李四",20));
list.add(new Person("b王五",20));
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
// 年龄降序
int result = o2.getAge()-o1.getAge();//年龄降序
if(result==0) {//第一个规则判断完了 下一个规则 姓名的首字母 升序
result = o1.getName().charAt(0) - o2.getName().charAt(0);
}
return result;
}
});
System.out.println(list);
//[Person{name='a张三', age=20}, Person{name='b王五', age=20}, Person{name='c李四', age=20}]
模拟斗地主的洗牌和发牌
String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] color = {"方片","梅花","红桃","黑桃"};
ArrayList<String> poker = new ArrayList<>();
for(String s1 : color) {
for(String s2 : num) {
poker.add(s1.concat(s2));
}
}
poker.add("小王");
poker.add("大王");
//洗牌
Collections.shuffle(poker);
//发牌
ArrayList<String> gaojin = new ArrayList<>();
ArrayList<String> longwu = new ArrayList<>();
ArrayList<String> me = new ArrayList<>();
ArrayList<String> dipai = new ArrayList<>();
for(int i = 0; i < poker.size(); i++) {
if(i >= poker.size() - 3) {
dipai.add(poker.get(i));
}else if(i % 3 == 0) {
gaojin.add(poker.get(i));
}else if(i % 3 == 1) {
longwu.add(poker.get(i));
}else {
me.add(poker.get(i));
}
}
//看牌
System.out.println(gaojin);
System.out.println(longwu);
System.out.println(me);
System.out.println(dipai);
13.Map
A:Map接口概述
- 查看API可以知道:
- 将键映射到值的对象
- 一个映射不能包含重复的键
- 每个键最多只能映射到一个值
B:Map接口和Collection接口的不同
- Map是双列的,Collection是单列的
- Map的键唯一,Collection的子体系Set是唯一的
- Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
14.Map集合的功能概述
1:添加功能
- V put(K key,V value):添加元素。
- 如果键是第一次存储,就直接存储元素,返回null
- 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
2:删除功能
- void clear():移除所有的键值对元素
- V remove(Object key):根据键删除键值对元素,并把值返回
3:判断功能
- boolean containsKey(Object key):判断集合是否包含指定的键
- boolean containsValue(Object value):判断集合是否包含指定的值
- boolean isEmpty():判断集合是否为空
4:获取功能
- Set<Map.Entry<K,V>> entrySet():???
- V get(Object key):根据键获取值
- Set keySet():获取集合中所有键的集合
- Collection values():获取集合中所有值的集合
5:长度功能
- int size():返回集合中的键值对的个数
15.Map的两种循环方式
//keySet
Set<String> keySet = hm.keySet(); //获取集合中所有的键
Iterator<String> it = keySet.iterator(); //获取迭代器
while(it.hasNext()) { //判断单列集合中是否有元素
String key = it.next(); //获取集合中的每一个元素,其实就是双列集合中的键
Integer value = hm.get(key); //根据键获取值
System.out.println(key + "=" + value); //打印键值对
}
//增强for
for(String key : hm.keySet()) { //增强for循环迭代双列集合第一种方式
System.out.println(key + "=" + hm.get(key));
}
//entrySet
Set<Map.Entry<String, Integer>> entrySet = hm.entrySet(); //获取所有的键值对象的集合
Iterator<Entry<String, Integer>> it = entrySet.iterator();//获取迭代器
while(it.hasNext()) {
Entry<String, Integer> en = it.next(); //获取键值对对象
String key = en.getKey(); //根据键值对对象获取键
Integer value = en.getValue(); //根据键值对对象获取值
System.out.println(key + "=" + value);
}
//增强for
for(Entry<String,Integer> en : hm.entrySet()) {
System.out.println(en.getKey() + "=" + en.getValue());
}
16.HashMap
当给 HashMap 中存放自定义对象时,如果自定义对象作为key存在,
这时要保证对象唯一,必须复写对象的 hashCode 和 equals 方法
统计每个字符出现的个数
String str = "aaaabbbcccccccccc";
char[] arr = str.toCharArray(); //将字符串转换成字符数组
HashMap<Character, Integer> hm = new HashMap<>(); //创建双列集合存储键和值
for(char c : arr) { //遍历字符数组
if(!hm.containsKey(c)) { //如果不包含这个键
hm.put(c, 1); //就将键和值为1添加
}else { //如果包含这个键
hm.put(c, hm.get(c) + 1); //就将键和值再加1添加进来
}
//hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
Integer i = !hm.containsKey(c) ? hm.put(c, 1) : hm.put(c, hm.get(c) + 1);
}
for (Character key : hm.keySet()) { //遍历双列集合
System.out.println(key + "=" + hm.get(key));
}
17.LinkedHashMap
有序集合、顺序打印:
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("a","a");
map.put("b","b");
map.put("c","c");
map.put("a","d");
Set<Map.Entry<String, String>> set = map.entrySet();
for (Map.Entry<String, String> entry : set) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key +"= " + value);//a= d b= b c= c
}
}