java.util.Collection List与其子类 Set与其子类

Posted guoDaXia的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java.util.Collection List与其子类 Set与其子类相关的知识,希望对你有一定的参考价值。

package com.Collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Study01 {
    public static void main(String[] args){
        Collection<String> c=new ArrayList<String>();
        Collection<String> c2=new ArrayList<String>();
        c.add("I");
        c.add("am");
        c.add("guo");
        
        c2.add("he");
        c2.add("ha");
        /*System.out.println(c);//增的结果
        c.remove("I");
        System.out.println(c);//删的结果
        c.addAll(c2);
        System.out.println(c);//增一个集合所有元素
        c.removeAll(c2);
        System.out.println(c);//删除另一个集合中存在的元素
        c.clear();
        System.out.println(c);//clear暴力删除所有
        */
        System.out.println(c);
        System.out.println(c.contains("am"));//包含?
        System.out.println(c2);
        System.out.println(c.containsAll(c2));//不包含c2中所有
        
        /*System.out.println(c.retainAll(c2));//取交集,用交集替换原集合的元素。只要改变了集合返回true
        System.out.println(c);*/
        /*c2.add("am");
        System.out.println(c.retainAll(c2));
        System.out.println(c);*/
        
        //遍历集合
        Object[] objs=c.toArray();
        for(int i=0;i<objs.length;i++){
            System.out.print(objs[i]+"\\t");
        }
        //
        System.out.println();
        Iterator<String> it=c.iterator();
        while(it.hasNext()){
            String o=it.next();
            System.out.print(o+"\\t");
        }
    }
}
/*
 * 引出集合:
 *         java是面向对象的语言,对象使用的话需要一个容器装,我们前面有StringBuffer和数组两种容器,但都不太适合。因为StringBuffer存储的是字符串,而数组是不可变长的
 * 数组和集合的比较:
 *         数组不可变长,一个数组只能存储一种类型,,集合只能存储引用数据类型
 * Collection 集合
 *   表示一组对象,这些对象也称为collection的元素
 * 既然是操作一组对象,所以引出一些方法:
 *     增加:
 *         boolean add(Object obj)
 *         boolean addAll(Collection c)
 *     删除:
 *         remove(Obj o);
 *         removeAll(Collection c) 移除与c的交集,移除了一个就返回true
 *         clear() 删除collection中所有元素
 *         boolean retainAll(Collection c) 此集合保留与c的交集
 *     查找:
 *     通过遍历可以实现查找:
 *         iterator() 返回在此collection上的迭代器
 *         Object[] toArray() 返回包含此collection中所有元素的数组
 *         <T> T[] toArray() 返回包含此collection中所有元素的数组,并且数组类型为指定的类型
 *     判断集合中是否包含指定元素
 *         contains(Object o) 如果collection包含指定元素,则返回true
 *         containsAll(Collection c) 如果包含c中所有的元素则返回true
 *     基本方法:
 *         size() 返回集合大小
 *         isEmpty() 是否为空
 *         hashCode()
 *         equals(Object o)
 * 
 * 关于迭代器:
 *         迭代是依托于集合的,它的内部实现其实是在各种集合类中的内部类,个人感觉有点像是集合元素的一种特殊形式的复制或者其他
 *         两个方法:
 *             boolean hasNext()如果仍有元素可以迭代,则返回 true。
 *            Object next()返回迭代的下一个元素。 
 *     
 *     
 */
