集合 Collection

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/krismile__qh/article/details/88828023

集合与数组一样,也是一个容器,与数组不同的是,数组长度固定,集合的长度不定,可以无限的向集合中添加元素,而且集合中存储的元素类型可以随意,可以是不同的类型,只能是引用类型。

集合中有三大组件:List,Set,Map(List和Set  是Collection的子接口,Map不是)

Colletion集合的框架结构:(在util包下)

Map集合的框架结构:

1.Collection接口中常用的方法:

增加:1:add(元素) 将指定对象存储到容器中

           2:addAll(集合) 将指定集合中的元素添加到调用该方法和集合中

删除:3:remove(元素) 将指定的对象从集合中删除

          4:removeAll(集合) 将指定集合中的元素删除

修改:5:clear() 清空集合中的所有元素

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

           7:contains(元素) 判断集合何中是否包含指定对象

           8:containsAll(集合) 判断集合中是否包含指定集合

           9:元素.equals(元素)判断两个对象是否相等  

获取: 10:int size()    返回集合容器的大小

转成数组:11: toArray()   集合转换数组

2.迭代器(Iterator接口)原理:

迭代器相当于一个游标,最初获取迭代器时,迭代器的位置在所有元素的前面,每迭代一个元素,迭代器向后移动一个位置。方法:hasNext()//游标不移动,仅仅判断是否存在下一个元素 next();//取值,游标向后移动

3.List接口:

继承Collection接口,相对有序存储,可以存储相同元素(不排重,可重复),可以通过下标访问集合元素,List接口中可以使用独有的迭代器ListIterator(是Iterator的子接口,hasPrevious(),previous()),具有反向遍历的功能

方法:(有序,所以有下标,但是有不去重)

1:增加

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

        boolean addAll(int index, Collection c) 指定位置添加集合  

2:删除

        remove(int index) 删除指定位置元素

3:修改

        set(int index, E element)    返回的是需要替换的集合中的元素

4:查找:

        get(int index)             注意: IndexOutOfBoundsException

        int indexOf(Object o)         // 找不到返回-1

        lastIndexOf(Object o)

5:求子集合

        subList(int fromIndex, int toIndex) // 不包含toIndex

4.泛型

List list = new ArrayList();//== List<Object> list = new ArrayList<Object>();不规范

List<Student> list  = new ArrayList<Student>();//确定输入的类型,规范!

a.泛型就是可以表示一个广泛数据类型的类型参数(泛型只能表示引用类型),把数据类型作为参数来传递。

b.泛型的声明:方法、类、接口

1)泛型可以声明在方法中:(泛型方法)
public static <标识符> void fun(){}

2)泛型可以声明在类中:(泛型类)
public class 类名<标识符>{
    //类体
    //该类型可以在整个类中使用,静态方法不能使用类上面声明的泛型
    //泛型可以在类中充当成员变量
    //泛型可以在类中充当方法的返回值
    //泛型可以在类中充当方法的参数
}

3)泛型可以声明在接口中:(泛型接口)
public interface 接口名<标识符>{
    //成员
    //泛型可以充当接口中方法的返回值
    //泛型可以充当接口中方法的参数
}

c. 注:

1)标识符(占位符):只要是一个合法的标识符即可,一般情况下,只使用一个大写字母表示泛型
例:public class Person<T>{} E(Element)  K(key)  V(value)
2)泛型的类型与声明的类或接口不需要有任何的关系
3)泛型可以在类中充当任何的成员
4)泛型具体类型取决于实例化对象时传入的实际类型

5)泛型不能在类中声明静态属性、常量
final修饰的属性必须在声明的同时初始化,所以泛型不能声明常量
static修饰的属性是静态属性,先于对象,泛型类型取决于创建对象时传入的实际类型,所以泛型不能声明静态属性
综上所述:不能使用泛型声明静态属性、常量

6)泛型不能在类中初始化数组,但是可以声明数组 例:E[] e;
初始化数组时需要给元素进行分配空间,但是泛型类型不确定无法分配空间

7)在类中不能使用泛型声明参数个数相同的重载方法
当一个类中有两个泛型时,创建对象时,两个泛型使用相同类型替换,那么重载方法就是相同的方法(同名,参数列表也相同)

8)使用不同实际类型创建出的泛型类对象的引用不可以相互赋值

d. 受限类型

1)<?>:表示任意类型
2)<? extends T>:表示T类或者T类的子类
3)<? super T>:表示T类或者T类的父类

5.List的实现类:ArrayList、LinkedList、Vector

ArrayList类是最重要的。

与LinkedList的区别:ArrayList底层是Object数组Object[],初始容量是10,每次增加元素时,先判断数组是否能容纳,如果不能,容量扩大1.5倍(类的代码是:newCapacity = oldCapacity + (oldCapacity >> 1))。特点是:查询快、增删慢。而LinkedList的底层是链表实现的,特点是查询慢、增删快。

与Vector的区别:ArrayList是线程不安全的,效率高。Vector是线程安全的,效率低,Stack类是Vector的子类。

6. Set的实现类:HashSet、TreeSet

set接口是Collection接口的子接口,特点:无序,不可重复(可自动去重)。

如何去重?对象的相等性

    引用到堆上同一个对象的两个引用是相等的,对两个引用调用hashCode方法,会得到相同的结果。如果对象所属的类没有覆盖Object的hashCode方法的话,hashCode会返回每个对象特有的序号(java是依据对象的内存地址计算出的此序号),所以两个不同的对象的hashCode值是不可能相等的。

    如果想要让两个不同的Person对象视为相等的,就必须覆盖Object继下来的hashCode方法和equals方法,因为Object  hashCode方法返回的是该对象的内存地址,所以必须重写hashCode方法,才能保证两个不同的对象具有相同的hashCode,同时也需要两个不同对象比较equals方法会返回true

    该集合中没有特有的方法,直接继承自Collection。

