您的位置:首页 > 编程语言 > Java开发

Java中的集合

2016-03-17 15:09 387 查看
存储对象可以使用数组或者集合
1/1数组存储对象
1、动态方式(同String)

Student []stu = new Studeng[20];

stu[0] = new Student();

Stu[1] = new Student();
……
2、静态方式(同String)
1/2当我们面向对象编程时,总要处理大量的对象;
1.处理大量对象,可以使用"数组"存储;
2.但数组有很多的局限性:
1).数组的长度一旦确定,后期不能更改;我们程序员可以定义新的数组,但是每次做这样的操作都很费事;
2).数组在定义时,指定了"数据类型",那么这个数组就只能装这个数据类型的,不能装其它类型的。
3.以上的两个局限性,对于我们程序员来说,在操作大量对象时,就非常的不方便。
所以这时,Java为我们提供了一种"工具"。它类似于"仓库",可以用来存储大量的"引用"。
这种"仓库"就是:"集合类";
特点:
1).对于我们程序员来说,就像一个"无底洞",可以装无数的"引用";我们不用关心"长度"信息;
2).这些"集合类"可以装任何"引用数据"类型的数据;

Collection接口的基本方法

1、添加

boolean add(E e):将元素e的引用添加到集合中

2、删除

boolean remove(Object o):将元素从集合中删除

void clear():清空集合

3、获取

boolean contains(Object o):查找集合中的元素o,如果有则返回true,否则返回false

boolean isEmpty():判断集合是否为空,为空返回true,否则返回false

int size():获取集合的大小

boolean addAll(Collection c):将指定Collection中的元素都添加到此Collection中

boolean removeAll(Collection c):删除此Collection中包含在指定Collection中元素

boolean containsAll(Collection c):如果此Collection中包含指定Collection中所有元素则返回true

boolean retainAll(Collection c):保留此Collection中也包含在指定Collection中元素

Object[] toArray():把集合转成数组,可以实现集合的遍历

Iterator iterator():迭代器,集合的专用遍历方式

4、Colletion的两个子接口:List、Set

Collection子接口——List接口

一、List(list 元素有序,可以重复的集合)

1、ArrayList()(主要实现类)、LinkedList()、Vector()

2、List三个子类的特点

1)ArrayList:数组实现,线程不安全,效率高,使用数组实现,效率比Vector高

2)Vector:数组实现,线程安全,效率低,使用数组实现

3)LinkedList:链表实现,线程不安全,效率高,使用链表实现

3、List特有的方法:

void add(int index,E element);

E remove(int index):

E get(int index)

E set(int index,E element)

ListIterator listIterator():List特有的迭代器,一个可以向前遍历的迭代器。
注意:当我们使用Iterator遍历List时,如果要添加删除元素,如果直接使用list的引用来操作会产生ConcurrentModificationException(并发修改异常),因为Iterator依赖于List和数组,List的结构发生了改变Iterator并不知道。解决方式:①通过ListIterator来修改,ListIterator继承自Iterator,另外添加了add(),remove()方法,可以实现元素的添加删除
②直接使用for循环遍历集合来修改。
当使用ListIterator向前遍历时,一定要先向后遍历

boolean hasPrevious()

E previous()

4、 Iterator和ListIterator的区别:

Iterator是父接口:

Iterator是单向的,只能向下遍历;

Iterator接口成员方法

boolean hasNext()

E next()

5、 ListIterator是Iterator的子接口;

ListIterator是双向的,可以向前遍历;

6、List特有的遍历方式(使用get(int index)方法):

for(int I = 0;i<list.size,i++){

System.out.println(list.get(i));

}

List实现类——ArrayList

遍历方式

方式一:

使用toArray()将集合转换为数组,使用普通for循环

方式二:

使用toArray()将集合转换为数组,使用增强for循环

方式三:

使用Collection的size()方法和List的get()方法

方式四:

使用接待器(Iterator或者ListIterator)

List实现类——Vector

Vector类(采用数组实现)

1、Vector(类)特有方法:

public void addElement(E obj):添加一个元素;

public E elementAt(int index):返回指定索引处的引用;

public Enumeration elements():返回此向量的组件的枚举

capacity():返回此向量的当前容量

2、遍历

方式一:

for(int i = 0;i < vec.size() ; i++){

//使用Collection的size()方法和List的get方法;

//String str = (String)vec.get(i);

}

方式二:

转换成数组,使用普通for循环

方式三:

转换成数组,使用增强for循环

方式四:

使用迭代器(Iterator或者ListIterator)

方式五:

for(int i = 0;i < vec.size() ; i++){

//使用Vector特有的方法

String str = (String)vec.elementAt(i);

System.out.println(str);

}

List实现类——LinkedList

1、LinkedList类的特有功能:
public void addFirst(E e):将元素e添加到第一个位置上。原位置上的元素依次后移;可以模拟"栈"结构;
public voidaddLast(E e):将元素e添加到末尾。
public E getFirst()及getLast():获取第一个元素和最后一个元素;
public E removeFirst()及public E removeLast():删除第一个元素和最后一个元素;

2、遍历方式

方式一:
将集合转换为数组,使用普通for循环

方式二:
将集合转换为数组,使用增强for循环

方式三:
使用接待器(Iterator或者ListIterator)

Collection子接口——Set

1、Set元素是无序的(取出时的顺序与存入时的顺序不一致不可存储重复值),不可重复的集合
2、Set接口是Colletion的子接口,继承了Collection的所有方法
3、特点
取出时的顺序与存入时的顺序不一致
不可存储重复值(需要重写hashCode()和equals()方法)
4、要求添加进Set中的元素所在的类,一定要重写equals()和hashCode()方法。进而保证Set中元素的不可重复性!其中hashCode()方法降低哈希值的重复率,equals()方法比较元素的值
5、HashSet(主要实现类)、LinkedHashSet、TreeSet
6、向HashSet和LinkedHashSet中添加对象时,首先调用此对象所在类的hashCode()方法,计算此对象的哈希值,此哈希值决定了对象在Set中的存储位置,若此位置没有对象存储,则直接添加进来,若已经有对象存储在此位置,再通过equals()方法比较这两个对象是否相同,如果相同,后一个对象就不能添加进来,如果不同,则可以添加。
6/1
重写hashCode()方法:
一般情况下,是将内部成员进行一个int值的累加
对于基本数据类型,尽量转换为int值
对于引用类型,调用它的hashCode()方法(此处的hashCode()方法是String重写的Object的方法)

6/2使用哈希表结构的特点:
1、存入时,先计算哈希值,然后存入哈希表;
2、在哈希表中产生了一个哈希值与存储的对象的映射关系
3、在查找时,先通过存储的对象生成一个哈希值,然后从哈希表中通过哈希值获取之前存储的对象
4、综合了数组和链表两种结构,具有数组的两种优势,查询快,增删快
6/3
哈希表的存储方式:
1、如果hashCode不同则一定存
2、如果hashCode不同,则判断equals()方法,如果equals()不同,则存储
7、向TreeSet中添加元素时需要实现Comparable接口并重写compareTo方法或者自定义比较器实现Comparator接口并从写compare方法来保证元素的不重复性

Set实现类——HashSet

HashSet保证元素的唯一性:

1.由于HashSet内部使用了"哈希表",所以它会先产生"哈希值";

2.通过查看源码,我们知道,判断重复元素的方式:

1.先判断:hashCode是否相同;

2.如果hashCode相同,再判断equals;

3.所以,我们使用HashSet存入自定义对象,如果想使HashSet存储不同的元素,排除掉不同对象,但内部属性完全相同的对象,我们就要在我们的自定义类中重写:hashCode()和equals()

Set实现类——LinkedHashSet

一、特点:

1、内部由链表和哈希表实现;

2、链表:保证顺序;

3、哈希表:保证唯一;

Set实现类——TreeSet

1、TreeSet:内部使用"树"结构存储:

1、先对元素进行比较;

2、对元素进行"排序";

2、由于要对元素进行排序,所以就需要比较。比较的方式有两种:

1、自然排序

必须实现Comparable接口

重写里面的compareTo()方法

2、使用比较器(定制排序)

①我们的类不用实现任何接口;

②在实例化TreeSet时,使用带Comparator接口的构造方法;

③我们自定义一个类,实现Comparator接口。并重写:compare()方法;

3、向TreeSet中添加的对象必须是同一个类的

4、当一个类没有实现Comparable接口时,如果向TreeSet中添加该类的对象,报ClassCastException

