Java集合

Java集合

数组作为容器,可以存储基本数据类型,也可以存储引用数据类型,数组一旦定义出来,长度就固定了,而且也只能存储引用数据类型,用起来不太方便,需哦一就引出了集合的概念。

集合

集合的长度是可变的,集合中可以存储不同的数据类型,但是集合不能存储基本数据类型

集合中的方法
   Collection:     包括      list     和 set

a/添加功能
 boolean add(Object obj):添加一个元素

 boolean addAll(Collection c):添加一个集合的元素  (给一个集合添加进另一个集合中的所有元素)

 Collection con = new ArrayList();
        con.add(s1);
        con.add(s2);
        con.add(s3);
 Collection con2 = new ArrayList();
        con2.add(Integer.valueOf(1));
        con2.add(2);
        con2.add(3);
        con.addAll(con2);
b/删除功能

   void clear():移除所有元素
   boolean remove(Object o):移除一个元素
   boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素 ,如果没有交集元素 则删除失败 返回false

 Collection collection = new ArrayList();
     collection.add("关羽");
        collection.add("张飞");
        collection.add("赵云");
        collection.add("马超");
        collection.add("魏延");
        boolean b = collection.remove("魏延");
   A 集合 removeAll B 集合,如果两个集合没有交集元素,则移除失败
   两个集合中的元素都不会发生变化
   如果说有交集元素, A 集合 removeAll B 集合 那么A中就会移除掉 交集元素 B集合不发生变化,移除成功
c/判断功能

   boolean contains(Object o):判断集合中是否包含指定的元素 
   boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合 包含 另一个集合中所有的元素才算包含 才返回true)

   boolean isEmpty():判断集合是否为空


 d/获取功能,接口 Iterator<E> 迭代器(可以理解为遍历)

 boolean hasNext()
 如果仍有元素可以迭代,则返回 true

Iterator iterator = collection.iterator();
            while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);}
e/长度功能

      int size():元素的个数

f/交集功能


   A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化
   boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)

g/把集合转换为数组


    toArray( )        System.out.println(collection.size());

 Collection collection = new ArrayList();
        collection.add(1);
        collection.add(2);
        collection.add(3);
        collection.add(4);
        collection.add(5);
        collection.add(6);
  Object[] toArray();
        Object[] objects = collection.toArray();

但是要注意的是通过aslist方法把数组转换成集合后,这个集合就不能再添加元素了

Integer[] integers = {1, 2, 3, 7};
        List<Integer> integers1 = Arrays.asList(integers);
        // integers1.remove(1);//报错
        //integers1.add(6);//报错
Collection 集合 对应一个工具类  Collections
ArrayList<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(6);
        list.add(5);
        list.add(2);
        list.add(1);
        list.add(9);
        list.add(10);
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer s1, Integer s2) {
                return s1 - s2;
            }
        };
        //Lambda 表达式 需要 函数式接口的支持,使用Lambda表达式可以有效的的节省代码,但应用时一定要细心将表达式补充完整。
        //函数式接口 接口里面只有一个抽象方法就是函数式接口
        // Comparator<Integer> com = (x, y) -> x - y;
      //Lambda 表达式 要一种函数式接口的支持                              排序
        list.sort(comparator);
        Collections.sort(list);
        System.out.println(list);
二分查找,前提是集合的元素有序
        int i = Collections.binarySearch(list, 10);
        System.out.println(i);
获取集合中 最大值和最小值
        Integer max = Collections.max(list);
        Integer min = Collections.min(list);
反转集合中的元素
        Collections.reverse(list);
        System.out.println(list);
随机打乱集合中的元素顺序
        Collections.shuffle(list);
        System.out.println(list);
接口 Iterator<E>


通过迭代器是遍历集合的一种方式

  boolean hasNext()
        如果仍有元素可以迭代,则返回 true。
        next()
        返回迭代的下一个元素。

 Iterator iterator = collection.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);}
获取集合长度的方法 size()

System.out.println(collection.size());


虽然集合可以存储任意数据的引用数据类型但一般来说,我们不会给集合中存储的多种类型的元素,我们一般只在集合里面就存储一种类型

