集合Collection

集合体系结构

单列集合(Collection)(接口)

创建对象使用多态的方法例如:

Collection<String> strArr= new ArrayList<String>();
  • Collection集合常用方法
 boolean add(E e)  //添加元素
 boolean remove(Object o)  //从集合中移除指定元素
 void clear()  //清空集合中元素
 boolean contains(Object o)//判断集合中是否存在指定元素
 boolean isEmpty() //判断集合是否为空
 int size()//返回集合长度
  • Collection集合遍历
    • Iterator:迭代器,集合的专用遍历方式
    • Iterator iterator(); 返回此集合中元素的迭代器,通过集合的iterator()方法得到迭代器
    • 常用方法
      • E next();返回迭代中的下一个元素
      • boolean has Next(); 如果迭代具有更多元素则返回true
      • 遍历集合案例
public static void main(String[] args) {
        Collection<String> strArr= new ArrayList<String>();
        strArr.add("asd");
        strArr.add("qwe");
        Iterator<String> it = strArr.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println("s = " + s);
        }
    }

结果:

s = asd
s = qwe
List(可重复)(接口)
  • List集合概述和特点
    • 继承自Collection接口
    • 允许重复元素
    • 存在索引
    • 有序 :存储和取出的元素顺序一致
  • List集合特有方法
	void add(int index,E element) //在此集合中指定位置插入元素
	E remove (int index)  //根据索引删除元素并返回
	E set(int index,E element)//修改索引处元素并返回
	E get(int index) //返回索引处元素
  • 并发修改异常 ConcurrentModificationException
    • 产生原因 迭代器遍历过程中,通过集合对象修改了集合中元素的长度,造成迭代器中预期修改值实际修改值不一样
    • 解决方案一 使用for循环遍历
  • ListIterator
    • 通过List集合的listiterator()方法得到,所以说它是List集合特有的迭代器
    • ListIterator常用方法
void add(E e) //将指定元素插入列表  //
boolean hasNext() //判断下一个元素是否存在
boolean hasPrevious() //判断上一个元素是否存在
E next()//返回列表中下一个元素,移动光标
E privious()//返回列表中上一个元素,移动光标

PS:ListIterator的add方法会将实际修改值赋值给预期修改值,所以不会出现并发修改异常

  • 增强for循环
    • 增强for:简化数组和Collection集合遍历
    • 实现Iterable接口的类允许其对象成为增强型for语句的目标
    • 它是JDK5之后出现的,其内部原理是一个**Iterator迭代器 **
  • 增强for的格式:
    for(元素数据类型 变量名:数组或者Collection集合){
    //在此处使用变量即可,该变量就是元素
    }
  • 示例
int[] arr = {1,2,3,4,5}
for(int i :arr){
	System.out.println(i);
}
List<String> list = new ArrayList<String>();
lsit.add("asd");
list.add("qwe");
for(String s : list){
	sout(s);    //结果应该是asd , qwe
}
ArrayList(实现类)
  • 底层实现是数组,查询快,增删慢
    案例
import java.util.ArrayList;
import java.util.Iterator;

// 需求:创建一个存储学生对象的集合,存储三个学生对象,实用程序实现在控制台遍历该集合
public class ListBianLi {
    public static void main(String[] args) {
        ArrayList<Student> stuArr= new ArrayList<Student>();
        stuArr.add(new Student("gakki",30));
        stuArr.add(new Student("樱木花道",20));
        stuArr.add(new Student("巴菲特",68));
        //第一正增强for
        for(Student stu : stuArr){
            System.out.println(stu);
        }
        System.out.println("--------");
        //第二种迭代器
        Iterator<Student> it= stuArr.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("--------");
        //第三种普通for
        for (int i = 0;  i<stuArr.size() ; i++) {
            System.out.println(stuArr.get(i));
        }
    }
}

LinkedList(实现类)
  • 底层实现是链表,查询慢,增删快
    在这里插入图片描述
