MIKU MOE

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集合接收)

定义方法看牌(遍历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();
 }

 



posted @ 2021-08-12 18:22  miku_moe  阅读(42)  评论(0)    收藏  举报