5、当想TreeSet中添加自定义类的对象时,有两种方法:自然排序和定制排序

5/1 自然排序

(1)自然排序:要求自定义类实现Java.lang.Comparable接口,并重写其CompareTo(Object obj)方法,在此方法中指明按照自定义类的那个属性进行排序

(2)为什么要重写compareTo()方法?

①TreeSet的add()方法,内部会自动调用存储对象的compareTo()方法,所以这个方法必须要有。

②compareTo()方法不是Object类中定义的。所以,我们自定义类中是没有这个方法的。

③所以,我们的类,为了满足:TreeSet的add()方法的需要,必须要实现Comparable接口,并重写

compareTo()方法;

注意:对于中文字段使用compareTo()方法进行排序,没有意义。

(3)向TreeSet中添加对象时,首先按照CompareTo(Object obj)进行比较,一旦返回0,虽然只有比较的属

性值相同,但程序会认为这几个对象是相同的,后面的对象将不能添加进去。

(4)自然排序步骤:自定义类实现Java.lang.Comparable接口,并重写其CompareTo(Object obj)方法==>

自定义类中重写equals()和hashCode()方法==>添加对象

5/2 定制排序

1、创建一个实现了Comparator接口的类对象,重写compare()方法,在此compare()方法中,指明是按照某个类的哪个属性排序的,若后添加的元素的该属性值与已添加进的改属性值相同,则后者不能添加进去

2、将此对象作为参数传递给TreeSet的构造器中

3、向TreeSet中添加Comparator接口中的compare方法中涉及的类的对象。

可以在实例化TreeSet是在其构造方法中使用匿名内部类,在其内部重写compare()方法

6、遍历集合

方式一:

使用toArray()方法

System.out.println(list);//这不是遍历,是获取一个String

Object[] objArray = list.toArray();

for(int i = 0 ;i < objArray.length ; i++){

String s = (String)objArray[i];

System.out.println(s);

//System.out.println(objArray[i]);//调用Object-->toString()

}

方式二:

使用迭代器:

Iterator iterator():

java.util.Iterator(接口):

成员方法:

boolean hasNext() 如果仍有元素可以迭代,则返回 true。

Object next() 返回迭代的下一个元素。

方式三:

使用增强for循环(基于迭代器的,凡是能用迭代器的都可以使用增强for循环)

Map接口

一、Map接口

1.特点:

1、双列的集合,存储使用"键、值"对;

2、键"是唯一的。

3、当我们存储相同的"键"时,会将新值替换原值;

4、无序的;

2、Map接口是具有映射关系的“key-value对”的集合,其中key不能重复,每个键映射一个值。

3、Map和Collection的区别:

1、Map是双列的,Collection是单列的

2、Map的键唯一,Collection的子体系Set是唯一的:HashSet(唯一)内部使用-->HashMap。所以HashMap对于

重复的"键值"的判断,跟HashSet的判断方式是一样的;

3、Map集合的数据结构只针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

4、HashMap()、LinkedHashMap()、TreeMap()、HashTable()

5、Map接口

|-----HashMap:Map的主要实现类

|-----LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按添加的顺序遍历的。

|-----TreeMap:按照添加进Map中的元素的key的指定属性进行排序。要求:key必须是同一个类的对象!

针对key:自然排序 vs 定制排序

|-----Hashtable:古老的实现类,线程安全,不建议使用。

|----Properties:常用来处理属性文件。键和值都为String类型的

二、常用方法

1、Map的基本方法:

V put(Object key,Object value):向Map中添加一个元素,向Map添加元素时,当存储重重复的键是,是使用

新值替换旧值

V remove(Object key):按照指定的key删除此key-value

void putAll(Map t)

void clear():清空

Object get(Object key):获取指定key的value值。若无此key,则返回null

boolean containsKey(Object key)

boolean containsValue(Object value):判断Value是否在集合中

boolean isEmpty()盘点集合是否为空

boolean equals(Object obj)

int size():返回集合内的元素的数量

2、Map接口的获取的方法:

V get(Object key):通过一个key获取一个value

Set<K> keySet():获取所有key,以一个Set返回

Collection<V> values():获取value,以一个collection返回值

Set<Map.Entry<K,V>>entrySet():获取键值对(用于遍历键值对)