Set(不可重复)(接口)
  • 概述和特点
  • set是一个不包含重复元素的集合
  • 没有带索引的方法,不能用for循环遍历
  • 哈希值
    • 哈希值是JDK根据对象的地址字符串或者数字算出来的int类型的数值
    • Object类中有一个方法可以获取对象的哈希值
      • public int hashcode();
      • 同一个对象多次调用hashcode方法返回的哈希值相同
      • 默认情况下不同对象的哈希值是不同的,而重写hashCode()方法,可以实现让不同对象的哈希值相同
HashSet(实现类)
  • HashSet集合特点
    • 底层数据结构是哈希表
    • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
    • 没有带索引的方法,所以不能使用普通for遍历
    • 由于是set集合所以是不包含重复元素的集合
  • 案例
HashSet<String> hs = new HashSet<String>();
hs.add("hello");
hs.add("java");
hs.add("world");
hs.add("hello");
for(String s : hs){
	sout(s);
}//结果为hello world java 证明不可重复无序
  • HashSet集合保证元素唯一性原理
    在这里插入图片描述
  • HashSet为了保证唯一性需要在泛型中重写hashCode()和equals()
    案例
public class Student {

    private String name;
    private int age;
    public Student (String name1,int age1){
        this.name = name1;
        this.age = age1;
    }
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    //为了保证向hashset中添加对象时不重复需要重写hashcode和equals方法

    @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 class hashset01 {

    public static void main(String[] args) {
        HashSet<Student> hs = new HashSet<Student>();
        hs.add(new Student("张曼玉",20));
        hs.add(new Student("asd",21));
        hs.add(new Student("张曼玉",20));
        for(Student stu : hs){
            System.out.println(stu);
        }
    }
}

输出

Student{name='张曼玉', age=20}
Student{name='asd', age=21}
LinkedHashSet(实现类)
  • 哈希表和链表实现得Set接口,具有可预测的迭代次序
  • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
  • 由哈希表保证元素唯一,也就是说没有重复元素
  • 案例
LinkedHashSet<String> lhs = new LinkedHashSet<String>();
lhs.add("hello");
lhs.add("world");
lhs.add("java");
lhs.add("hello");
for(String s : lhs){
	sout(s);
}
结果为hello,world,java
TreeSet(实现类)
  • 间接继承Set接口
  • 元素有序,这里的有序不是指存储和取出顺序一致,而是按照一定的规则排序,具体的排序方法取决于构造方法;
    • TreeSet(); 根据其元素得自然排序进行排序
    • TreeSet(Comparator comparator);根据指定的比较器进行排序
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以不包含重复元素
    案例
   public static void main(String[] args) {
      TreeSet<Integer> ts = new TreeSet<>();
       ts.add(50);
       ts.add(20);
       ts.add(10);
       ts.add(111);
       ts.add(888);
       ts.add(20);
       for(Integer num : ts){
           System.out.println(num);
       }
   }
   结果为10 20 50 111 888 有序且不重复
  • 自然排序Comparable的使用
public class Student implements Comparable<Student>{

    private String name;
    private int age;
    public Student (String name1,int age1){
        this.name = name1;
        this.age = age1;
    }
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    //为了让学生类能够排序需要实现Comparable接口
    //返回值小于零认为当前对象比上一个小 大于零认为比上一个大  等于零认为相等所以不添加
    @Override
    public int compareTo(Student s) {
        int num = this.age-s.age; //升序 反过来就是降序
        int num2 = num==0?this.name.compareTo(s.name):num;//年龄差是否为0?如果为零就比较姓名,不为零就不用了
        return num2;
    }


}
public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<Student>();
        ts.add(new Student("张曼玉",20));
        ts.add(new Student("asd",21));
        ts.add(new Student("张曼玉",20));
        ts.add(new Student("asd",20));
        for(Student stu : ts){
            System.out.println(stu);
        }
    }

