黑马程序员__JAVA基础__集合(一)

 ------------android培训java培训、java学习型技术博客、期待与您交流! ------------

1.概述

    面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

    java语言的java.util包中提供了一些集合类,这些集合又被成为容器,提到容器不难会想象到数组,集合类与数组的不同之处。

数组与集合不同之处:

    数组长度是固定的,集合长度是可变的

    数组中可以存储基本数据类型,集合只能存储对象。

集合的特点:

    集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象

集合有List集合,Set集合,Map集合,其中List和Set集合实现了Collection接口,各个接口还提供了不同的实现类。

集合的框架构成及分类:


2.Collection接口

Collection接口的有两个子接口:List和Set,List元素有序,元素可以重复,Set元素无序,元素要求唯一。

Collection

    |---->List可存放重复元素,元素存取是有序的。因为该集合体系有索引。

        |---->Vector:底层的数据结构是数组,线程安全,但速度慢,已被ArrayList替代。

        |---->ArrayList:底层的数据结构是数组。特点:查询速度很快。但是增删稍慢。线程不同步。

        |---->LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。

    |---->Set元素是无序(存入和取出的顺序不一定一致),元素不可以重复

        |---->HashSet:底层数据结构是哈希表,是线程不安全的,不同步。

        |---->TreeSet:可以对Set集合中的元素进行排序

Collection接口的功能:

    1.添加

        boolean add(Object obj):添加单个元素

        boolean addAll(Collection c):添加多个元素

    2.删除

        void clear():移除所有元素

        boolean remove(Object o):移除单个元素,有一个删除,就返回true

        boolean removeAll(Collection c):移除多个元素

    3.判断

        boolean contains(Object obj):判断元素是否存在

        boolean containsAll(Collection c):判断一个集合的元素是否包含在当前集合中

        boolean isEmpty():判断集合是否为空

    4.获取

        Iterator iterator():返回集合上的一个迭代器

        int size():元素个数

    5.获取交集

        boolean retainAll(Collection c):交集

    6.集合变数组

        Object[] toArray()

迭代器Iterator

    迭代器是取出集合中元素的一种方式,会直接访问集合中的元素。

    所以将迭代器通过内部类的形式来进行描述。

    通过容器的iterator()方法获取该内部类的对象。

迭代器的方法:

    boolean hasNext()判断是否还有元素可以迭代

    next()返回迭代的下一个元素,获取的元素默认为Object类

    注意:

    1.迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)

    2.迭代器的next()方法是自动向下取元素,要避免出现NoSuchElementException

    3.迭代器的next方法返回值类型是Object,所以要记得类型转换

3.List

    可存放重复元素,元素存取是有序的。因为该集合体系有索引。

List接口功能:

    1.添加元素

    void add(int index, Object element):在指定位置添加指定元素

    boolean addAll(index i,Collection<? extends E> c)

    2.删除元素

    Object remove(int index):返回并删除指定位置的元素

    3.修改元素

    Object set(int index, Object element):修改指定位置的元素

    4.查找元素

    Object get(int index):根据指定索引获取元素

    List<E> subList(int fromIndex, int toIndex)返回列表中指定的 fromIndex(包括)和toIndex(不包括)之间的部分视图。

    int indexOf(Object o)返回此列表中第一次出现的指定元素的索引,如不包括,返回-1

    ListIterator listIterator()List特有的迭代器

List特有迭代器

    ListIterator<E> listIterator():返回按适当顺序在列表的元素上进行迭代的迭代器。

    在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。

    注:ConcurrentModificationException异常是指当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常,这个地方是指在用迭代器的方法操作集合的时候,又用集合本身的方法来操作这个集合,所以抛出这个异常

    在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator

    该接口只能通过List集合的listIterator方法获取。例:ListIterator it = List集合名. listIterator();

List迭代器特有方法:

    void add(E e) 将指定的元素插入列表(可选操作)。

    boolean hasPrevious()  如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。 

    int nextIndex() 返回对 next 的后续调用所返回元素的索引。         

    E previous() 返回列表中的前一个元素。    

    int previousIndex() 返回对 previous 的后续调用所返回元素的索引。    

    void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。

    void remove()从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。

List实现类

Vector

    底层的数据结构是数组,查询快,增删慢,线程同步,效率低已被ArrayList替代

Vector特有方法:

    1.添加元素

    void addElement(Object obj) JDK1.2 后改为了add(Object obj)

    2.获取元素

    Object elementAt(int index) JDK1.2后就改为了get(int index),通过角标拿元素

    3.遍历元素

    Enumeration elements() JDK1.2后就改为Iterator iterator()

    boolean hasMoreElements() JDK1.2后就改为boolean hasNext()

    Object nextElement() JDK1.2后就改为了 Object next()

    Enumeration elements() 

    Enumeration就是枚举,枚举就是Vector特有的取出方式。此接口的功能与 Iterator 接口的功能是重复的,Iterator接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用Iterator接口而不是Enumeration接口。

Vector取出元素示例代码:

class VectorDemo 
{
	public static void main(String[] args) 
	{
		Vector v = new Vector();

		v.add("java01");//添加元素
		v.add("java02");
		v.add("java03");
		v.add("java04");

		Enumeration en = v.elements();//枚举的方式取出元素
		while(en.hasMoreElements())
		{
			System.out.println(en.nextElement());
		}
	}
}


Arraylist

底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步

    练习:去除ArrayList集合中的重复元素

    思路:新建立一个集合,遍历原集合往新集合里面存,在存之前进行是否有这个元素的判断。

import java.util.*;
class ArrayListTest 
{

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();

		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java03");
		
		al =  singleElemen(al);
		sop(al);
	}

	public static ArrayList singleElement(ArrayList al)
	{
		//定义一个临时容器。
		ArrayList newAl = new ArrayList();
		Iterator it = al.iterator();//使用迭代器
		while(it.hasNext())
		{
			Object obj = it.next();
			if(!newAl.contains(obj))//判断是否有遍历到元素
				newAl.add(obj);
		}
		return newAl;
	}
}


LinkList

底层使用的链表数据结构。特点:增删速度很快,查询稍慢,线程不同步。

LinkList特有方法:

    1.添加元素:

    void addFirst(E e) 将指定元素插入此列表的开头。 

    void addLast(E e) 将指定元素添加到此列表的结尾。 

    2.获取元素:

    E getFirst()返回此列表的第一个元素。 

    E getLast()返回此列表的最后一个元素。 

    3.删除元素:

    E removeFirst()移除并返回此列表的第一个元素。  

    E removeLast()移除并返回此列表的最后一个元素。 

测试代码示例:

class LinkedListDemo
{
	public static void main(String[] args)
	{
		LinkedList link = new LinkedList();//创建对象
		link.add("hello");//添加元素
		link.add("world");
		//特有方法:添加在列表开头与末尾
		link.addFirst("start");
		link.addLast("over");

		// 获取元素
		System.out.println("getFirst:" + link.getFirst());
		System.out.println("getLast:" + link.getLast());
		// 遍历
		Iterator it = link.iterator();
		while (it.hasNext())
		{
			String s = (String) it.next();
			System.out.println(s);
		}
	}
}

4.Set集合

    Set接口里面存放的是元素是无序唯一的,可以包含null。Set集合是无序的,因此只能用迭代器获取元素。Set的子类包括HashSet和TreeSet

    Set集合的功能和Collection是一致的.

HashSet:

底层数据结构是哈希表。是线程不安全的。不同步。

HashSet是如何保证元素唯一性的呢?

    是通过元素的两个方法,hashCode和equals来完成。

    如果元素的HashCode值相同,才会判断equals是否为true。

    如果元素的hashcode值不同,不会调用equals。

注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法

练习:往hashSet集合中存入自定对象,姓名和年龄相同为同一个人,重复元素。复写hashCode和equals方法

import java.util.*;

class HashSetTest 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		HashSet hs = new HashSet();

		hs.add(new Person("a1",11));
		hs.add(new Person("a2",12));
		hs.add(new Person("a3",13));
		hs.add(new Person("a2",12));//添加复杂元素,会调用比较器不将此元素添加至列表
		hs.add(new Person("a4",14));

		Iterator it = hs.iterator();

		while(it.hasNext())
		{
			Person p = (Person)it.next();
			sop(p.getName()+"::"+p.getAge());
		}
	}
}

class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public int hashCode()//复写hashCode方法
	{
		System.out.println(this.name+"....hashCode");
		return name.hashCode()+age*37;
	}

	public boolean equals(Object obj)//复写equals方法
	{

		if(!(obj instanceof Person))
			return false;

		Person p = (Person)obj;
		System.out.println(this.name+"...equals.."+p.name);

		return this.name.equals(p.name) && this.age == p.age;
	}

	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

TreeSet

    可以对Set集合中的元素进行排序,底层数据结构是二叉树。

    保证元素唯一性的依据:compareTo方法return 0.

    TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。这种方式也成为元素的自然顺序,或者叫做默认顺序。

    TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式,接受实现Comparator接口的子类对象

    第一种方式:实现Comparable接口

class Person implements Comparable<Person> {
	private String name;
	private int age;
	public Person() {
	}
	public Person(String name, int age) {
		this.name = name;
		this.age = 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 int compareTo(Person p) {
		int num = p.age - this.age;
		//年龄相同的时比较姓名是否相同
		int num2 = (num == 0) ? this.name.compareTo(p.name) : num;
		return num2;
	}
}

第二种方式:接受实现Comparator接口的子类对象

TreeSet ts = new TreeSet(MyCompare);
//定义一个类,实现Comparator接口,覆盖compare方法。
class MyComart implements Comparator
{
	public int compare(Object o1,Object o2)//覆盖compare方法。
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
		{
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));//比较年龄因为Intege已经具有比较性了.直接比就可以
			
			/*
			if(s1.getAge()>s2.getAge())
				return 1;
			if(s1.getAge()==s2.getAge())
				return 0;
			return -1;
			*/
		}
		return num;
	}
}

    注:当元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身具备比较性,定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。当两种排序都存在时,以比较器为主。




个人总结

    集合是一个大的重点,才开始看视频的时候总是分不清他们的特有属性。每个分支里面又有小的分支,多多敲代码与多多看笔记加深印象,好在实用的过程中明白到底用哪个最好。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值