Map实现类——HashMap
1、key是用Set来存放的,不可重复。value是用Collection来存放的,可重复一个key-value对,是一个Entry。所有的

Entry是用Set存放的, 也是不可重复的。

2、向HashMap中添加元素时,会调用key所在类的equals()方法,判断两个key是否相同。若相同 则只能添加进后添加

的那个元素。

3、HashMap:

A.内部使用哈希表结构;

B.验证键的唯一:通过调用"键"对象的hashCode()和equals()。当使用自定义类做"键",为了维护"键"的唯一性,要在自定义类中重写:hashCode()和equals()方法;

4、遍历

(1)遍历key集

Set set = map.keySet();

for (Object obj : set) {

System.out.println(obj);

}

(2)遍历value集

Collection values = map.values();

Iterator i = values.iterator();

while (i.hasNext()) {

System.out.println(i.next());

}

(3)如何遍历key-value对

// 方式一:

Set set1 = map.keySet();

for (Object obj : set1) {

System.out.println(obj + "----->" + map.get(obj));

}

// 方式二:

Set set2 = map.entrySet();

for (Object obj : set2) {

Map.Entry entry = (Map.Entry) obj;

// System.out.println(entry.getKey() + "---->" + entry.getValue());

System.out.println(entry);

}

Map实现类——LinkedHashMap

1、内部由链表和哈希表实现
2、链表:保证了有序;
哈希表:保证了唯一;
注意:Map子类的数据结构,都是应用在"键"上的。

Map实现类——TreeMap

1、内部使用的"树"结构;
2、只对"键"进行排序;
3、TreeMap存储对象时键需要保证唯一性,

HashMap和Hashtable的区别

1、java.util.Hashtabel类
1、内部使用哈希表实现
2、不允许使用NULL键和NULL值
3、线程安全,效率低(同步的)
4、从JDK1.0开始

2、java.util.HashMap类
1、内部使用哈希表实现
2、允许使用NULL键和NULL值
3、线程不安全,效率高(不同步)
4、从JDK1.2开始
3、除了非同步和允许使用 null之外,HashMap类与
Hashtable大致相同。

List,Set,Map的联系

List,Set,Map等接口是否都继承了Map接口:不是
Collection(接口)
|--List(接口):
|--ArrayList(类):
|--Vector(类):
|--LinkedList(类):
|--Set(接口):
|--HashSet(类):
|--TreeSet(类):
|--LinkedHashSet(类):
Map(接口)
|--HashMap(类):
|--TreeMap(类):
|--LinkedHashMap(类):
|--Hashtable(类);

集合的嵌套

1.一个集合,可以存储任何类型的对象,包括"集合"。

2.所以:一个集合可以存储另一个集合,这就叫:集合的嵌套;

例子:一个班有3名同学,有3个姓名。另一个班有5名同学,有5个姓名;要求:将两个班合并为一个集合打印:

1.定义一个集合,存储第一个班的3名学员;

2.定义一个集合,存储第二个班的5名学员;

3.定义一个大集合,将前面的两个小集合存入;

4.遍历大集合

3、ArrayList嵌套ArrayList

package cn.itcast.demo20_集合的嵌套;

import java.util.ArrayList;

public class Demo {

public static void main(String[] args) {

//1.第一个班的集合

ArrayList<String> class1List = new ArrayList<>();

class1List.add("马云");

class1List.add("马化腾");

class1List.add("雷军");

//2.第二班的集合

ArrayList<String> class2List = new ArrayList<>();

class2List.add("成龙");

class2List.add("甄子丹");

class2List.add("李连杰");

class2List.add("吴京");

class2List.add("洪金宝");

//3.实例化一个大集合

ArrayList<ArrayList<String>> list = new ArrayList<>();

list.add(class1List);

list.add(class2List);

//4.打印大集合

for(ArrayList<String> classList : list){

for(String name : classList){

System.out.println(name);

}

}

}

}

4、HashMap集合嵌套HashMap集合的案例

例子:

有两个班的学员:

----Map<String,Map<String,String>>------------

0616班:

------Map<String,String>------

"it001" "张学友"

"it002" "郭富城"

"it003" "刘德华"

0617班:

------Map<String,String>------

"it101" "刘亦菲"

"it102" "王菲"