结果

Student{name='asd', age=20}
Student{name='张曼玉', age=20}
Student{name='asd', age=21}
  • Comparartor比较器使用(TreeSet带参构造方法)
  • 案例
 public static void main(String[] args) {
        //使用带参得TreeSet构造方法 创建一个匿名类重写compare方法
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getAge()-s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });
        ts.add(new Student("张曼玉",20));
        ts.add(new Student("asd",21));
        ts.add(new Student("张曼玉",20));
        ts.add(new Student("asd",20));
        for(Student stu : ts){
            System.out.println(stu);
        }
    }
    结果同上  效果与学生类实现Comparable方法一样

双列集合(Map)(接口)

Map集合基本的功能

在这里插入图片描述

Map集合的获取功能

在这里插入图片描述

Map集合的遍历

方法一

public static void main(String[] args) {
        Map<String , String> map = new HashMap<String , String>();
        map.put("樱木花道","流川枫");
        map.put("漩涡鸣人","宇智波佐助");
        map.put("8848","背背佳");
        Set<String> keyset = map.keySet(); //获取键的集合
        for(String key: keyset){
            String value = map.get(key);
            System.out.println(key+","+value);
        }
    }

方法二

	Map<String , String> map = new HashMap<String , String>();
    map.put("樱木花道","流川枫");
    map.put("漩涡鸣人","宇智波佐助");
    map.put("8848","背背佳");
    Set<Map.Entry<String, String>> entrySet = map.entrySet(); //获取所有键值对集合
    for(Map.Entry<String, String> me: entrySet){
        System.out.println(me.getKey()+","+me.getValue());
    }

应用案例1

 //需求创建一个HashMap集合,键是学生对象,值是居住地。存储多个键值对元素,并遍历。
    //要求保证键的唯一性:如果学生对象成员变量的值都相同就认为是同一个对象
    public static void main(String[] args) {
        Map<Student , String> map = new HashMap<Student , String>();
        Student stu1 = new Student(20,"流川枫");
        Student stu2 = new Student(18,"樱木花道");
        Student stu3 = new Student(21,"佐助");
        Student stu4 = new Student(21,"佐助");
        map.put(stu1,"北京");
        map.put(stu2,"上海");
        map.put(stu3,"武汉");
        map.put(stu4,"沈阳");//学生作为键需要保证键的唯一性所有就要重写学生类得equals和hashcode方法

        Set<Student> keySet = map.keySet();

        for(Student key: keySet){
            String value = map.get(key);
            System.out.println(key.getAge()+","+key.getName()+","+value);
        }
//      输出18,樱木花道,上海
    //      20,流川枫,北京
    //      21,佐助,沈阳
泛型
泛型方法与泛型类
public class Gic<T>{ //类
	public void show(T t){
		sout(t);
	}
}
public class Gic{
	public <T> void show(T t){
		sout(t);
	}
}
泛型接口
public interface Generic<T>{
	void show(T t);
}
public class GenericImpl<T> implements Generic<T>{
	void show(T t){
		sout(t);
	}
}
类型通配符
List<?> list1 = new ArrayList<Object>();
List<?> list1 = new ArrayList<Number>();
List<?> list1 = new ArrayList<Integer>();

//List<? extends Number> list1 = new ArrayList<Object>(); 不可以
List<? extends Number> list1 = new ArrayList<Number>();
List<? extends Number> list1 = new ArrayList<Integer>();

List<? super Number> list1 = new ArrayList<Object>();
List<? super Number> list1 = new ArrayList<Number>();
//List<? super Number> list1 = new ArrayList<Integer>(); 不可以

可变参数
public int sum(int... a){
	int sum = 0;
	for(int i : a){
		sum+=i;
	}
	return sum;
}
public int sum(int a,int... b){ //如果要两个以上参数 
	return 0;
}
可变参数的使用
HashMap(实现类)

案例

//需求:键盘录入一个字符串,要求统计字符串中每个字符串出现的次数
    //例如:键盘录入“asdasdasdfffea”在控制台输出"a4d3e1f3s3"
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入字符串");
        String s = scanner.nextLine();  //获取键盘键入得字符串

        HashMap<Character, Integer> charIntHs = new HashMap<>(); //创建hashmap
        for (int i = 0; i < s.length() ; i++) {  //循环遍历字符串 如果get到value就++如果没有get到就put
            char key = s.charAt(i);
            Integer value =  charIntHs.get(key);
            if(value==null){
                charIntHs.put(key,1);
            }else {
                charIntHs.put(key,++value);
            }
        }

        Set<Character> keySet = charIntHs.keySet(); //根据keyset遍历hashmap

        for(Character ch : keySet){
            Integer integer = charIntHs.get(ch);
            System.out.println(ch+","+integer);
        }
    }