List集合:  包括  ArrayList       Vector         LinkedList

 允许元素重复
  void add(int index,E element): 在指定索引处添加元素
  E remove(int index):移除指定索引处的元素  返回的是移除的元素
  E get(int index):获取指定索引处的元素
  E set(int index,E element):更改指定索引处的元素 返回的而是被替换的元素
  subList(首索引,尾索引),根据首位索引截取集合中的元素
List的三个子类的特点
 ArrayList  底层数据结构是数组,增删慢,查询快  线程不同步,数据不安全,效率高
 Vector 底层数据结构也是数组,增删慢 查询快 线程同步,数据安全,效率慢
 LinkedList 底层数据结构是链表,增删快 查询慢 线程不同步,数据不安全效率高
我们根据需要,如果对数据安全要求较高,建议采用Vector
还要考虑操作中查询多还是增删多
数组特点: 查询快 , 增删慢
链表特点:  查询慢 , 增删快


ListIterator

ListIterator继承了Iterator,所以也可以使用Iterator中的方法

而ListIterator的特有功能有

  boolean hasPrevious():   是否存在前一个元素
  E previous():     返回列表中的前一个元素

用这两个方法反向遍历集合

因为指针默认在集合开始,只有先将指针放到末尾才能反向遍历

  ListIterator<String> iterator = list.listIterator();
        while (iterator.hasNext()){
            System.out.println( iterator.next());
        }
        System.out.println("---------------------");
            while (iterator.hasPrevious()){
            System.out.println(iterator.previous())

List集合的遍历方式
如果说你用迭代器去遍历集合,在遍历的中间,如果你想往集合里面加元素,或者说删除元素
那就要用迭代器自己的 添加和删除方法,不要用集合的添加和删除方法,不然就会报并发修改异常,//ConcurrentModificationException,所以经常采用for循环来遍历
   方式1:
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {

            System.out.println(iterator.next());
        }
        System.out.println("----------------------------------------");
   方式2:采用List 特有的迭代器
        ListIterator<String> stringListIterator = list.listIterator();
        while (stringListIterator.hasNext()) {
            System.out.println(stringListIterator.next());

        }
        System.out.println("----------------------------");
   方式3:for 循环遍历//我们最常用for循环来遍历
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));

        }
ArrayList
他的底层数据结构是数组,所以 查询快,增删慢
数据是有序的,存的顺序和取得顺序一样

去除ArrayList中重复字符串元素方式
  ArrayList<String> list = new ArrayList<>();
        list.add("唐三藏");
        list.add("孙大圣");
        list.add("猪悟能");
        list.add("沙悟净");
        list.add("小白龙");
        list.add("唐三藏");
        list.add("孙大圣");
        list.add("猪悟能");
        list.add("沙悟净");
        list.add("小白龙");
        //重新拿出一个集合,遍历第一个集合,去掉重复的元素
        ArrayList<String> newList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            String ele = list.get(i);
            if (!newList.contains(ele)) {
                newList.add(ele);
            }
        }
        System.out.println(newList);
        System.out.println(list);
其中contains这个方法底层调用了equals方法,默认比较的是地址值,所以当两个对象相同时,我们要重写equals方法
 Vector

insertElementAt(E obj, int index)在指定索引的位置插入一个元素

indexOf(Object o)返回指定元素的一次出现的索引

lastElement()获取集合中最后一个元素

firstElement()获取集合中第一个元素

Vector 特有的一个遍历方式
        Enumeration<String> elements = v.elements();

       boolean hasMoreElements()
        测试此集合是否包含更多元素。
        E nextElement()
       返回此集合的下一个元素,如果此集合至少有一个元素可以返回。

LinkedList
void addFirst(E e)在此列表的开始处插入指定的元素。
void addLast(E e)将指定的元素列表的结束。
getFirst()返回此列表中的第一个元素。
getLast()返回此列表中的最后一个元素。
boolean offer(E e)将指定的元素添加到列表的尾部(最后一个元素)。
boolean offerFirst(E e)在列表的前面插入指定的元素。
boolean offerLast(E e)在列表的结尾插入指定的元素。
void push(E e)将一个元素放在集合最前端


Arrays工具类的asList()方法

将数组元素转换成集合,得到的集合长度是不可变的 你不能往这个转换后的集合中 添加元素(add) 和 删除元素(remove), 只能获取元素(get)


数据结构的栈和队列

