java-集合老大哥-Collection

集合老大哥-Collection

集合,是java提供的一种容器,可以用来存储多个数据,数组同样是容器,但是两者有区别:

  1. 数组的长度是固定的,而集合的长度是可变的
  2. 集合中存储的元素必须是引用类型的数据

学会使用集合:能够使用集合来存储对象,能够遍历集合取出对象,能够掌握不同集合的特点,如List集合(有序可重复)Set集合(无序不可重复)等

集合的使用(两个例子)
例一:集合存储Person类对象

package 集合;
//Person类
public class Person {
    private String name;
    private int age;
    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    }
}
package 集合;
import java.util.ArrayList;
public class Collection_Demo {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<Person>();
        list.add(new Person("张三",20));
        list.add(new Person("李四",22));
        list.add(new Person("王五",18));
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }
}

输出如下:

集合.Person@1540e19d
集合.Person@677327b6
集合.Person@14ae5a5

这是因为list中存储的是Person类的对象,get()方法打印的是对象,在java中打印对象会调用该类的toString()方法,若未重写该方法,打印的是对象在内存中的地址

重写Person类的toString()方法

package 集合;
public class Person {
    private String name;
    private int age;

    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

再次打印,观察输出,打印对象确实是调用toString()方法

Person{name='张三', age=20}
Person{name='李四', age=22}
Person{name='王五', age=18}

例二:集合存储基本类型(数值)

package 集合;
import java.util.ArrayList;
public class Collection_Demo {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(123);
        list.add(456);
        list.add(789);
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }
}

输出如下:

123
456
789

集合本身只能存储引用类型的数据(对象),但是java的自动装箱可以将基本类型转换为封装后的引用类型,如int -> Integer(int类型的数据封装为Integer的对象)

查看ArrayList类发现它继承了抽象类AbstractList,同时实现了接口List

public class ArrayList extends AbstractList implements List{}

而List接口又继承了Collection接口

interface List extends Collection {}

同理Set接口也继承了Collection接口

interface Set extends Collection {}

在集合框架中,Collection是爸爸,有俩出名的儿子List和Set
即Collecton接口常用的子接口有:List接口、Set接口
List和Set又都有比较出息的儿子们
List接口常用的子类有:ArrayList类、LinkedList类(有序可重复)
Set接口常用的子类有:HashSet类、LinkedHashSet类(无序不可重复)

通关集合,必须先搞定大BOSS:Collection
Collection接口中的方法,是集合中所有实现类必须拥有的方法,下面是Collection接口中经常使用的几个方法:

  1. add(E e)
  2. clear()
  3. contains(Object o)
  4. remove(Object o)
  5. toArray()
package 集合;
import java.util.ArrayList;
import java.util.Collection;
public class Collection_Demo {
    public static void main(String[] args) {
        function();
    }
    private static void function() {
        //接口多态的方式调用
        Collection<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        System.out.println(list);
        list.clear();
        System.out.println(list);

    }
}
//输出
//[one, two, three]
//[]

clear()方法:清空集合中的所有元素,但是集合本身依然存在,还可以继续添加元素,就像水杯倒水一样,水没了,但是杯子还在

package 集合;
import java.util.ArrayList;
import java.util.Collection;
public class Collection_Demo {
    public static void main(String[] args) {
        function();
    }
    private static void function() {
        //接口多态的方式调用
        Collection<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        boolean judge = list.contains("two");
        System.out.println(judge);
    }
}
//输出
//true

contains()方法:如果集合包含指定元素则返回true,否则返回false

package 集合;
import java.util.ArrayList;
import java.util.Collection;
public class Collection_Demo {
    public static void main(String[] args) {
        function();
    }
    private static void function() {
        //接口多态的方式调用
        Collection<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("two");
        System.out.println(list);
        boolean judge = list.remove("two");//删除的是第一个two
        System.out.println(judge);
        System.out.println(list);
    }
}
//输出
//[one, two, three, two]
//true
//[one, three, two]

remove()方法:从这个集合中移除指定元素

package 集合;
import java.util.ArrayList;
import java.util.Collection;
public class Collection_Demo {
    public static void main(String[] args) {
        function();
    }
    private static void function() {
        //接口多态的方式调用
        Collection<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        //数组的长度不可变,但是集合的长度可以变
        Object[] objs = list.toArray();
        //java中长度的三种表现形式:数组.length属性,字符串.length()方法,集合.size()方法
        for(int i=0;i<objs.length;i++){
            System.out.println(objs[i]);
        }
    }
}
//输出
//one
//two
//three

toArray()方法:返回一个包含此集合中所有元素的数组,数组存储的数据类型是Object,因为集合可以存储任意类型对象

集合遍历-迭代器

java中提供了很多种集合,每种集合的底层的数据结构不同,例如ArrayList的底层是数组,LinkedList的底层是链表,虽然在存储时采用的存储方式不同,但是我们却不需要针对不同的存储方式来设计相应的遍历方法,因为无论使用哪种集合,我们都会有判断是否有元素以及取出里面的元素的动作,所以能够通过一种通用的方式来遍历集合:那就是迭代