常见数据结构值哈希表

  • JDK8之前,底层采用数组+链表实现 可以说是一个元素为了链表的数组
  • 8之后在长度比较长的时候底层实现了优化
    在这里插入图片描述

Collections应用(模拟斗地主,洗牌发牌)

Collections常用方法

在这里插入图片描述

案例

在这里插入图片描述

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

// 需求 通过程序实现斗地主过程中的洗牌,发牌和看牌 要求对牌进行排序
/*
 *   思路:
 *      1.创建HashMap,键是编号,值是牌
 *      2.创建ArrayList,存储编号
 *      3.创建花色数组和点数数组。
 *      4.从0开始往HashMap里面存储编号,并存储对应的牌,同时往ArrayList里存储编号
 *      5.洗牌(洗的是编号)用Collections的shuffle()方法实现
 *      6.发牌(发的是编号,为了保证编号是排序的,创建TreeSet集合接收)
 *      7.定义方法看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
 *      8.调用看牌的方法
 *
 * */
public class doudizhu {
    public static void main(String[] args) {
        HashMap<Integer, String> map = new HashMap<>();
        ArrayList<Integer> array = new ArrayList<>();
        String[] point = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
        String[] huase = {"♥", "♦", "♣", "♠"};
        int index = 0;
        for (int i = 0; i <point.length ; i++) {
            for (int j = 0; j <huase.length ; j++) {
                map.put(index,huase[j]+point[i]);
                array.add(index);
                index++;
            }
        }
        map.put(index,"小王");
        array.add(index);
        index++;
        map.put(index,"大王");
        array.add(index);

        Collections.shuffle(array);

        TreeSet<Integer> lqxSet = new TreeSet<>();
        TreeSet<Integer> jySet = new TreeSet<>();
        TreeSet<Integer> sySet = new TreeSet<>();
        TreeSet<Integer> dpSet = new TreeSet<>();

        for (int i = 0; i <array.size() ; i++) {
            int index1=array.get(i);
            if(i>=array.size()-3){
                dpSet.add(index1);
            }else if(i%3==0){
                lqxSet.add(index1);
            }else if(i%3==1){
                sySet.add(index1);
            }else if(i%3==2){
                jySet.add(index1);
            }
        }
        lookPoker("林青霞",lqxSet,map);
        lookPoker("结衣",jySet,map);
        lookPoker("石原",sySet,map);
        lookPoker("底牌",dpSet,map);

    }
    public static void lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String > hm){
        System.out.println(name+"的牌是:");
        for (Integer key:ts) {
            System.out.print(hm.get(key));
        }
        System.out.println();
    }

}

结果:

林青霞的牌是:34456778910♥J♠J♦Q♣Q♠Q♠A♥2
结衣的牌是:45666788891010♣J♣K♥A♦A♦2
石原的牌是:3355799♦J♥Q♥K♦K♠K♣A♣22小王大王
底牌的牌是:3410

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值