"it103" "胡一菲"

package cn.itcast.demo02_集合练习_HashMap集合嵌套HashMap集合的案例;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

public class Demo {

public static void main(String[] args) {

//1.第一个班的Map

Map<String,String> class1Map = new HashMap<>();

class1Map.put("it001", "张学友");

class1Map.put("it002", "郭富城");

class1Map.put("it003", "刘德华");

//2.第二个班的Map

Map<String,String> class2Map = new HashMap<>();

class2Map.put("it101", "刘亦菲");

class2Map.put("it102", "王菲");

class2Map.put("it103", "胡一菲");

//3.一个大Map,存储两个班的Map集合

Map<String,Map<String,String>> map = new HashMap<>();

map.put("0616班", class1Map);

map.put("0617班", class2Map);

//4.遍历

Set<String> keySet = map.keySet();

for(String classNo : keySet){

System.out.println(classNo);

Map<String,String> m = map.get(classNo);

Set<String> keys = m.keySet();

for(String stuNo : keys){

System.out.println("\t" + stuNo + "\t" + m.get(stuNo));

}

}

}

}

5、HashMap集合嵌套ArrayList集合

HashMap集合嵌套ArrayList集合的案例

例子:

一个班的学员,只记录姓名:

--------Map<String,ArrayList<String>>-------------

0616班

---ArrayList<String>---------

"刘亦菲"

"王菲"

"胡一菲"

0617班

---ArrayList<String>---------

"刘德华"

"张学友"

"郭富城"

package cn.itcast.demo03_集合练习_HashMap集合嵌套ArrayList集合的案例;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

public class Demo {

public static void main(String[] args) {

//1.第一个班的ArrayList

ArrayList<String> class1List = new ArrayList<>();

class1List.add("刘亦菲");

class1List.add("王菲");

class1List.add("胡一菲");

//2.第二个班的ArrayList

ArrayList<String> class2List = new ArrayList<>();

class2List.add("刘德华");

class2List.add("张学友");

class2List.add("郭富城");

//3.一个Map集合,存储班号,和两个班的ArrayList

Map<String,ArrayList<String>> map = new HashMap<>();

map.put("0616班", class1List);

map.put("0617班", class2List);

//4.遍历

Set<String> keySet = map.keySet();

for(String key : keySet){

System.out.println(key);

ArrayList<String> list = map.get(key);

for(String s : list){

System.out.println("\t" + s);

}

}

}

}

6、ArrayList集合嵌套HashMap集合的案例

package cn.itcast.demo04_集合练习_ArrayList集合嵌套HashMap集合的案例;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

ArrayList集合嵌套HashMap集合的案例

例子:

-----------ArrayList<Map<String,String>>-----------------

第一个班:

-----Map<String,String>------------

"it001" "刘德华"

"it002" "张学友"

"it003" "郭富城"

第二个班:

-----Map<String,String>------------

"it101" "刘亦菲"

"it102" "王菲"

"it103" "胡一菲"

public class Demo {

public static void main(String[] args) {

//1.第一个班的map

Map<String,String> class1Map = new HashMap<>();

class1Map.put("it001", "刘德华");

class1Map.put("it002", "张学友");

class1Map.put("it003", "郭富城");

//2.第二个班的map

Map<String,String> class2Map = new HashMap<>();

class2Map.put("it101", "刘亦菲");

class2Map.put("it102", "王菲");

class2Map.put("it103", "胡一菲");

//3.一个ArrayList,存储两个班的Map

ArrayList<Map<String,String>> list = new ArrayList<>();

list.add(class1Map);

list.add(class2Map);

//4.遍历ArrayList

for(Map<String,String> map : list){

//遍历map

Set<String> keySet = map.keySet();

for(String key : keySet){

System.out.println(key + "\t" + map.get(key));

}

System.out.println();//打印一个换行符

}

}

}

泛型

一、为什么要使用泛型

1.对于集合类,就其本身而言,是可以添加任何的引用类型。因为它的add()方法的形参是Object类型;但,这样在我

们取出时,会造成很大的麻烦,我们总要向下转型为我们存储的类型;一旦判断失误,就会导致转换失败,会抛出

异常。