数据结构的数组和链表

set接口:包含HashSet   LinkedHashSet     TreeSet

set集合的特点:元素是无序的,唯一的
HashSet(无序,唯一)
HashSet集合底层结构是哈希表,哈希表底层维护的是数组和链表
HashSet集合靠元素重写hashCode和equals方法来保证元素的唯一性
元素有序靠链表保证
元素唯一靠哈希表保证
如果元素不重写这两个方法,就无法保证唯一性
String和Integer默认重写了hashCode方法和equals方法
HashSet存储元素保证元素唯一性图解



TreeSet(排序,唯一)
TreeSet  底层数据结构是二叉树结构,元素唯一,而且还能排序

二叉树存储数据保证元素唯一性的原理图解


排序的方法有两种

1。自然排序    空参构造采用的就是自然排序
采用自然排序,是元素实现了Comparaeble接口 重写了compareTo方法
如果元素不重写接口中的方法。那么存储元素时就会报错
存元素的时候,根据 compareTo方法的返回值来决定
返回0:就不存
返回正数:往树的根节点的右边存
返回负数:往树的根节点的左边存

string和Integer默认实现了Compareble和重写了compareTo方法
 TreeSet<String> tree = new TreeSet<>();
        tree.add("b");
        tree.add("a");
        tree.add("b");
        tree.add("c");
        tree.add("d");
        tree.add("a");
        System.out.println(tree);


2。比较器排序  有参构造采用的就是比较器排序
   创建TreeSet对象的时候,传进来一个比较器的子类对象
  接口 Comparator<T> 比较器
   int compare(T o1, T o2) 比较方法比较用来排序的两个参数
   根据子类对象重写比较器中的compare方法,根据方法返回值的正负和0来排序元素和去重
   对于自定义类,采用匿名内部类的方法去重写方法传参数比较方便,当然自己定义一个子类也是可以的
TreeSet t = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer s1, Integer s2) {
                return s1 - s2;
            }
        });
        t.add(6);
        t.add(6);
        t.add(3);
        t.add(2);
        t.add(1);
        t.add(4);
        t.add(5);
        t.add(4);
        t.add(3);
        System.out.println(t);
    }//[1,2,3,4,5,6]
LinkedHashSet(有序,唯一)

LinkedhashSet  底层数据结构是链表和哈希表

元素有序靠链表保证,元素唯一靠哈希表保证

LinkedHashSet<Integer> list = new LinkedHashSet<>();
        list.add(Integer.valueOf(1));
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list);//[1, 2, 3, 4, 5]
用自然排序:采用自然排序 要求元素必须实现Comparable接口
            然后重写compareTo方法 根据自己的排序方式 返回正负或0

用比较器去排序:采用匿名内部类的方式去传入比较器 的子类对象,重写compare方法


接口 Map<K,V>

将键映射到值的对象,一个映射不能包含重复的键,每个键最多映射一个值,K为键。V为值。map集合中,一个键只对应一个值,当键相同时值会覆盖,其中允许使用null键与null值,

map集合的数据结构只和键有关,与值无关

常用方法
HashMap<String, String> hm = new HashMap<>();
 String put = hm.put("老大", "呵呵");//添加元素
String put2 = hm.put("张三", "哈哈");//键相同,值覆盖
String put3 = hm.put("张三", "呵呵");//输出结果:张三呵呵
 hm.remove("老大");//移除一个键值对
hm.clear();//清空一个集合
boolean b = hm.containsKey("张三");//判断一个集合是否包含指定键
boolean v = hm.containsValue("哈哈");//判断一个集合是否包含指定值
boolean empty = hm.isEmpty();//判断一个集合是否为空

类 HashMap<K,V>

允许插入null键和null值
HashMap和Hashtable的区别: 
  HashMap: 非同步,线程不安全,效率高.允许null值和null键
  Hashtable: 同步,线程安全 , 效率低.不允许null值和null键

获取所有值的集合
 Collection<String> values = hm.values();
        for(String v:values){
            System.out.println(v);
        }
获取集合长度
hm.size();


遍历集合有两种方法
1。通过键来找值
 Set<Integer> keys = hm.keySet();//获取所有键的集合
        for (Integer key : keys) {
            String value = hm.get(key);//通过键,获取值
            System.out.println(key + "====" + value);
        }