View Code
package com.List;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Study01 {
    public static void main(String[] args) {
        List<String> l=new ArrayList<String>();
        l.add("guo");
        l.add("da");
        l.add("xia");
        System.out.println(l);
        l.add(0, "ni");
        System.out.println(l);
        
        List<String> l2=new ArrayList<String>();
        l2.add("hao");
        l2.add("ma");
        l.addAll(1,l2);
        System.out.println(l);
        System.out.println(l.get(2));
        System.out.println(l.indexOf("guo"));
        System.out.println("");
        l.set(5,"guo");//set是改变的方法。改变的下标必须拥有元素
        System.out.println(l);
        System.out.println(l.lastIndexOf("guo"));
        
        List<String> l3=l.subList(2, 4);
        System.out.println(l3);
        
        for(int i=0;i<l.size();i++){
            String s= l.get(i);
            System.out.print(s+"\\t");
        }
        
        ListIterator<String> it=l.listIterator();
        System.out.println();
        while(it.hasNext()){
            String s= it.next();
            System.out.print(s+"\\t");
        }
        System.out.println();
        while(it.hasPrevious()){//逆序输出
            String s= it.previous();
            System.out.print(s+"\\t");
        }
        
        System.out.println();
        //在遍历的中途中增加操作
        while(it.hasNext()){
            String s= it.next();
            if(s.equals("ma")){
                //ConcurrentModificationException 并发修改异常 
                //l.add("hi"); 不能在迭代的时候直接使用集合进行修改,但在这里可以使用迭代器的方法进行操作,在该下标的后一位增加。此次迭代器中不会出现
                it.add("hi");
            }
            System.out.print(s+"\\t");
        }
        System.out.println("\\n"+l);
        
        for(int i=0;i<l.size();i++){
            String s= l.get(i);
            if(s.equals("ma")){
                l.add("haha");//for循环过程中增加,遍历出来所有元素
            }
            System.out.print(s+"\\t");
        }
        System.out.println("\\n"+l);
    }
    /*
     * 
     * 对并发修改异常就是这两种方式处理:
     * 一是使用迭代器对象修改
     * 二是使用get()和size()的结合操作
     */
}
/*
 * List 有序的collection,也称为序列。允许重复。
 *     有序:指的是存进去和取出来的顺序一致
 * 存取有序,所以就应该是有下标的说法
 * 
 * 新增方法:
 *     add(int index Object obj) :将元素插入到集合指定下标的位置,之前的位置和后面的元素全部向后推移一位
 *     addAll(int index,Collection)
 *  get(int index) 获取指定索引下的元素
 *  indexOf(Object obj) 返回指定元素在集合中的下标,不存在则返回-1
 *  lastIndexOf(Object obj) 返回指定元素在集合中最后一次出现的下标
 *  remove(int index)
 *  set(int index,Object obj) 将集合中指定下标的元素更改为obj,返回集合中原有的元素
 *  subList(int formIndex,int toIndex)和String的substring类似,返回截取版的数组
 *  
 *  两个特有遍历方法:
 *      listIterator() 返回此列表元素的迭代器,注意,是列表专用
 *          这个迭代器的特点:可以实现逆向遍历。
 *      ListIterator
 *          add(Object obj)将指定的元素插入列表,插入的位置是当前指针位置
 *          int nextIndex() 返回对next后续元素调用所返回元素的索引
 *          boolean hasPrevious() 判断将迭代器指针往前移一位是否存在元素
 *          previous() 迭代器指针前移一位,返回列表的前一个元素
 *          int previousIndex()
 *          remove() 从列表中移除又next或者previous返回的最后一个元素
 *          set(Object obj) 用指定元素替换next或者previous返回的最后一个元素
 *  
 *  ListIterator迭代和使用get()和size()结合迭代是List集合的两个特点遍历
 *      
 *  
 *  
 * 
 */ 
View Code
package com.ArrayList_LinkedList_Vector;

import java.util.ArrayList;
import java.util.LinkedList;

public class Study01 {
    public static void main(String[] args) {
        ArrayList<String> al=new ArrayList<String>();
        al.add("ni");
        al.add("hao");
        al.add("wo");
        al.add("men");
        al.add("zai");
        System.out.println(al);
        
        LinkedList<String> ll=new LinkedList<String>();
        ll.add("c");
        ll.addFirst("a");    
        ll.addLast("b");
        System.out.println(ll);
        System.out.println(ll.peek());
        System.out.println(ll.poll());
        System.out.println(ll);
    }
}
/*
 * ArrayList
 *     底层数组,线程不同步,效率快,安全低
 * 
 * 构造方法:
 *     ArrayList() 初始容量为10的空列表
 *     ArrayList(Collection c) 构造一个包含指定元素的集合的对象
 *     ArrayList(int initialCapacity) 构造一个具有指定初始化容量的空列表
 * 
 * 新增方法:
 *     ensureCapacity(int minCapacity) 增加此ArrayList的容量
 *     //removeRange(int fromIndex,int toIndex) 删除指定索引区间的元素  这个方法在JDK1.6中是受保护的,不知道为什么用不了现在。
 *     trimToSize() 将此ArrayList实际的容量调整为列表的当前大小
 *     
 */

/*
 * LinkedList
 *     List接口的链接列表实现。不是同步的  链接链表特点:增删快,查询慢  不同步特点:效率快
 * 新增方法:
 *     addFirst(Object obj)
 *     addLast(Object obj)
 *     descendingIterator() 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器
 *     Object element()获取此列表第一个元素
 *     offer(Object obj)将指定元素添加到列表的末尾
 *     offerFirst(E e)
 *     peek()获取第一个元素
 *     peekLast()获取最后一个元素
 *     pool()获取第一个元素同时移除第一个元素
 *     poolFirst()
 *     poolLast()
 *     set()
 * 
 */

/*
 *Vector
 *    底层数组,查询快,增删慢  线程安全
 *    和ArrayList几乎一样,不写太多
 */

/*
 * 三个集合的选择:
 *         数组底层的:查询快,增删慢  ArrayList Vector
 *             线程安全的:速率慢,安全性高:Vector 反之,安全性较低,速率高:ArrayList
 *         链表结构:查询慢,增删快 LinkedList
 *         
 */
View Code
package com.Set;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

/*
 * Set接口
 *  实现Collection接口,无序,唯一
 *  不是真的无序,是按照一种特殊的算法存储的,但不是11排列这种顺序
 * 
 * HashSet
 *     底层是哈希表,哈希表示元素为链表的数组结构
 *    hashSet唯一,所以添加不进重复元素,观察其源码,发现其底层是hashMap,其add方法和hashCode()和equals()方法有关
 *    只有当两个元素的hash值相等,并且equals方法为true的时候才会直接跳过这个添加以保证hashSet集合的唯一性
 *
 *    可以发现,前面好像是有唯一性,使用对象的时候就失效了,这是为什么呢?
 *    因为String对象自动重写了hashCode和equals方法,比较的是值。而你的Student对象的两个方法都没有重写,比较的就
 *  是Object对象的hashCode方法得到的值,也就是地址值的特殊表示。所以,你只有将对象的equals和hashCode方法重写后才能
 *  使得hashSet的唯一性生效
 *  此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
 *  LinkedHashSet
 *      具有可预知的迭代顺序,LinkedHashSet的子类
 *      底层是哈希表和链表
 *      哈希表保证元素唯一性
 *      链表保证元素有序(存储一致)
 */
/*
 * 首先比较哈希值是否相同
 *     相同: 继续执行equals
 *             返回true:元素重复了,不添加
 *             返回false:可以添加
 * 不同:也可以添加
 */
public class HashSetAndLinkedHashSet {
    public static void main(String[] args) {
        LinkedHashSet<String> hs=new LinkedHashSet<String>();
        hs.add("hello");
        hs.add("java");
        hs.add("world");
        hs.add("java");
        hs.add("world");
        
        for(String s:hs){
            System.out.println(s);
        }
    }
    public void test01(){
        Set<String> s=new HashSet<String>();
        s.add("java");
        s.add("hello");
        s.add("world");
        s.add("java");
        s.add("hello");
        
        for(String ss:s){
            System.out.println(ss);
        }
        
        Set<Student> s1=new HashSet<Student>();
        s1.add(new Student("林青霞",27));
        s1.add(new Student("范冰冰",30));
        s1.add(new Student("林青霞",27));
        s1.add(new Student("柳岩",25));
        s1.add(new Student("林青霞",27));
        
        for(Student ss:s1){
            System.out.println(ss);
        }
    }
}

package com.Set;

public class Student implements Comparable<Student>{
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    public Student() {
        super();
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }
    
    @Override
    public int compareTo(Student o) {
        //两个Student对象的比较方法
        //我这里定义它先根据年龄比较,然后根据姓名比较
        
        if(this.equals(o)){
            return 0;
        }else if(this.getAge()==o.getAge()){
            return this.getName().compareTo(o.getName());
        }else{
            return this.getAge()-o.getAge();
        }
    }
    
    
}

package com.Set;

import java.util.Comparator;
import java.util.TreeSet;

/*
 * TreeSet:能够对元素按照某种规律排序
 * TreeSet的排序方式和它的比较方式有关
 * 
 * 底层是红黑树结构!
 * 
 * 排序有两种:
 *     A:自然排序 
 *     B:比较器排序
 * 
 * 构造方法:
 *     TreeSet() 构造新的空set,根据自然顺序进行排序
 *     TreeSet(Comparator<? extends E> o) 构建一个空的TreeSet,它根据比较器进行排序
 * TreeSet集合的特点:
 *     排序和唯一
 *         唯一:根据比较的值是否为0
 *         排序:数的存储方式和取出方式
 * 
 * 自然排序接口:Comparable 在基本数据类型和常用类型都有它的实现,它表现在类型的compareTo方法上:
 *     Number型比较的是数值的大小,String比较的是内容的哈希吗,boolean类型真比假为正,假比真为负,其他为0,char类型比较的是Ascill码
 * 如果你使用的是自定义对象类型,就必须实现Comparable接口,才能使用自然排序。
 * 自然排序,就是依据对象的compareTo方法进行排序
 * 
 * 比较器排序
 *     什么是比较器?
 * 比较器是一个用来比较两个同类型对象的对象,比较器实现了Comparator接口,在compare方法中确定如何比较或者说是比较结果。
 * 
 * 使用比较器就是在构造方法中加入比较器。
 * 
 * 使用比较器与自然排序相比:
 *     自然排序的比较方式是定义在对象里的,所以每一个同类型的对象的比较方法都是确定的。而比较器是独立的一个对象,在需要这样比较的时候调用特定的比较器就好。
 */
public class TreeSetStudy {
    public static void main(String[] args) {
        //我们前面使用了自然排序,那么怎么使用比较器排序呢?
        TreeSet<Student> ts=new TreeSet<Student>(new comparator02());
        ts.add(new Student("林青霞",27));
        ts.add(new Student("刘亦菲",18));
        ts.add(new Student("苏有朋",30));
        ts.add(new Student("刘诗诗",18));
        
        for(Student i:ts){
            System.out.println(i);
        }
    }
    public  void test01(){
        TreeSet<Integer> ts=new TreeSet<Integer>();
        ts.add(18);
        ts.add(28);
        ts.add(22);
        ts.add(18);
        ts.add(19);
        
        for(int i:ts){
            System.out.println(i);
        }
    }
    
    public  void test02(){
        //自然排序
        TreeSet<String> ts=new TreeSet<String>();
        ts.add("hi");
        ts.add("nice");
        ts.add("to");
        ts.add("meet");
        ts.add("you");
        
        for(String s:ts){
            System.out.println(s);
        }
    }
    
    public void test03(){
        //这样报错:com.Set.Student cannot be cast to java.lang.Comparable
        //因为这样默认使用的是自然排序,但是Student并没有实现Comparable接口,没有自然比较方法,接下来我们让Student实现Comparable接口试试
        TreeSet<Student> ts=new TreeSet<Student>();
        ts.add(new Student("林青霞",27));
        ts.add(new Student("刘亦菲",18));
        ts.add(new Student("苏有朋",30));
        ts.add(new Student("刘诗诗",18));
        
        for(Student i:ts){
            System.out.println(i);
        }
    }
    