迭代过程:在取元素之前先要判断集合中是否有元素,如果有,就把这个元素取出来,继续判断,如果还有,就再取出来,一直把集合中的所有元素全部取出

代码实现

package 集合;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Collection_Demo {
    public static void main(String[] args) {
        function();
    }
    private static void function() {
        //接口多态的方式调用
        Collection<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        //调用集合的iterator()方法,获取Iterator接口的实现类对象
        Iterator<String> it = list.iterator();
        //接口的实现类对象,调用hasNext()方法判断集合中是否有元素
        //boolean b= it.hasNext();
        //接口的实现类对象调用next()方法取出集合中的元素
        //String str = it.next();
        //System.out.println(str);//one

		//迭代是反复内容,推荐使用while循环实现,循环结束的条件, hasNext()返回了false
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}
//输出
//one
//two
//three

Tips:

  • 集合中存储的其实都是对象的地址,在jdk1.5版本以后可以存储基本类型了,因为出现了基本类型包装类,提供了自动装箱操作(基本类型 对象),集合中的元素就变成了基本类型的包装类对象
  • 集合不指定存储的数据类型时,则什么元素都可以存,参数是Object类型,存储时提升到Object,取出时要使用元素的特有内容,必须向下转型
Collection list = new ArrayList();
list.add("one");
list.add("two");
list.add("three");
Iterator it = list.iterator();
while(it.hasNext()){
	//需要打印每个字符串的长度,就要把迭代出来的对象转成String类型
	String str = (String)it.next();//String str=(String)obj;
    System.out.println(str.length());
}
  • 当使用Iterator控制元素类型后,就不需要强制转换了,因为获取到的元素直接就是String类型
Iterator<String> it = list.iterator();

增强for循环遍历

JDK1.5版本后,出现新的接口java.lang.Iterable
老大哥Collection继承Iterable
Iterable的作用:实现增强for循环
格式:

for(数据类型 变量名 : 数组或者集合){
	sop(变量);
}
  • 增强for循环遍历数组
String[] strs = {"one","two","three"};
for(String str : strs){
	System.out.println(str);
}
  • 增强for循环遍历集合
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("张三",20));
list.add(new Person("李四",22));
list.add(new Person("王五",18));
for(Person p : list){
	System.out.println(p);
}

增强for循环的优缺点:
优点: 代码少了,方便对容器遍历
缺点: 没有索引,不能改变容器里面的元素

泛型

jdk1.5 出现了新的安全机制,引入了泛型来保证程序的安全性
泛型:指明了集合中存储数据的类型<数据类型>

public class GenericDemo {
	public static void main(String[] args) {
		List list = new ArrayList();
        list.add("one");
        list.add("two");
        list.add(3);//由于集合没有做任何限定,任何类型都可以存放,相当于 Object obj=new Integer(3);
        
        Iterator it = list.iterator();
        while(it.hasNext()){
          	//需要打印每个字符串的长度,就要把迭代出来的对象转成String类型
          	String str = (String) it.next();//String str=(String)obj;
          	//编译时期仅检查语法错误,String是Object的儿子可以向下转型
          	//运行时期String str=(String)(new Integer(5))
          	//String与Integer没有父子关系所以转换失败
          	//程序在运行时发生了问题java.lang.ClassCastException
          	System.out.println(str.length());
        }
	}
}

使用泛型可以将运行时期的ClassCastException类型转换异常转移到编译时期,使编译失败,同时还可以避免类型的强制转换,如下

//使用泛型
public class GenericDemo {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        //list.add(3);//当集合明确类型后,存放类型不一致就会编译报错
                    
        //当使用Iterator<String>控制元素类型后,就不需要强制转换了,获取到的元素就是String类型
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
          	String str = it.next();
          	System.out.println(str.length());
        }
	}
}

泛型的通配符:泛型的通配,匹配所有的数据类型 ?

public class GenericDemo {
	public static void main(String[] args) {
		ArrayList<String> array = new ArrayList<String>();
		HashSet<Integer> set = new HashSet<Integer>();
      	array.add("one");
      	array.add("two");
     	set.add(3);
      	set.add(4);
      	iterator(array);
      	iterator(set);
	}
    /*
     *  定义方法,可以同时迭代集合array和set
     *  方法参数: 共同继承的父类或者共同实现的接口,不能写ArrayList,也不能写HashSet,要写两者共同实现的接口Collection,接口的参数要写?
     *  迭代器参数: 不能写String,也不能写Integer,要写?
     */
    public static void iterator(Collection<?> coll){
		Iterator<?> it = coll.iterator();
      	while(it.hasNext()){
        	//it.next()获取的对象不确定是什么类型
        	System.out.println(it.next());
      	}
	}
}
发布了22 篇原创文章 · 获赞 21 · 访问量 7011

猜你喜欢

转载自blog.csdn.net/weixin_43108122/article/details/100889453
今日推荐