2。直接获取   键值对  对象 ,用对象里面的方法获取键跟值
 Set<Map.Entry<Integer, String>> entries = hm.entrySet();
        for (Map.Entry<Integer, String> en : entries) {
            System.out.println(en.getKey() + "===" + en.getValue());
        }

类 LinkedHashMap<K,V>

底层数据结构是链表和哈希表,元素有序且唯一
其特点是保存了记录的插入顺序,先得到的记录先插入,LinkedHashMap取的顺序就是自己存的顺序

类 TreeMap<K,V>

TreeMap集合不允许插入null键,可以插入null值
TreeMap集合的两种排序方法:自然排序和比较器排序
方法与TreeMap大致相同



案例演示:经常拿来看看,复习一下

案例演示: 需求:统计字符串中每个字符出现的次数      "aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:"a(5)b(4)c(3)d(2)e(1)"
利用Map集合键相同值覆盖的特点,很适合用来获取字符串的次数
 HashMap<Character, Integer> hm = new HashMap<>();
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一段字符串");
        String str = sc.next();
        // asdfasdfasdfwefwefasdfwef
        //遍历字符串
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (hm.get(ch) == null) {//第一次找
                hm.put(ch, 1);//没找到,存进去
            } else {
              //找到了 取出这键 对应的值,自增1 再存进去,让他键相同,值覆盖
                Integer v = hm.get(ch);
                v++;
                hm.put(ch, v);
            }
        }
        // System.out.println(hm);
        StringBuffer sb = new StringBuffer();
        Set<Character> keys = hm.keySet();
        for (Character ch : keys) {
            Integer v = hm.get(ch);
            sb.append(ch).append("(").append(v).append(")");
        }

        String s = sb.toString();
        System.out.println(s);

案例演示:集合嵌套

HashMap嵌套HashMap
	jc	基础班
		张三	20
		李四	22
	jy	就业班
		王五	21
		赵六	23

package org.westos.demo6;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test {
    public static void main(String[] args) {
        HashMap<String, Integer> jc = new HashMap<>();
        jc.put("张三", 20);
        jc.put("李四", 22);

        HashMap<String, Integer> jy = new HashMap<>();
        jy.put("王五", 21);
        jy.put("赵六", 23);

        HashMap<HashMap<String, Integer>, String> bj = new HashMap<>();
        bj.put(jc, "jc\t\t基础班");
        bj.put(jy, "jy\t\t就业班");

        Set<Map.Entry<HashMap<String, Integer>, String>> entries = bj.entrySet();
        for (Map.Entry<HashMap<String, Integer>, String> en : entries) {
            HashMap<String, Integer> key = en.getKey();
            String value = en.getValue();
            System.out.println(value);
            Set<String> strings = key.keySet();
            for (String s : strings) {
                System.out.println("\t\t" + s + "\t\t" + key.get(s));
            }
        }
    }
}
HashMap嵌套ArrayList
package org.westos.demo6;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Test2 {
    public static void main(String[] args) {
        ArrayList<String> jc = new ArrayList<>();
        jc.add("张三\t\t20");
        jc.add("李四\t\t22");

        ArrayList<String> jy = new ArrayList<>();
        jy.add("王五\t\t21");
        jy.add("赵六\t\t23");

        HashMap<String, ArrayList<String>> bj = new HashMap<>();

        bj.put("jy\t\t就业班",jy);
        bj.put("jc\t\t基础班",jc);
        Set<Map.Entry<String, ArrayList<String>>> entries = bj.entrySet();
        for(Map.Entry<String, ArrayList<String>> en:entries) {
            String key = en.getKey();
            System.out.println(key);
            ArrayList<String> value = en.getValue();
            for(String s: value){
                System.out.println("\t\t"+s);
            }
        }
    }
}

案例演示:斗地主,经常拿来看看,复习一下

使用ArrayList

package org.westos.demo4;

import java.util.ArrayList;
import java.util.Collections;

