Java的collection集合/set容器/list容器/map容器

一、collection集合【父类】

collection是父类 父类的方法子类全都可以使用

集合和数组的区别

1、数组 长度固定
集合 长度不固定

2、数组中存储的数据是同一类型的
集合存储的一定是对象 不过对象是任意类型的
list.add(“abc”)

什么时候用集合?
当对象很多的时候(对象很多?不存在的…

collection集合的方法
①、如何知道添加完到底有没有?直接输出对象

Collection c=new ArrayList();

以前直接输出对象 然后输出结果是类名@内存地址
这里是打印集合 把集合中的元素以数组形式打印出来

②、一般方法(不带All的方法)
add() 添加 可以添加任意类型的对象
remove() 删除
contains() 判断集合中是否包含某个对象 返回boolean
size() 返回此列表的元素数

③、全部方法(带All的方法)
addAll() 添加全部 将collection2的所有元素添加到collection1的尾部 并且内容允许重复
containsAll() A.containsAll(B)判断集合A里是否包含集合B中的所有元素 返回boolean
removeAll() A.removeAll(B)移除A中包含在B中的所有元素 即 移除集合A和集合B共同的元素
retainAll() A.retainAll(B)保留A中包含在B中的所有元素 即 保留集合A和集合B共同的元素

二、list【子类,继承自collection】

List容器的特点

1、元素存储和取出顺序是有序的
2、有角标 可以进行精确地定位
3、允许重复的元素

这是List集合的特有方法★因为能精确定位

list.size() 获取该list集合的总长度
for (int i=0;i<list.size();i++)
{
    System.out.println(list.get(i));
}

List接口支持对元素进行curd(create update read delete)操作
注:只有List集合可以增删改查 因为它有角标

经典for循环用迭代器遍历集合元素示例:
for (Iterator<MyStudent> it = list.iterator(); it.hasNext();)
{
    MyStudent s=it.next();
    System.out.println(s);
}

1、ArrayList

ArrayList特点★
1、定位一个元素很快 因为有索引
2、增加和删除一个元素很慢 因为底层是数组实现 效率较低
它采用的是数组结构
方法:
获取元素 get(int index) :
只是获取 不进行修改

MyStudent a=list.get(0);

修改元素 set(int index,E element) :
(获取为get 修改为set)

list.set(0,new MyStudent("学生M",17));

2、LinkedList

LinkedList特点★ LinkedList:链接链表 简称链表
数据域→指针域
1、查找操作费时
2、添加和删除操作 简单
它采用的是链表结构
方法:
addFirst(E e) 将指定元素插入此列表的开头:

link.addFirst("aaa");

addFirst(E e) 将指定元素插入此列表的末尾:

link.addLast("zzz");

获取第一个数据:

link.getFirst();

获取最后一个数据:

link.getLast();

获取元素 get(int index) 只是获取 不进行修改:

MyStudent a=list.get(0);

修改元素 set(int index,E element) :
(获取为get 修改为set)

list.set(0,new MyStudent("学生M",17));

三、set【子类,继承自collection】

Set容器的特点

1、元素存储和取出顺序是无序的
2、没有角标 不能进行精确地定位
3、不允许重复的元素 内容相同的只保留一个 它是通过复写equals()方法来判断是否的重复元素

Set容器和List容器一样 同样支持迭代和增强for循环

1、HashSet

返回哈希值

int hashCode=stu1.hashCode();

小案例

需求:同姓名同年龄视为同一个人

前置:
        set.add(new Student("treeset",16));
        set.add(new Student("B",21));
        set.add(new Student("C",24));
        set.add(new Student("treeset",16));

首先调用hashCode() 判断两个对象的哈希值是否一样(算法可以凭自己喜好写)

重写hashCode()方法★
重写hashCode()方法的目的就是要让同姓名同年龄的hashCode相同
因为原装的hashCode的算法结果 同姓名同年龄的hashCode不同 无法达到需求

public int hashCode()
{
        return name.hashCode()+age;
 }

若两个对象的hashCode()不相同 则:存这个对象
若两个对象的hashCode()相同 则:调用equals()方法 判断内容也是否一样
若不一样 采用拉链法 存储
若一样 视为重复 不存储

重写equals()方法★

public boolean equals(Object obj) {
        if (this==obj)//若传进来的和当前引用对象为同一个对象(即:自己和自己比较)
        {
            return true;
        }
        if (obj==null)//若传空值
        {
            return false;
        }
        if (obj instanceof Student)//若传进来的不为Student类或其子类
        {
            Student s=(Student)obj;//强制类型转换
            return name.equals(s.name) && this.age==s.age;//判断姓名和年龄是否相等
        }
        return super.equals(obj);
}

以上如此 即可实现需求

2、TreeSet

排序有两种方式:
1、实现Compareable接口 并且复写CompareTo()方法
2、TreeSet(Comparator<? super E> comparator)
构造一个新的空TreeSet 它根据指定比较器进行排序

①、compareTo()方法

用此方法时 传入的自定义的类必须实现Comparable接口 并且复写compareTo方法 二者缺一不可★

比较方法一:根据姓名排序★

@Override
public int compareTo(StudentX s)
{
    //在此比较时 必须明确主次 主要条件相等 再进行次要条件比较
    int temp=this.name.compareTo(s.name);
    return temp==0?/*若姓名相同*/ this.age-s.age:temp/*若姓名相同 返回年龄,若姓名不相同 返回0*/          /*再按照姓名排序*/;
}

比较方法二:根据年龄排序★

@Override
public int compareTo(StudentX s)
{
    //在此比较时 必须明确主次 主要条件相等 再进行次要条件比较
    int temp=this.age-s.age;
    return temp==0?/*若年龄相同*/ this.name.compareTo(s.name):temp/*再按照姓名排序*/;
}

②、compare()方法★★★
用此方法时 传入的自定义的类无须实现Comparable接口 无须复写compareTo方法★
但要在比较器里实现Comparator接口 复写compare方法★
语法:TreeSet(Comparator<? super E> comparator)
构造一个新的空TreeSet 它根据指定比较器进行排序
例:Set<StudentXX> set=new TreeSet<StudentXX>(new TreeSetCompareByName())

用于中文比较的类

Collator collator=Collator.getInstance(Locale.CHINA);

小案例:

要求:姓名和年龄相同 视为同一个对象
按照姓名排序:当姓名相同 再根据年龄排序

自己创建个比较器 用于执行固定的功能

public class TreeSetCompareByName implements Comparator<StudentXX> 
{
    @Override
    public int compare(StudentXX o1, StudentXX o2) {
        //如果是汉字,字符串比较不包含中文
        Collator collator=Collator.getInstance(Locale.CHINA);//用于中文比较的类★★★
        int temp=collator.compare(o1.name,o2.name);
        return temp==0? o1.age-o2.age:temp;//若o1.age大于o2.age 返回一个正数 则代表o1的age比o2的age大 且它们两个不相等
}

要求:姓名和年龄相同 视为同一个对象
按照年龄排序:当年龄相同 再根据姓名排序

自己创建个比较器 用于执行固定的功能

public class TreeSetCompareByAge implements Comparator<StudentXX> 
{
    @Override
    public int compare(StudentXX o1, StudentXX o2) {
        //如果是汉字,字符串比较不包含中文
        Collator collator=Collator.getInstance(Locale.CHINA);//用于中文比较的类★★★
        int temp=o1.age-o2.age;//若o1.age大于o2.age 返回一个正数 则代表o1的age比o2的age大 且它们两个不相等
        return temp==0? collator.compare(o1.name,o2.name):temp;
    }
}

总结:

Set两个实现类:

一、hashset

底层结构:哈希表(数组+链表)
如果自定义一个类
自定义:对象是否是同一个对象 就要重写HashCode()方法和equals()方法

二、TreeSet

底层结构:二叉树结构
1、让自定义的类去实现comparable接口 重写compareTo()方法
自定义排序需求(根据年龄、姓名…)

2、写一个比较器 实现comparator 重写compare()方法
自定义排序需求(根据年龄、姓名…)

TreeSet比HashSet多了排序功能

四、map【子类,继承自collection】

不关心实现类到底是谁 只关心顶层方法
存储特点:
存储重复键 对应的值会被覆盖

方法:

put(K key, V value)   往map里添加键值对

get(Object key)  返回指定键所映射的值,如果此映射不包含该键的映射关系 则返回null

remove(Object key)  如果存在一个键的映射关系,则将其从此映射中移除

Integer a=map.remove("bbb");//移除一个key键 并返回这个键对应的value值

keySet() 返回此映射中所有的键

K→getKey() 返回与此项对应的键

V→getValue() 返回与此项对应的值

Set<Map,Entry<K,V>>entrySet() 返回此映射中包含的映射关系的Set视图
返回map中键值对的映射关系 这个键值对的映射关系由Set保存

拆箱:将Integer类型自动转化成int类型

例:

Map<String,Integer> map=new HashMap<String,Integer>();
map.put("aaa",1);
int i=map.get("aaa");

Map集合的遍历方式:

方法一、通过键找值 ★
步骤:
1、调用集合的keySet()方法 获得集合所有的键
2、遍历所有的键 调用集合的get(Object obj) 通过指定的键找到对应的值

方法:
keySet() 返回此映射中所有的键
例:

Map<String,Integer> map=new HashMap<String,Integer>();

map.put("aaa",1);
map.put("bbb",2);
map.put("ccc",99999);
map.put("ccc",3);

Set<String> mySet=map.keySet();//通过map集合的keySet()方法获得集合中的全部的键key

or (Iterator<String> it=mySet.iterator();it.hasNext();)
{
      String myKey=it.next();
      Integer myValue=map.get(myKey);//通过key找到对应的value值
      System.out.println("Key="+myKey+" Value="+myValue);
}

方法二、通过map.entrySet()方法 ★
思考方式:

public interface Map
{
        class Entry
        {

        }
}

Map.Entry<K,V>这里面存的是键值对的映射关系 把键值对的映射关系封装成一个类

Entry反映的是键值关系 里面保存的是键值对 所以里面要注明K和V的类型
Set<Map.Entry<K,V>> → 这里的Map.Entry<K,V>相当于Student 也是一个类而已
方法:
K→getKey() 返回与此项对应的键
V→getValue() 返回与此项对应的值
Set<Map,Entry<K,V>>→entrySet() 返回此映射中包含的映射关系的Set视图
返回map中键值对的映射关系 这个键值对的映射关系由Set保存

步骤:
1、调用map集合方法中的entrySet() 将集合中的映射关系对象存储到set集合中
2、迭代set集合
3、获取set集合中的映射关系对象元素
4、通过映射对象方法getKey()和getValue()来获取键值对

例:

Map<String,Integer> map=new HashMap<String,Integer>();

        map.put("aaa",1);
        map.put("bbb",2);
        map.put("ccc",99999);
        map.put("ccc",3);

Set<Map.Entry<String,Integer>> mySet=map.entrySet();//调用entrySet()方法获得集合中的全部的键和值

        遍历方法一、用迭代器遍历★
        Iterator<Map.Entry<String,Integer>> it=mySet.iterator();//创建迭代器
        while (it.hasNext())
        {
            Map.Entry<String,Integer> myEntry=it.next();
            System.out.println("Key="+myEntry.getKey()+" Value="+myEntry.getValue());//这里的每个myEntry都是一组key键和value值
        }

        //遍历方法二、用增强for循环遍历★
        for (Map.Entry<String,Integer> myEntry:mySet)
        {
            System.out.println("Key="+myEntry.getKey()+" Value="+myEntry.getValue());//这里的每个myEntry都是一组key键和value值
        }
发布了13 篇原创文章 · 获赞 0 · 访问量 107

猜你喜欢

转载自blog.csdn.net/Piconjo/article/details/104576259