2.我们在平时使用集合类时,更多的情况是"只存储一种类型",所以这时,Java为我们提供了一种方式,可以在定义集合时,就规定好这个集合内能够存储什么类型的数据,一旦定义之后,它的add()方法就只能接受那种类型的数据。这种方式:泛型

二、泛型的语法:

ArrayList<String> list = new ArrayList<String>();

或者:

ArrayList<String> list = new ArrayList<>();(比较常用)

或者:

ArrayList<String> list = new ArrayList();

注意:泛型:只在"编译期"存在。一旦生成class文件后,泛型信息就没有了。

说明,只是用在"编译"时,进行"类型检查"。

三、定义泛型类

1.在类名的后面定义一对<>,里面定义泛型字母:

2.泛型的名称:

1).可以是一个字母(大写、小写),可以是多个字母;一般都是"一个大写字母";

T : Type

K : Key

V : Value

2).可以同时定义多个泛型,每个泛型使用,隔开

3.当其他类使用此类时,可以使用"泛型",也可以不使用"泛型",如果不使用"泛型",那么内部所有使用泛型的位置,全部变为"Object"类型;



public class MyArrayList<T> {

public void show(T obj){

}

}

四、定义泛型方法

对于一个方法,可以定义泛型,但如果只定义泛型,而且形参使用泛型,似乎没有什么意义--此方法能接收任何类型数据。但是,如果返回值也定义为T类型,这就表示:这个方法能保证接收某个类型,那么就返回某个类型;

例:

public <T> T show(T t){

System.out.println("t = " + t);

return t;

}

五、定义泛型接口

1、一个接口也可以定义泛型,格式跟"泛型类"相同

例:

public interface IA<T> {

void show(T t);

}

2、当子类实现接口时有三种方法:

2/1 可以继续使用泛型;(常见的情况)

class SubA<T> implements IA<T>{

public void show(T t){

{

}

2/2 可以丢弃泛型;内部的使用泛型的地方全部变为Object类型;

class SubA implements IA{

public void show(Object obj){

}

}

2/3 可以定义为某个具体类型:在接口的名称后,指定具体类型的泛型;

class SubA implements IA<String>{

public void show(String s){

}

}

例:

public class SubA implements IA<String> {

@Override

public void show(T t) {

}

@Override

public void show(Object t) {

}

@Override

public void show(String t) {

Collection c;

}

}

六、泛型通配符

1、<?>:

1).能够指向什么类型的对象?

可以指向具有任何具体类型泛型的集合对象;

ArrayList<?> list1 = new ArrayList<>();//OK的

ArrayList<?> list2 = new ArrayList<String>();//OK的

ArrayList<?> list3 = new ArrayList<Integer>();//OK的

2).可以添加什么类型的引用?

list1:不能添加任何类型;

list2:不能添加任何类型;

list3:不能添加任何类型;

3).取出时,用什么接收?

接收全部使用Object接收;

特点:不能向里面存东西,但可以从里面取东西。这种声明一般用于方法的返回值;

2、<? extends E>:

1).能够指向什么类型的对象?

可以指向具有E或者E的子类类型泛型的集合对象;

ArrayList<? extends B> list4 = new ArrayList<A>();//NO

ArrayList<? extends B> list5 = new ArrayList<B>();//OK

ArrayList<? extends B> list6 = new ArrayList<C>();//OK

public <? extends B> show(){

ArrayList<B> list = new ArrayList<B>();

ArrayList<C> list2 = new ArrayList<C>();

//return list;

return list2;

}

2).可以添加什么类型的引用?

不能存任何类型;

3).取出时,用什么接收?

可以使用E或E的父类类型接收;

特点:不能向里面存东西,只能从里面取东西。这种声明一般用于方法的返回值;表示,这个方法返

回的集合,里面存的可能是E类型,或者E的某个子类类型;

3、<? super E>:

1).能够指向什么类型的对象?

可以指向具有E或者E的"父类"类型泛型的集合对象;

2).可以添加什么类型的引用?

可以添加E或E的子类对象的引用;

3).取出时,用什么接收?

取出时只能用Object接收;

特点:存入的时候是任何E或E的子类对象的引用。取出时,仍然使用Object接收。所以这种声明一般

用于方法的形参

Collections工具类

