Java中的集合

存储对象可以使用数组或者集合

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

1LinkedList类的特有功能:

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

1Set元素是无序的(取出时的顺序与存入时的顺序不一致不可存储重复值),不可重复的集合

2Set接口是Colletion的子接口,继承了Collection的所有方法 

3、特点

取出时的顺序与存入时的顺序不一致

不可存储重复值(需要重写hashCode()equals()方法) 

4、要求添加进Set中的元素所在的类,一定要重写equals()hashCode()方法。进而保证Set中元素的不可重复性!其中hashCode()方法降低哈希值的重复率,equals()方法比较元素的值 

5HashSet(主要实现类)、LinkedHashSetTreeSet 

6、向HashSetLinkedHashSet中添加对象时,首先调用此对象所在类的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、只对""进行排序;

3TreeMap存储对象时键需要保证唯一性,


HashMapHashtable的区别

1java.util.Hashtabel

1、内部使用哈希表实现

2、不允许使用NULL键和NULL

3、线程安全,效率低(同步的)

4、从JDK1.0开始

 

2java.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

|------不需要排序:使用HashMaplinkedHashMap

|------需要排序:TreeMap


多种集合的遍历方式

1Collection

1toArray()

2、迭代器

3、增强for(常用)

 

|------List

4、特有的遍历方式:使用Collectionsize()Listget(intindex)(常用)

5Vector特有的遍历方式:使用elementAt()方法

|------Set

没有特有的遍历方式

 

2Map

1keySet():遍历set<>

2entrySet():遍历Set<Map.Entry>

 

3、常用的遍历方式

增强for循环:不使用循环变量

普通for循环:使用循环变量






 

 


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值