public class MyTest7 {
    public static void main(String[] args) {
        //模拟斗地主的发牌和看牌
        // 模拟斗地主洗牌和发牌,牌没有排序
        //1.定义一个牌盒 来装牌
        //2.生成54张牌装进牌盒
        //3.洗牌
        //4.发牌
        //5.看牌
        //1.创建牌盒子
        ArrayList<String> pokerBox = new ArrayList<>();
        //2.生成牌 ,装进牌盒
        String[] colors = {"♣", "♠", "♥", "◆"};
        String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
        for (String color : colors) {
            for (String num : nums) {
                String pai = color.concat(num);
                pokerBox.add(pai);

            }

        }
        //添加大小王
        pokerBox.add("★");
        pokerBox.add("☆");

        //洗牌
        Collections.shuffle(pokerBox);
        Collections.shuffle(pokerBox);
        Collections.shuffle(pokerBox);

        //  System.out.println(pokerBox);
        // 发牌
        ArrayList<String> 底牌 = new ArrayList<>();
        ArrayList<String> 周星驰 = new ArrayList<>();
        ArrayList<String> 吴宗宪 = new ArrayList<>();
        ArrayList<String> 曾志伟 = new ArrayList<>();
        //发牌的算法
//        周星驰 0 3 6 9
        吴宗宪 1 4 7 10
        曾志伟 2 5 8 11
        for (int i = 0; i < pokerBox.size(); i++) {
            //留底牌
            if (i >=pokerBox.size() - 3) {
                底牌.add(pokerBox.get(i));
            } else if (i % 3 == 0) {
                周星驰.add(pokerBox.get(i));

            } else if (i % 3 == 1) {
                吴宗宪.add(pokerBox.get(i));

            } else if (i % 3 == 2) {
                曾志伟.add(pokerBox.get(i));
            }
        }

        //看牌
        lookPoker("周星驰",周星驰);
        lookPoker("吴宗宪",吴宗宪);
        lookPoker("曾志伟",曾志伟);
        lookPoker("底牌",底牌);
    }

    private static void lookPoker(String name, ArrayList<String> list) {
        System.out.println(name);
        for(String s:list){
            System.out.print(s+"  ");
        }
        System.out.println();
    }
}
使用HashMap
package org.westos.demo4;

import sun.security.action.PutAllAction;

import java.util.*;

public class MyTest8 {
    public static void main(String[] args) {
        //创建牌盒
        HashMap<Integer, String> pokerBox = new HashMap<>();
        //生成牌,往牌盒里面装牌
        String[] colors = {"♣", "♠", "♥", "◆"};
        String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
        int index = 0;//定义索引
        for (String num : nums) {
            for (String color : colors) {
                String poker = num.concat(color);
                pokerBox.put(index, poker);
                index++;

            }
        }
        //手动添加两张王
        pokerBox.put(index, "★");
        index++;
        pokerBox.put(index, "☆");
        //System.out.println(pokerBox);
        //洗牌
        Set<Integer> integers = pokerBox.keySet();
        ArrayList<Integer> suoyin = new ArrayList<>();
        for (Integer i : integers) {
            suoyin.add(i);

        }

        // System.out.println(suoyin);
        Collections.shuffle(suoyin);
        Collections.shuffle(suoyin);
        Collections.shuffle(suoyin);

        //发牌
        TreeSet<Integer> 底牌 = new TreeSet<Integer>();
        TreeSet<Integer> 周星驰 = new TreeSet<Integer>();
        TreeSet<Integer> 吴宗宪 = new TreeSet<Integer>();
        TreeSet<Integer> 曾志伟 = new TreeSet<Integer>();
        for (int i = 0; i < suoyin.size(); i++) {
            if (i >= suoyin.size() - 3) {

                底牌.add(suoyin.get(i));
            } else if (i % 3 == 0) {

                周星驰.add(suoyin.get(i));
            } else if (i % 3 == 1) {

                吴宗宪.add(suoyin.get(i));
            } else if (i % 3 == 2) {
                曾志伟.add(suoyin.get(i));
            }

        }

        //看牌
        lookPoker("底牌", 底牌, pokerBox);
        lookPoker("周星驰", 周星驰, pokerBox);
        lookPoker("吴宗宪", 吴宗宪, pokerBox);
        lookPoker("曾志伟", 曾志伟, pokerBox);


    }

    private static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> pokerBox) {
        System.out.println(name);
        for (Integer in : ts) {
            System.out.print(pokerBox.get(in));
        }

        System.out.println();

    }
}






















评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值