Java_集合框架
集合框架
Collection(单列) :
List(有序可重复) :
ArrayList(常用) ---add / remove / contains / size
LinkedList(常用) ---getFirst() / getLast() / removeFirst() / addFirst() / ....
Vector
Stack
Set(无序不可重复) :
HashSet(常用)
TreeSet
Iterator : 迭代器 , 集合的专用遍历方法
Map(双列) :
HashMap(重点,面试高频问点)
JDK1.7:数组+链表 / JDK1.8:hash表=数组+链表+红黑树
TreeMap
Collections工具类
泛型 <> 约束 , 避免类型转换的问题
-----------------------------------------
Collection , Map , List , Set : 接口
ArrayList , LinkedList , HashSet , TreeSet , HashMap : 实现类
-----------------------------------------
1.Collection
Collection<String> c = new ArrayList<String>( );
Alt+7 : 打开一个窗口,可以看到类的所有信息
| 常用方法(添加删除同下) | 说明 |
|---|---|
| void clear() | 清空集合中的元素 |
| boolean isEmpty() | 判断集合是否为空 |
| boolean contains(Object o) | 判断集合中是否存在指定的元素 |
1.1 Iterator : 迭代器 -next()
iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到迭代器是通过集合 , iterator()方法得到的,所以我们说它是依赖于集合而存在的
| 常用方法 | 说明 |
|---|---|
| E next() | 返回迭代中的下一个元素 |
| boolean hasNext() | 如果迭代具有更多元素,则返回true |
Iterator<String> it = c.iterator(); //通过集合对象获取迭代器对象 while(it.hasNext()) { System.out.printLn(it.next()); String s = it.next(); System.out.println(s); }
并发修改异常
遍历 -- 添加
next() -- add()
预期修改值和实际修改值不一致的问题 , add()会导致实际修改值++ , 会导致数据不一致抛出异常
通过for循环遍历添加数据
ListIterator : 列表迭代器
用于允许程序员沿任一方向遍历列表的列表的迭代器
迭代期间允许修改列表,并获取列表中迭代器的当前位置
| 方法(next(),hasNext()方法相同) | |
|---|---|
| E previous() | 返回列表中的上一个元素 |
| boolean hasPrevious() | 如此迭代器在相反方向遍历列表时具有更多元素,则返回true |
| add(E e) | 将指定的元素插入列表 |
常见数据结构
栈 : 先进后出
队列 : 先进先出
数组 : 查询快 , 增删慢
链表 : 增删快 , 查询慢 (对比数组)
/----------------------/
哈希表 :
JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
JDK8以后,在长度比较长的时候,底层实现了优化
对哈希值 %16 取余 , 将相应数据存入余数对应的表(默认初始化表长16),如发现相同余数则对比哈希值不同且内容不同则以链表方法表示(先比余 , 再比哈希值 , 最后比内容)
2.List
List集合子类特点 :
ArrayList : 底层数据结构是数组,查询快 , 增删慢
LinkedList : 底层数据结构是链表, 查询慢 , 增删快
2.1ArrayList
| 构造添加方法 | 说明 |
|---|---|
| public ArrayList( ) | 创建一个空的集合对象 |
| 常用方法 | 说明(多数通用)... |
|---|---|
| public boolean add(E e) | 将指定的元素追加到此集合的末尾 |
| public void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
| public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 |
| public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
| public E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
| public E get(int index) | 返回指定索引处的元素 |
| public int size( ) | 返回集合中的元素的个数 |
2.2LinkedLIst
| 特有功能 | 说明 |
|---|---|
| public void addFirst(E e) | 在该列表开头插入指定的元素 |
| public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
| public E getFirst() | 返回此列表中的第一个元素 |
| public E getLast() | 返回此列表中的最后一个元素 |
| public E removeFirst() | 从此列表中删除并返回第一个元素 |
| public E removeLast() | 从此列表中删除并返回最后一个元素 |
3.Set
无序不可重复
不包含重复元素的集合
没有带索引的方法,所以不能使用普通for循环遍历,可以用增强for循环
Set<String> hs = new HashSet<String>();
哈希值 : 是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下 , 不同对象的哈希值不同--通过方法重写hashCode(),可以实现不同对象的哈希值是相同的
3.1HashSet
底层数据结构是哈希表
对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以是不包含重复元素的集合
使用Stu等对象时需要重写hashCode() , equals()方法
3.2LinkedHashSet
哈希表和链表实现的Set接口,具有可预测的迭代次序
由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
由哈希表保证元素唯一,也就是说没有重复的元素
3.3TreeSet
元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序
具体排序方式取决于构造方法 :
TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
没有带索引的方法,所以不能使用普通for循环遍历
由干是Set集合,所以不包含重复元素的集合
比较器需要让Stu类继承Comparator<Stu>并重写compareTo方法 , 如 :
public class Stu implements Comparable<Stu> { //自然排序 //..... @Override pubiic int compareTo(Stu s){ //s表示 /* 返回值为0,重复不存储 返回值为正数,正向输出 返回值为负数,降序输出 */ int num1 = this.age - s.age; //按年龄升序排列 int num2 = num1==0?this.name.compareTo(s.name):num;//年龄相同比姓名 return num2; } }
带参比较器需要可以采用内部匿名类 :
TreeSet<Stu> ts = new TreeSet<Stu>(new Comparator<Stu>() { @Override public int compare(student s1,student s2) { //this.age - s.age //s1,s2 int num1 = s1.getAge()-s2.getAge(); int num2 = num1==0?s1.getName().compareTo(s2.getName()):num; return num2; } });
4.泛型
public c1ass Generic<T> { //泛型类 public void show(T t) { System.out.println(t); } } public class Generic { //泛型方法 pubiic <T> void show(T t) { System.out.print1n(t); } } public interface Generic<T> { //泛型接口 void show(T t); } public class GenericImpl<T> implements Generic<T> { //泛型接口实现类 @Override public void show(T t)i System.out.println(t); } }
类型通配符
为了表示各种泛型List的父类,可以使用类型通配符
类型通配符:<?>
List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
类型通配符上限: <? extends类型>
List<? extends Number> :它表示的类型是Number或者其子类型
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
类型通配符下限:<? super类型>
List<? super Number>:它表示的类型是Number或者其父类型
List<? extends Number> list1 = new ArrayList<Number>(); //上限Number List<? super Number> list2 = new ArrayList<0bject>(); //下限Number
5.Map
lnterface Map<K,V> K:键的类型;V:值的类型
将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
Map<String,String> map = new HashMap<String,String>(); map.put("键","值"); //如果键值重复,后输入的值将替换之前的值
| 方法 | 说明 |
|---|---|
| V put(K key,V value) | 添加元素 |
| V remove(Object key) | 根据键删除键值对元素 |
| void clear() | 移除所有的键值对元素 |
| boolean containsKey(Object key) | 判断集合是否包含指定的键 |
| boolean containsValue(Object value) | 判断集合是否包含指定的值 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中键值对的个数 |
| 获取功能 | 说明 |
|---|---|
| V get(Object key) | 根据键获取值 |
| Set<K> keySet() | 获取所有键的集合 |
| Collection<V> values() | 获取所有值的集合 |
| Set<Map.Entry<K,V> > entrySet() | 获取所有键值对对象的集合 |
遍历思路 :
方法1 :
1.获取所有键的集合。用keySet(方法实现
2.遍历键的集合,获取到每一个键。用强for实现
3.根据键去找值。用get(Object key)方法实现
方法2 :
1.获取所有键值对对象的集合
Set<Map.Entry<K,V> > entrySet( ):获取所有键值对对象的集合
2.遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry
3.根据键值对对象获取键和值
用getKey()得到键 / 用getValue()得到值
Set<Map.Entry<String,String>> entrySet = map.entrySet(); //遍历键值对对象的集合,得到每一个键值对对象 for(Map.Entry<string,string> me : entrySet) { //根据键值对对象获取键和值 String key = me.getKey(); String value = me.getValue(); System.out.print1n(key + "," + value); }
5.1HashMap
如果有要求 : 要求保证键的唯一性 , 如果学生对象的成员变量值相同 , 我们就认为是同一个对象
因为使用哈希表 , 需要重写两个方法 : hashCode()和equals() 默认即可
集合嵌套
//ArrayList中嵌套HashMap ,且HashMap建字类型为String : ArrayList<HashMap<String,String>> array=new ArrayList<HashMap<String,Sstring>>(); HashMap<String,String> hm = new HashMap<String,string>(); hm.put("键","值"); //................. array.add(hm); //遍历ArrayList for(HashMap<String,String> hm : array) { set<String> keySet = hm.keySet( ); for(String key : keySet) { String value = hm.get(key); System.out.println(key+","+value); } }
//HashMap集合存储ArrayList元素并遍历 HashMap<String,ArrayList<String>> hm = new HashMap<String,ArrayList<String>>() ArrayList<String> array1 = new ArrayList<String>(); array1.add("String"); //................. hm.put("键",array1); //遍历HashMap set<String> keyset = hm.keySet(); for(String key : keySet) { System.out.println(key) ; ArrayList<String> value = hm.get(key); for(String s : value) { System.out.println("\t" + s); } }
5.2统计字符串字符个数 --案例
键是字符,类型应该是Character;值是字符出现的次数,类型应该是Integer
-
键盘录入一个字符串
-
创建HashMap集合,键是Character,值是Integer
-
遍历字符串,得到每一个字符
-
拿得到的每一个字符作为键到HashMap集合中去找对应的值,看其返回值
-
如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
-
如果返回值不是null:说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符和对应的值
-
-
遍历HashMap集合,得到键和值,按照要求进行拼接
-
输出结果
如果将HashMap改为用TreeMap将对键自动排序,用法相同
//输入字符串line HashMap<Character,Integer> hm = new HashMap<Character,Integer>(); for(int i = 0;i < line.length();i++) { char key = line.charAt(i); Integer value = hm.get(key); if (value == null) { hm.put(key,1); } elsc { value++; hm.put(key,value); //更新 } } StringBuilder sb = new StringBuilder(); Set<Character> keySet = hm.keySet(); for(Character key : keySet) { Integer value = hm.get( key ); sb.append(key).append("(").append(value).append(")"); } String result = sb.toString();
6.Collections
是针对集合操作的工具类
常用方法(静态) :
public static <T extends Comparable<?super T>> void sort(List<T> list):将指定的列表按升序排序
public static void reverse(List<?> list) : 反转指定列表中元素的顺序
public static void shuffle(List<?> list) : 使用默认的随机源随机排列指定的列表 --模拟洗牌
Collections.sort(list);
6.1ArrayList存储学生对象并排序 -案例(使用Collections)
//.......... Collections.sort(array,new Comparator<Stu>() { @Override public int compare(Stu s1, student s2) { //按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序 int num1 = s1.getAge() - s2.getAge(); int num2 = num1==0?s1.getName().compareTo(s2.getName()):num; return num2; } }); //遍历集合 for (Stu s : array ) { System.out.println(s.getName()+","+s.getAge()); }
6.2斗地主 发牌 洗牌 看牌 -案例(使用Collections)
1.创建一个牌盒,也就是定义一个集合对象,用ArrayList集合实现
2.往牌盒里面装牌
3.洗牌,也就是把牌打撒,用collections的shuffle()方法实现
4.发牌,也就是通历集合,给三个玩家发牌
5.看牌,也就是三个玩家分别遍历自己的牌
ArrayList<String> array = new ArrayList<String>(); //定义花色数组 点数数组 String[] colors = {"♦","♣","♥","♠"}; String[] number = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"}; //拼接 for(String color : colors) { for(string num : number) { array.add(color+num); } } array.add("小王"); array.add("大王"); //洗牌 Collections.shuffle Collections.shuffle(array); //发牌 定义3个玩家手牌列表 以及存储底牌列表 ArrayList<String> player1 = new ArrayList<String>(); ArrayList<String> player2 = new ArrayList<String>(); ArrayList<String> player3 = new ArrayList<String>(); ArrayList<String> dp = new ArrayList<String>(); //底牌 for(int i = 0;i < array.size();i++) { String poker = array get(i); if(i >= array.size()-3) { //判断底牌 dp.add(poker); } else if(i%3 == 0) { player1.add(poker); } else if(i%3 == 1) { player2 . add(poker); } else if(i%3 == 2) { player3.add(poker); } } //看牌 lookPoker("player1",player1); lookPoker("player2",player2); lookPoker("player3",player3); lookPoker("底牌",dp); /*---------定义看牌函数---------*/ public static void lookPoker(String name,ArrayList<String> array) { System.out.print(name +"的牌是:"); for(String poker : array ) { System.out.print( poker + " "); } System.out.println(); }
6.3斗地主 - 整合案例(HashMap-ArrayList-TreeSet)
使用HashMap键值对表示54张牌
key(索引) : 0---53 / value : ♦3--♠2--大王
使用ArrayList洗牌,仅打乱HashMap的key(索引)
使用TreeSet自然升序排列 看牌
创建HashMap,键是编号,值是牌
创建ArrayList,存储编号
创建花色数组和点数数组
从0开始往HashMap里面存储编号,并存储对应的牌 . 同时往ArrayList里面存储编号
洗牌(洗的是编号),用Collections的shuffle()方法实现
定义方法看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
调用看牌方法
//main HashMap<Integer,String> hm = new HashMap<Integer,String>(); ArrayList<String> array = new ArrayList<String>(); //定义花色数组 点数数组 String[] colors = {"♦","♣","♥","♠"}; String[] number = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"}; //往HashMap里面存储编号 int index = 0; for(String color : colors) { for(string num : number) { hm.put(index,color+num); array.add(index); index++; } } hm.put(index,"小王"); array.add(index); index++; hm.put(index,"大王"); array.add(index); //洗牌 Collections.shuffle 洗的是编号 Collections.shuffle(array); //发牌 使用TreeSet定义三个玩家手牌集合和一个底牌集合 TreeSet<Integer> player1 = new TreeSet<Integer>(); TreeSet<Integer> player2 = new TreeSet<Integer>(); TreeSet<Integer> player3 = new TreeSet<Integer>(); TreeSet<Integer> dp = new TreeSet<Integer>(); //底牌 //将发牌发出的编号有序存入TreeSet for(int i = 0;i < array.size();i++) { String poker = array get(i); if(i >= array.size()-3) { //判断底牌 dp.add(poker); } else if(i%3 == 0) { player1.add(poker); } else if(i%3 == 1) { player2 . add(poker); } else if(i%3 == 2) { player3.add(poker); } } //看牌 看牌函数上面已经定义过 lookPoker("player1",player1); lookPoker("player2",player2); lookPoker("player3",player3); lookPoker("底牌",dp); /*---------定义看牌函数---------*/ public static void lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hm) { System.out.print(name +"的牌是:"); for(Integer key : ts) { String poker = hm.get(key); System.out.print(poker+" "); } System.out. println(); }

浙公网安备 33010602011771号