1、常用方法
java.util.Collections类:对集合操作的工具类。它没有构造方法,是由一些静态方法组成的;
public static <T> voidsort(List<T> list):根据元素的自然顺序对指定列表按升序进行排序。
注意:形参List<T>中存储的对象一定要是:Comparable的子类类型。因为sort()方法内部使用对象的compareTo()方法进行比较;

publicstatic <T> int binarySearch(List<?> list,T key)
参数:
list -要搜索的列表。
key -要搜索的键。
public static <T> Tmax(Collection<?> coll):根据元素的自然顺序,返回给定collection的最大元素。
public static void reverse(List<?> list):反转指定列表中元素的顺序。
public static void shuffle(List<?> list):打乱集合的顺序;

Properties类



一、java.util.Map:
|--Hashtable:
|--Properties:
1.此类不支持泛型;

二、Properties特殊功能的使用:
public Object setProperty(Stringkey,String value)-->put(Object key ,Object value)//添加键值对
public String getProperty(Stringkey)-->get(Object key);//返回key所对应的值
public Set<String>stringPropertyNames() -->keySet();//返回键的集合

三、Propertis操作配置文件
一般的程序都需要配置文件,记录:用于的一些配置信息;

要读取配置文件,使用字符流是可以的。但是由于配置文件有固定的格式:名 =值;
所以Java就提供了一种双列的集合:Properties类,并且内部,添加了一些读取、写入文件的一些方法。

操作配置文件的方法:
public void load(Reader reader):读取。直接存储到本集合内部;
public void store(Writer writer,String comments):写入。将集合内部的所有键值对,写到配置文件中;

public void store(OutputStream out, String Comments)

集合的特点和数据结构总结

一、集合的特点
Collection(接口)
|------List(接口):1、有序;2、可以存储重复元素
|------ArrayList(类):数组实现,线程不安全,效率高
|------Vector(类):数组实现,线程安全,效率低
|------LinkedList(类):链表实现,线程不安全,效率高
|------Set(接口):1、无序;2、不能存储重复元素;
|------HashSet(类):哈希表实现。线程不安全,效率高
保证唯一性:使用hashCode()和equals()
|------LinkedHashSet(类)链表、哈希表实现。线程不安全,效率高
|------TreeSet(类):数组实现。线程不安全,效率高
对元素排序的,要排序就要比较,比较方式:
1、自然排序:
①我们的类要实现Comparable接口
②重写compare方法
2、比较器排序

①我们的类不需要实现任何接口
②自定义一个比较器,实现Comparator接口,重写compare()方法
③实例化TreeSet时,传递自定义比较器的对象
Map(接口)
1.双列集合,使用"键、值对"存储;

|------HashMap(类):哈希表实现。线程不安全的,效率高;
保证"键"的唯一性,同HashSet
|------TreeMap(类):树实现。线程不安全的,效率高;
对"键"的排序,同TreeSet
|------LinkedHashMap(类);链表、哈希表实现。线程不安全的,效率高;
|------Hashtable(类):哈希表实现。线程安全的,效率低;

二、数据结构
1、数组:查询快、增删慢
2、链表:查询慢、增删快
3、栈:后进先出
4、队列:先进先出
5、哈希表:综合了数组和链表的优点。查询、增、删都很快;
6、树:第一个存储的作为"根节点",再存储其它元素时,跟每个元素依次比较,小的:存到左边,
大的:存到右边。相等的:不存;

如何选择使用哪种集合

1、需要单列还是双列
|------单列:使用Collection
|------有序:使用list
|------经常查询,但不经常修改:使用ArrayList(单线程、快),Vector(多线程、慢)
|------经常会修改:使用LinkedList
|------无序:使用Set
|------不需要排序:HashSet(无序的)、LinkedHashSet(有序的)
|------需要排序:TreeSet
|------双列:使用Map
|------不需要排序:使用HashMap、linkedHashMap
|------需要排序:TreeMap

多种集合的遍历方式

1、Collection
1、toArray()
2、迭代器
3、增强for(常用)

|------List
4、特有的遍历方式:使用Collection的size()和List的get(intindex)(常用)
5、Vector特有的遍历方式:使用elementAt()方法

|------Set
没有特有的遍历方式

2、Map
1、keySet():遍历set<键>
2、entrySet():遍历Set<Map.Entry>

3、常用的遍历方式
增强for循环:不使用循环变量
普通for循环:使用循环变量
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: