• 集合、Iterator迭代器、增强for循环、泛型、List接口、Set接口


    1、集合:

    集合是java中提供的一种容器,可以用来存储多个数据。

    集合和数组的区别:数组的长度是固定的。集合的长度是可变的。集合中存储的元素必须是引用类型数据

    (1)ArrayList 集合存储元素并遍历

    练习一:ArrayList集合存储5int类型元素

    import java.util.ArrayList;
    public class Demo01 {
        public static void main(String[] args) {
            ArrayList<Integer> list=new ArrayList<Integer>();
            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);
            list.add(5);
            for(int i=0;i<list.size();i++){
                System.out.println(list.get(i));
            }
        }
    
    }

    练习二:ArrayList集合存储5Person类型元素

    package demo03;
    
    public class Person {
        String name;
    
        public Person(String name) {//================================构造方法传参
            super();
            this.name = name;
        }
    
        @Override
        public String toString() {//==================================重写toString方法
            return   name ;
        }
        
    }
    package demo03;
    
    import java.util.ArrayList;
    public class Demo01  {
        public static void main(String[] args) {
            ArrayList<Person> list=new ArrayList<Person>();
            list.add(new Person("张三"));
            list.add(new Person("李四"));
            list.add(new Person("王五"));
            list.add(new Person("赵六"));
            list.add(new Person("孙七"));
            for(int i=0;i<list.size();i++){
    
                System.out.print(list.get(i)+" ");
            }
        }
    
    }

     

    (2)ArrayList集合的继承实现关系

    ArrayList类继承了抽象类AbstractList同时实现接口List,而List接口又继承了Collection接口。Collection接口为最顶层集合接口了

    public interface List extends Collection {//==========List接口继承了Collection接口
    }
    public class ArrayList extends AbstractList implements List{
    }

    我们在使用ArrayList类时,该类已经把所有抽象方法进行了重写。那么,实现Collection接口的所有子类都会进行方法重写。

    Collection接口常用的子接口有:List接口、Set接口

    List接口常用的子类有:ArrayList类、LinkedList

    Set接口常用的子类有:HashSet类、LinkedHashSet

    图shi:

    Collection接口是集合中的顶层接口,因此他中的所有的子类功能都可以使用。

    一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

    ArrayList是允许重复和有序的,set是不许重复和无序的

    Collection 表示一组对象,这些对象也称为 collection 的元素。

    Collection接口的基本方法:

    add():bollean类型,确保此Collection包含指定的元素,基本无法使用,

    clear():移除此Collection中的所有的元素

    contains():boolean类型,如果此Collection包含指定的元素,包含则返回true,反之返回false

     size():int类型,返回此Collection中的元素数

     toArray():将集合转成数组

    这些基本方法都得通过方法重写后才能使用,要不没有意义,都是通过new ArrayList重写

    格式1:

    Collection<String> col=new ArrayList<String>();String代表了元素类型,col是变量名:这样创建的集合,只能存储<>中指定的元素类型,该方式为常用方式

     格式2:

    Collection col=new ArrayList();col是变量名,这样创建的集合,集合的元素类型默认为Object类型,即任何类型的元素都可以存储。

     Collection接口中的方法的演示:

    package demo06Collectionmethod;
    
    import java.util.ArrayList;
    import java.util.Collection;
    
    public class Demo01 {
    
        public static void main(String[] args) {
            Collection col=new ArrayList();
            col.add("abc");//add()方法是重写后的add方法
            col.add("b");
            col.add("def");
            System.out.println(col);
            System.out.println(col.toString());
            //2,从集合中删除元素。remove(Object o)方法
            col.remove("b");
            //删除后,集合元素为[abc, def]
            //3,判断集合中是否包含指定元素。contains(Object o)方法
            System.out.println(col.contains("abc"));
            //4,获取集合元素个数。size()方法
            System.out.println(col.size());
            //5,返回包含集合中所有元素的数组。toArray()方法
            Object[] array = col.toArray();
            for(Object bb:array){
                System.out.println(bb);
            }
            
            //数组中的元素为{"abc", "def"}
            //6,清除集合元素。remove()方法
            //col.clear();
            //清空后,集合元素为[],代表没有元素
    
        }
    
    }

     2、Iterator迭代器

     (1)Iterator迭代器介绍:

    迭代:

    Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

    集合中把这种取元素的方式描述在Iterator接口中

    Iterator接口的常用方法:

    hasNext():boolean类型,判断集合是否有下一个元素可以迭代,如果集合中有元素,可以迭代,则返回true,反之返回false

    Next():返回下一个迭代元素

    Collection接口描述了一个抽象方法iterator方法,所有Collection子类都实现了这个方法,并且有自己的迭代形式。

    Collection接口有一个Iteratoral超级接口,里面有一个方法,来获取 Iterator对象

     iterator():返回在此Collection的元素上进行迭代的迭代器

    格式:

    Collection<String> coll = new ArrayList<String>();

     

    //2.获取容器的迭代器对象。通过iterator方法。

     

    Iterator it = coll.iterator();

     

    用法实例:

    package demo05;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class Demo01 {
    
        public static void main(String[] args) {
            Collection<String> col=new ArrayList<String>();
            col.add("a");col.add("b");
            col.add("c");col.add("d");
            col.add("e");col.add("f");
            Iterator it=col.iterator();
            while(it.hasNext()){
                System.out.println(it.next());
            }
    
        }
    
    }

    集合元素的向下转型

    集合中可以存储任何对象,存放进去的数据都成了Object

     注意:

    集合中存储其实都是对象的地址。

    集合中可以存储基本数值因为出现了基本类型包装类,它提供了自动装箱操作(基本类型à对象),这样,集合中的元素就是基本数值的包装类对象。

    存储时提升了Object。取出时要使用元素的特有内容,必须向下转型。

    String str = (String) it.next();

        System.out.println(str.length());

    注意:

    Iterator接口也可以使用<>来控制迭代元素的类型的。

    Collection<String> coll = new ArrayList<String>();
    
    coll.add("abc");
    
    coll.add("aabbcc");
    
    coll.add("cat");
    
    Iterator<String> it = coll.iterator();
    
    while (it.hasNext()) {
    
        String str = it.next();
    
    //当使用Iterator<String>控制元素类型后,就不需要强转了。获取到的元素直接就是String类型
    
        System.out.println(str.length());
    
    }

    迭代器使用示例:

    package demo01;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class Demo01 {
    
        public static void main(String[] args) {    
            Demo01 p=new Demo01();
            p.method();
            p.method02();
            p.method03();
        }
        public void method(){
            Collection<String> col=new ArrayList<String>();
            col.add("zbc");
            col.add("bhjbh");
            col.add("vsnaj");
            col.add("abvij");
            //获取迭代器对象
            Iterator<String> it=col.iterator();
            //迭代器进行迭代
            while(it.hasNext()){
                System.out.println(it.next());
            }
        }
        public static void method02(){
            Collection<Person> col=new ArrayList<Person>();
            col.add(new Person("zhangsan",12));
            col.add(new Person("lisi",14));
            Iterator<Person> it=col.iterator();
            while(it.hasNext()){
                System.out.println(it.next());
            }
        }
        public static void method03(){
            Collection col=new ArrayList();
            col.add("111");
            col.add(123);
            //获取迭代器对象
            Iterator it=col.iterator();
            while(it.hasNext()){
                Object obj=it.next();//it.next()是匿名函数,只能用一次,先定住it,next类型object,定以后可以重复用
                if(obj instanceof String){
                    String s=(String)it.next();//向下转型
                    System.out.println(s);
                }
                
            }
        }
    
    }

    3、增强for循环

    (1)

    增强for循环是

    专门用来遍历数组和集合的

    部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

    格式:

    for(数据类型     变量名:容器){   }

    它用于遍历Collection接口和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。

    package demo02;
    
    import java.util.ArrayList;
    
    public class Demo03 {
    
        public static void main(String[] args) {
            //遍历数组
            String[] arr={"a","d","f"};
            for(String str:arr){
                System.out.println(str);
                System.out.println(str.length());    
            }
            //遍历集合
            ArrayList<Integer> list=new ArrayList<Integer>();
            list.add(123);
            list.add(1234);
            list.add(34);
            for(Integer s:list){
                System.out.println(s);
            }
        }
    
    }

    注意:

    增强for循环和老式的for循环有什么区别?

    增强for循环必须有被遍历的目标。目标只能是Collection或者是数组。

    建议:遍历数组时,如果仅为遍历,可以使用增强for如果要对数组的元素进行 操作,使用老式for循环可以通过下标操作。

    增强for底层就是Iterator迭代器

    4、泛型

    (1)泛型的引入

    注意:

    集合就要添加泛型。泛型不进class文件,class文件里没有泛型一说,泛型和注释都不进class文件

    集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。

    集合中什么类型的元素都可以存储。导致取出时,如果出现强转就会引发运行时 ClassCastException。怎么来解决这个问题呢?使用集合时,必须明确集合中元素的类型。这种方式称为:泛型。

    (2)泛型的定义与使用

    含有泛型的类

    定义格式:

    修饰符 class 类名<代表泛型的变量> { }

    class ArrayList<E>{
    public boolean add(E e){ }
        public E get(int index){ }
    }

    创建对象时确定泛型的类型

    格式:

    例如:ArrayList<String> list = new ArrayList<String>();

    ArrayList<Integer> list = new ArrayList<Integer>();此时,变量E的值就是Integer类型

    (3)使用泛型的好处

    将运行时期的ClassCastException(类型转换异常),转移到了编译时期变成了编译失败。

    5、List接口

     (1)List接口的概述:

    在Collection中有两个接口:List和Set接口,

    List接口可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素

    List接口:

    它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。

    l 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。

    集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

    List接口的常用子类有:

    l ArrayList集合

    l LinkedList集合

     (2)List接口中的常用方法:

    l 增加元素方法

     add(Object e):向集合末尾处,添加指定的元素

     add(int index, Object e):向集合指定索引处,添加指定的元素,原有元素依次后移

    l 删除元素删除

     remove(Object e):将指定元素对象,从集合中删除,返回值为被删除的元素

     remove(int index):将指定索引处的元素,从集合中删除,返回值为被删除的元素

    l 替换元素方法

     set(int index, Object e):将指定索引处的元素,替换成指定的元素,返回值为替换前的元素

    l 查询元素方法

     get(int index):获取指定索引处的元素,并返回该元素

    package demo03;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Demo01 {
    
        public static void main(String[] args) {
            List<String> list=new ArrayList<String>();
            list.add("哆啦a梦");//向集合尾部添加元素
            list.add("大熊");//向集合尾部添加元素
            //指定位置添加指定元素
            list.add(1,"静香");
            /*for(int i=0;i<list.size();i++){
                System.out.println(list.get(i));
            }*/
            String str = list.remove(2);
            //修改指定下标的元素值
            list.set(1, "胖虎");
            System.out.println(str);
            //获取指定下标的值
            for(int i=0;i<list.size();i++){
                System.out.println(list.get(i));
            }
        }
    
    }

     (3)Iterator的并发修改异常

    list集合迭代元素中,对元素进行判断,一旦条件满足就添加一个新元素

    public class IteratorDemo {
    //在list集合迭代元素中,对元素进行判断,一旦条件满足就添加一个新元素
        public static void main(String[] args) {
            //创建List集合
            List<String> list = new ArrayList<String>();
            //给集合中添加元素
            list.add("abc1");
            list.add("abc2");
            list.add("abc3");
            list.add("abc4");
            //迭代集合,当有元素为"abc2"时,集合加入新元素"a"
            Iterator<String> it = list.iterator();
            while(it.hasNext()){
                String str = it.next();
                //判断取出的元素是否是"abc2",是就添加一个新元素
                if("abc2".equals(str)){
                    list.add("a");// 该操作会导致程序出错
                }
            }
            //打印容器中的元素
            System.out.println(list);
        }
    }

     运行后出现

    java.util.ConcurrentModificationException========================并发修改异常

     如何解决这个问题:

    在迭代时,不要使用集合的方法操作元素。

     (4)List集合存储元素的结构:

    数据存储的常用结构有:堆栈、队列、数组、链表。

     特点:

    堆栈:先进后出

    队列:先进先出

    数组:查找快,增删慢,ArrayList集合数据存储的结构是数组结构

    链表:查找满增删快,   LinkedList集合数据存储的结构是链表结构

     链表结构:LinkedList查找慢,增删快,因此其提供了很多增、删的方法

     addFirst()将指定元素插入表头

    addLast()    将指定元素 插入 最后

    getFirst()返回第一个元素

    getLast()返回最后一个元素

    removeFirst()移除并返回第一个元素

    removeLast()移除并返回最后一个元素

    isEmpty():boolean类型,列表不含数据返回true

    6、Set接口

     (1)概述

    List中是可以存放重复元素的,Set接口,它里面的集合,所存储的元素就是不重复的。

     Set集合通过元素的equals方法,来判断是否为重复元素, 

     (2)HashSet集合

    HashSet集合不能保证的迭代顺序与元素存储顺序相同。

     HashSet集合实现Set接口,由哈希表支持

    什么是哈希表呢? 

    哈希表底层,使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,

    当需要把这些对象给数组中存放时,那么会根据这些对象的特有数据结合相应的算法,计算出这个对

    象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。

    当向哈希表中存放元素时,需要根据元素的特有数据结合相应的算法,这个算法其实就是Object类中的hashCode方法

    由于任何对象都是Object类的子类,所以任何对象有拥有这个方法。即就是在给哈希表中存放对象时,会调用对象的hashCode方法,算出对象在表中的存放位置,这里需要注意,如果两个对象hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中。 

    HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

    HashSet中存储JavaAPI中提供的类型元素时,不需要重写元素的hashCode和equals方法,因为这两个方法,在JavaAPI的每个类中已经重写完毕,如String类、Integer类等。

    如:

    package demo05;
    
    import java.util.HashSet;
    
    public class Demo {
    
        public static void main(String[] args) {
            Object obj=new Object();
            System.out.println(obj.hashCode());
            HashSet<String> set=new HashSet<String>();
            set.add("abc");
            set.add("bcd");
            set.add("ace");
            set.add("abc");
            for(String s:set){
                System.out.println(s);
                System.out.println(s.hashCode());
                
            }
            
        }
    
    }

    总结:

    哈希不能存储重复元素的原因:

    set集合存元素的时候,先调用该元素类型的hashcode方法计算哈希值,先去数组中看下有没有重复的哈希值,如果没有,则添加上,如果有,则继续调用该元素类型的equals方法判断内容,如果内容相同,则丢掉(其实是覆盖掉),如果内容不同,则添加上

    (3) HashSet存储自定义类型元素

    HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法建立自己的比较方式,才能保证HashSet集合中的对象唯一

    package demo05;
    
    public class Person {
        String name;
        int age;
        
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", 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;
            Person other = (Person) 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;
        }
    }
    package demo05;
    
    import java.util.HashSet;
    
    public class Demo03 {
    
        public static void main(String[] args) {
            HashSet<Person> set=new HashSet<Person>();
            set.add(new Person("a",18));
            set.add(new Person("b",17));
            set.add(new Person("c",19));
            set.add(new Person("a",18));
            for(Person p:set){
                System.out.println(p);
            }
    
        }
    
    }

    (4) LinkedHashSet介绍

    HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序

    HashSet下面有一个子类LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。

    public class LinkedHashSetDemo {
        public static void main(String[] args) {
            Set<String> set = new LinkedHashSet<String>();
            set.add("bbb");
            set.add("aaa");
            set.add("abc");
            set.add("bbc");
    Iterator it = set.iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
    }

    输出结果如下,LinkedHashSet集合保证元素的存入和取出的顺序:

    bbb

    aaa

    abc

    bbc

  • 相关阅读:
    html5--6-10 CSS选择器7--伪类选择器
    html5--6-9 CSS选择器6--伪类选择器
    html5--6-8 CSS选择器5
    避开美国全球监控阴影下的问题手机,寻求新伙伴
    DMA过程分析
    混淆
    Missile:双状态DP
    Java抓取网页数据(原网页+Javascript返回数据)
    Binders 与 Window Tokens(窗体令牌)
    编程之美2013 初赛一 A
  • 原文地址:https://www.cnblogs.com/yang1182/p/9755420.html
Copyright © 2020-2023  润新知