HashSet类:线程不安全,存取速度快。底层是以hash表实现的。

HashSet的存储原理:

哈希表存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同) 是按照哈希值来存的所以取数据也是按照哈希值取得。

HashSet不存入重复元素的规则.使用hashcode和equals。

元素的哈希值是通过元素的hashcode方法来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法 如果 equls结果为true ,HashSet就视为同一个元素。如果equals 为false就不是同一个元素。

哈希值相同equals为false的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。

注:HashSet 和ArrayList集合都有判断元素是否相同的方法,HashSet使用hashCode和equals方法,ArrayList使用了equals方法

TreeSet:红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。

给TreeSet指定排序规则。

方式一:元素自身具备比较性

元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。

@Override

public int compareTo(Object obj) {

    Person p = (Person) obj;

    System.out.println(this+" compareTo:"+p);

    if (this.age > p.age) {

        return 1;

    }

    if (this.age < p.age) {

        return -1;

    }

    return this.name.compareTo(p.name);

}

方式二:容器具备比较性

当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeSet集合的构造方法。

例如:

    main:   TreeSet ts = new TreeSet(new MyComparator());

    class MyComparator implements Comparator {}

注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;

注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,因为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)

通过return 0来判断唯一性。

7,Map接口

注:

1.一个键(key)和它对应的值构成map集合中的一个元素。

2.Map中不能有重复的键(Key),自动去重,规则是hashCode()、equals();

3.通过key获取Value值

4.Key可以为null

5.Interface Map<K,V>   K,V必须是引用数据类型

6.Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素。

   1>map.keySet(),获取key的Set集合,遍历集合,通过key获取value(map.get(key)).

   2>通过获取一个entrySet集合,map.entrySet();(Entry是一个类,里面包括key和value两个属性),获取里面的键值对的值(entry.getKey(),entry.getValue())

7.Map中的key是无序的

常见方法:

1、添加:

put(K key, V value)(可以相同的key值,但是添加的value值会覆盖前面的, 返回值是前一个,如果没有就返回null)             

putAll(Map<K,V> m)  从指定映射中将所有映射关系复制到此映射中(可选操作)。

2、删除

remove(key)    删除Key元素,并返回Value

remove(key,value) 判断value对不对,返回boolean

clear()     清空集合对象

replace(key,value)通过key找到元素,把对应的值改成value

replace(key,oldvalue,newvalue)

3、获取

get(key) 返回value。当指定的键不存在的时候,返回的是null。

keySet() 返回以key为元素的Set集合

entrySet();返回Entry为元素的Set集合

3、判断:

boolean isEmpty()   长度为0返回true否则false

boolean containsKey(Object key)  判断集合中是否包含指定的key

boolean containsValue(Object value)  判断集合中是否包含指定的value

4、长度:

Int size()

Map接口的实现类:HashMap\HashTable\TreeMap    继承接口SortedMap

HashMap集合:底层是哈希表数据结构,所以自动去重,但是是无序的。线程不安全,可以存入null Key,null Value。要保证键的唯一性,需要覆盖hashCode方法,和equals方法。

HashTable集合:底层是哈希表数据结构,自动去重,但无序。线程安全,不可以存入null Key,null Value。效率较低,被HashMap 替代。

TreeMap集合:底层是二叉树数据结构,可以对map集合中的键进行排序。需要使用Comparable或者Comparator 进行比较排序。

Properties类:HashTable的子类

注:配置文件(在workspace中新建的一个File文件),是以键值对的形式存储的

load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。

load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。

(流里的文件可以是任意文件!不一定非是File文件)

返回值:枚举Enumeration(功能相当于Iterator,有hasMoreElements()方法和nextElement())  elements()  返回此哈希表中的值的枚举。keys()   返回此哈希表中的键的枚举。(这两个方法都是父类HashTable的方法)

方法详见API。

Collections 和 Arrays 工具类

Collections:常见方法:

1,对list进行二分查找:

前提该集合一定要有序。

int binarySearch(list,元素);

//必须根据元素自然顺序对列表进行升级排序

//要求list 集合中的元素都是Comparable 的子类。

int binarySearch(list,元素,Comparator);//比较器

2,对list集合进行排序。

sort(list);

//对list进行排序,其实使用的事list容器中的对象的compareTo方法

sort(list,comaprator);

//按照指定比较器进行排序

3,对集合取最大值或者最小值。

max(Collection)

max(Collection,comparator)

min(Collection)

min(Collection,comparator)
4,对list集合进行反转。

reverse(list);

5,对比较方式进行强行逆转。

Comparator reverseOrder();

Comparator reverseOrder(Comparator);

6,对list集合中的元素进行位置的置换。

swap(list,index1,index2);

7,对list集合进行元素的全替换。如果被替换的元素不存在,那么原集合不变。

replaceAll(list,old元素,new元素);

8,可以将线程不安全的集合变成线程安全的集合。synchronized***

Set synchronizedSet(Set<T> s)

Map synchronizedMap(Map<K,V> m)

List synchronizedList(List<T> list)

9. 如果想要将集合变数组:

可以使用 Collection 中的toArray 方法。注意:是Collection不是Collections工具类。

传入指定的类型数组即可,该数组的长度最好为集合的size。

猜你喜欢

转载自blog.csdn.net/krismile__qh/article/details/88828023