    public void test04(){
        TreeSet<Integer> ts=new TreeSet<Integer>(new comparator01());
        ts.add(18);
        ts.add(28);
        ts.add(22);
        ts.add(18);
        ts.add(19);
        
        for(int i:ts){
            System.out.println(i);
        }
    }
}
class comparator01 implements Comparator<Integer>{


    @Override
    public int compare(Integer o1, Integer o2) {
        int i=o2-o1;
        return i;
    }
    
}

class comparator02 implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        if(o1.getAge()!=o2.getAge()){
            return o2.getAge()-o1.getAge();//年龄从大到小排序
        }else{
            return o1.getName().compareTo(o2.getName());
        }
    }

    
}


package com.Set;

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

/*
 * ctrl+ shift+ o  自动导包
 * alt+ shift +s+o 有参构造
 * alt+ shift +s+c 无参构造
 * alt+ shift +s+r 封装
 */
public class TreeSetDemo {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        //内部类实现比较
        TreeSet<Student01> ts=new TreeSet<Student01>(new Comparator<Student01>(){

            @Override
            public int compare(Student01 o1, Student01 o2) {
                //总分从高到低
                int num=o2.getSum()-o1.getSum();
                //总分相同的语文不一定相同
                int num2=num==0?o1.getChinese()-o2.getChinese():num;
                //数学不一定相同
                int num3=num2==0?o1.getMath()-o2.getMath():num2;
                //英语不一定相同
                int num4=num3==0?o1.getEnglish()-o2.getEnglish():num3;
                //姓名不一定相同
                int num5=num4==0?o1.getName().compareTo(o2.getName()):num4;
                return num5;
            }            
        });
        
        for(int x=1;x<=5;x++){
            System.out.println("请输入第"+x+"个学生的姓名:");
            String name=sc.nextLine();
            System.out.println("请输入第"+x+"个学生的语文成绩:");
            String chineseString=sc.nextLine();
            System.out.println("请输入第"+x+"个学生的数学成绩:");
            String mathString=sc.nextLine();
            System.out.println("请输入第"+x+"个学生的英语成绩:");
            String englishString=sc.nextLine();
            
            Student01 s=new Student01();
            s.setName(name);
            s.setChinese(Integer.parseInt(chineseString));
            s.setMath(Integer.parseInt(mathString));
            s.setEnglish(Integer.parseInt(englishString));
            ts.add(s);
        }    
        System.out.println("学生信息录入完毕");
        System.out.println("学生信息从高到低顺序如下:");
        System.out.println("姓名\\t语文成绩\\t数学成绩\\t英语成绩");
        
        for(Student01 s:ts){
            System.out.println(s.getName()+"\\t"+s.getChinese()+"\\t"+s.getMath()+"\\t"+s.getEnglish());
        }
    }
}
class Student01{
    private String name;
    private int chinese;
    private int math;
    private int english;
    public Student01(String name, int chinese, int math, int english) {
        super();
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }
    public Student01() {
        super();
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getChinese() {
        return chinese;
    }
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }
    public int getMath() {
        return math;
    }
    public void setMath(int math) {
        this.math = math;
    }
    public int getEnglish() {
        return english;
    }
    public void setEnglish(int english) {
        this.english = english;
    }
    
    public int getSum(){
        return getChinese()+getMath()+getEnglish();
    }
    
    
    
}
View Code

 

以上是关于java.util.Collection List与其子类 Set与其子类的主要内容,如果未能解决你的问题,请参考以下文章

java----数据结构与算法----JavaAPI:java.util.Collection接口

java源码 -- java.util.Collection

java.util.Collection 为啥不实现新的 Stream 接口?

java.util.Collection List与其子类 Set与其子类

java.util (Collection接口和Map接口)

如何正确实现java.util.Collection类?