`
javawangzilong
  • 浏览: 55416 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

java集合

阅读更多
Java中的集合:
为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

集合是存储对象的一个工具。

集合和数组的特点:
  相同点:
  数组和集合都是容器。
  
  不同的:
集合:
  1,可以存储对象,只能存储对象
  2,集合的长度是可变的。
数组:
  1,可以存储对象,也可以存储基本数据类型。
  2,数据长度是固定的。

**容器对象有很多种,通过内部的数据结构来区分。
数据结构:就是一种数据存储的方式。

**容器在不断将共性向上抽取的过程中,就出现了集合体系结构。
该结构的顶层是一个接口,Collection。


Collection接口:
创建一个集合对象,也就是一个容器。
Collection coll = new ArrayList();

1,添加元素
  Add(); coll.add(“abc”);
2,删除元素
  Boolean b = coll.remove(“abc”);
3,获取集合的长度
  Int size = coll.size();
4,清除集合中的所有元素
  Coll.clear();
5,判断集合是否为空(其实依据的是size()是否等于0判断的)
  Boolean b = coll.isEmpty();
6,添加一堆元素
  coll.addAll(Collection co1);//添加的是一个集合
7, 判断一堆元素是否存在
  coll.containsAll(Collection co1);
8,删除一堆元素
  Boolean b = coll.removeAll(Collection co1);
9,获取两个集合的交集。
  Boolean b = coll.retainAll(co1);
  //retainAll会将coll和co1中相同的元素保留在coll中,所以coll中存储的就是交集的元素,当coll集合中的元素变化时,retainAll方法返回的是true,当coll集合中的元素本身就是交集元素,不发生变化,返回false。
10,Collection集合中对元素的获取方法。
  Coll.iterator();
   
  
**集合容器都具备取出方式,取出方式并不是一个方法。因为一个方法不足以完成取出功能。
取出是由多个功能来完成,为了方便使用,就将这些功能封装成对象。该对象在描述这些功能会直接使用到具体集合中的数据和集合特点。
所以这个取出元素的描述类,定义在了集合的内部。也就是一个内部类。
因为这个类直接访问集合中的数据,根据集合自身的数据结构特点。将具体的方法都定义完成后。需要将对象提供出去。让用户使用。所以暴露了一个方法来完成对这个内部类对象的访问。
为了提高扩展性,发现只要是容器,就具备取出功能。但是数据结构不同,取出的具体实现就不一样,这时为了扩展,就抽取出了一个接口。Iterator。

取出对象有两种表现形式:
1,Iterator it = coll.iterator();
While(it.hasNext()){
  System.out.println(it.next());
}
2,for(Iterator it = coll.iterator(); it.hasNext(); ){
  System.out.println(it.next());
}
第二种可以减少内存的消耗,因为第一种的it使用完之后还存在,而在for循环中,it出了for循环就不存在了


容器在进行添加的时候add();中的参数是object类型。
那么在取出的时候就要写成
Person p1 = (Person)it.next();
所以在进行迭代器使用的时候,next方法在循环中,建议只定义一个,定义多个会导致数据错误。当next方法没有获取到元素时,会发生NoSuchElementException;

**其实集合中存储的都是对象的引用。
获取迭代器后,迭代器中持有的也是元素的引用。




Collection
  |--List:该容器的元素是有序的 (存储的顺序和取出的顺序一致)
  该集合中的元素都有索引 (角标) ,该集合可以存储重复的元素
  |--ArrayList:底层数据结构是数组结构 不同步的,查询的速度很快
  |--vector:底层数据结构是数组结构 jdk1.0版本。 同步的
  |--LinkedList:底层数据结构是链表结构 不同步的,对元素的增删操作效率很高
  (vector和ArrayList区别?
  Vector相对于线程时安全的,同步的。ArrayList是不安全的
  )
  |--Set:无序,不可以存储重复元素。Set接口的方法与collection方法一致。
  Set没有特殊方法。Set接口取出元素方法只有迭代器。
  |--HashSet:底层数据结构是哈希表。哈希表这种结构,就是对哈希值的存储。而且 每一个对象都有自己的哈希值。因为object类中有个hashCode方法。
  (如何保证元素唯一性?
  通过判断元素的hashCode方法,和equals方法来完成的。当hashCode值相同,会再判断一次equals方法的返回值是否为true。
  如果hashCode值不同,就确定元素的哈希表中的位置,不同判断equals了。
  哈希表中有一个桶结构,每一个桶都有一个哈希值,当哈希值相同,但是equals为false时,这些元素都放在同一个桶中。
  )
  |--TreeSet:可以对set集合中的元素进行排序。
  数据结构是二叉树,这种结构,可以提高排序性能。
  (如何保证元素唯一性?
  是根据比较方法的返回值确定的,只要返回的是0,就代表元素重复。
  )
  
  
  
  
  
List:常用的共性方法。(继承了Collection接口)
1,添加元素。
  Add(index,element);//在索引位添加元素,其他元素依次顺延。
2,删除元素。
  Remove(index);//按照指定索引删除元素。被删除的元素会被返回。
3,修改元素。
  Set(index,element);//按照索引修改元素,被修改的元素会被返回。
4,获取元素。
  Get(index);//通过索引获取指定元素
  Get(element);//通过元素获取元素第一次出现的位置
  subList(fromIndex,lastIndex);//根据头尾角标获取子列表。
  
  通过List特有的方式,获取集合中所有的元素。(其实就是for循环)
  For(int x = 0;x < list.size(); x++)
  {
  System.out.println(list.get(x));
  }

**在进行迭代过程中,如果出现了迭代器和容器同时对元素进行操作的情况很容易引发
ConcurrentModificationException并发修改异常。
所以要么使用集合的方法操作元素,要么使用迭代器的方法操作元素,不要同时使用,
迭代器Iterator中只有三个操作,hasNext,next,remove,如果想进行添加,这个迭代器就不可以使用了,这时,可以使用一个新的迭代方式,ListIterator列表迭代器,ListIterator本身也是Iterator的接口,并且有更多的方法。

既然ArrayList底层是数组实现的,数组的长度是固定的,那么究竟是如何实现的呢?
ArrayList内部封装了一个默认长度为10的数组。当超出长度时,集合内部会自动生成一个新的数组,然后将原来的数组复制到新的数组中去。这就是导致ArrayList修改数据的效率比LinkedList慢的原因。

新的数组到底多长?
ArrayList 50%延长
Vector 100%延长

ArrayList判断元素是否相同,底层依据的是元素的equals方法。无论是contains还是remove都会去使用equals判断元素是否相同。所以在往ArrayList集合存储自定义元素时,最好建立该元素特有判断对象是否相同的依据。也就是需要覆盖equals方法。

LinkedList的特有方法:
1,
addFirst();
addLast();
在jdk1.6以后。
被offerFirst();
offerLast();替代
2,
getFirst(); 获取元素,集合的长度不改变
getLast();
在jdk1.6以后,被
peekFirst();
peekLast();替代。
3,
removeFirstt();获取元素,集合的长度改变
  如果集合中没有元素,那么该方法会发生异常NoSuchElementException
removeFirst();
在jdk1.6以后,被
pollFirst();
pollLast();代替。
如果集合元素没有,不会抛异常,而是返回null


Vector:vector中提供了一个独特的取出方式,就是枚举
Enumeration。此接口Enumeration的功能与Iterator接口的功能是重复的。
Enumeration的名称和方法的名称过程,书写比较麻烦,并且Iterator有个移除的方法。
所以被Iterator取 代。


**如果在编译的时候如果出现了
{
注意:TestArrayList.java 使用了未经检查或不安全的操作。
注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。
}
的提醒,并不是编译失败,是因为类型的原因导致的,如果用了泛型,就没有该提示了。


HashSet:
HashSet集合元素保证唯一性,依赖的是元素的hashCode方法和equals方法。
当元素的哈希值不同时,元素都有自己的独立位置。不需要再判断元素的equals方法,当元素的哈希值相同时,这时元素在哈希表中位置相同,这时就需要再判断元素的内容是否相同,就需要调用元素的equals方法进行一次比较。如果equals返回true,那么视为两个元素重复。只存储一个。如果返回false,那么这两个元素不是重复元素,会存储在同一个哈希值上。
为了建立自定义对象判断元素是否重复的依据。
需要覆盖hashCode方法,和equals方法。
而且最好依据对象的特有条件来建立hashcode和equals的实现。

ArrayList:判断包含,以及删除,都是依据元素的equals方法。
HashSet:判断包含,以及删除,都是依据元素的hashCode方法。当hashCode值相同时,再判断一次equals方法。


TreeSet:
TreeSet集合是用于给元素进行排序的。那么自定义元素本身不具备比较性,treeSet集合是无法对元素进行排序的。所以,在自定义对象时,需要对象具备一个扩展功能,用于比较的,而java已经提供了接口,可以让实现它的对系那个具备比较性。
那么自定义类,要想被treeSet排序,就要实现Comparable接口,以具备比较功能。

也可以将一个实现了Comparato接口的子类对象作为参数传递给TreeSet集合的构造函数即可,这样该集合就具备了比较功能。

TreeSet排序方式有两种:
1,让元素自身具备比较性
  其实是让元素实现Comparable接口,覆盖CompareTo方法。这称为元素的自然排序。
2,当元素自身不具备比较性,或者元素具备的比较性不是所需要的,定义一个比较器。
  其实就是定义一个类,实现Comparator接口,覆盖Compare方法。将comparator接口的子类对象作为参数传递给TreeSet的构造函数。

当元素自身具备比较性,同时TreeSet集合也具备比较器,这时以比较器为主。
所以建议使用第二种方法,比较灵活。

**一般在描述一个对象时,如果该对象封装了具体的数据,会出现很多这样的对象,这时就需要进行容器的存储。

那么描述该类对象时,一般要复写几个方法:
1,hashCode()
2,equals()
3,toString()
4,最好实现Comparable接口让该类具备自然排序功能。

建立对象自身判断是否相同的依据,同时让对象具备基本的比较性。



泛型:
泛型其实就是jdk1.5版本以后出现的一个安全机制。,泛型其实是给编译器使用的。
Al.add(3);//al.add(new Integer(3));因为jdk1.5之后有自动装箱,所以会自动把3装成对象。

集合中存储了不同类型的对象,取出时,容易在运行时时期发生classCastException类型转换异常。为了避免这个问题的发生,如果在存储的时候名气了集合要操作的数据类型,这样取就没有问题了。
就需要在定义集合时,就立刻明确元素的类型。
其实借鉴于数组。
可以通过<>来明确元素的类型。
ArrayList<String> al = new ArrayList<String>();

泛型的好处:
1,将运行时期出现的classCastException问题,转移到编译时期。
2,泛型的出现避免了强制转换的麻烦。

泛型的表现形式是<>;

什么时候使用泛型?
只要用到的类或者接口的旁边有<>的时候,就要明确具体类型。
泛型的使用其实就是给<>传递实际参数,而这个参数就是一个具体的引用数据类型。

什么时候使用泛型类?
当类要操作的引用数据类型不确定的时候,可以使用泛型来定义。
也就是定义一个类型参数。
具体要操作什么类型的对象,有使用该类的使用者来明确,将具体的类型作为实际参数传递给<>;

Class Tool<Q>
{
Private Q obj;
Public void setObj(Q obj){
  This.obj = obj;
}
Public Q getObj(){
  Return obj;
}
}

当泛型定义在类上,该泛型作用于整个类。当该建立对象时,就明确了具体类型。那么凡是使用了类上定义的泛型的方法,操作的类也就固定了。
当希望类中的方法,可以操作任意类型而不受类中泛型限制。
可以将泛型定义在方法上。泛型方法。
Public <Q> void print(Q q){
   System.out.println(“print”+q);
}


当类中定义static方法时,静态方法是不可以直接访问类上的泛型。因为类上的泛型只有通过建立对象才能明确具体类型。
所以静态方法如果操作的引用数据类型不确定,只能将泛型定义在方法上。
(静态方法上定义泛型,必须定义在static关键字之后)
Public static<W> void method(W w){
System.out.prinln(method+”w”);
}

当方法中操作的应用数据类型不确定,而且和对应的对象执行的类型也不一定一致。
这时就将泛型定义在方法上。


泛型接口:
1,
Class InterImpl implements Inter<String>{
Public void show(String s){
  System.out.println(s);
}
}
2,
Class InterImpl<T> implements Inter<T>{
Public void show(T t){
  System.out.println(“show”+t);
}
}

泛型:通配符?代表任意类型。
Public static void show(Collection<?> coll){
Iterator<?> it = coll.iterator();
While(it.hasNext()){
  System.out.println(it.next());
}
}


定义集合时要保证左右两边的类型一致。两边只有一边定义泛型,也是可以支持,至少新老版本兼容,但是一样会出现提示信息。

泛型限定:
定义T只能固定一种类型,定义?可以是任意类型,只想操作该类或该类的子类。要使用泛型限定。
? extends E:接收E类型或者E的子类型。
? super E:接收E类型或者E类型的父类型。
例如:
Public static void show(Collection<? extends Person> coll){
  Iterator<? extends Person> it = coll.itrator();
  While(it.hasNext()){
    System.out.println(it.next());
  }
}

集合框架中的另一个顶层接口:Map
Map集合的特点:
1,是一个双列集合,collection是单例集合
2,Map一次存一对元素,同时键值对的形式。建和值有对应关系,collection是一次存一个元素。
3,Map集合必须保证集合中键的唯一性。

Map集合中常见的功能:
1,添加
v  put(k , v);将k和v作为元素存储如map集合,当存入相同的k时,
新的值会覆盖原来的值,并返回原来的值。
void  putAll(map);
2,删除
Clear();
V remove(k):按照键删除,并返回被删除的键对应的值。
3,判断
Boolean containsKey(Object key)
Boolean containsValue(Object value);
Boolean isEmpty();
4,获取
Int size();获取map集合的元素个数
V get(k);通过键获取值。
Collection values();获取map集合中所有的值。
Set keySet():获取map集合中所有的键。
Set entrySet():获取的是键值的映射关系,将映射关系存入到set集合中。

Map集合没有迭代器。迭代器是collection集合具备的,Map集合的取出元素的原理就是将map集合先转成set集合,然后再进行迭代。

Map
  |--Hashtable:底层是哈希表数据结构(同步的,不允许null作为键,null作为值)
    |--properties:用于配置文件的定义和操作,使用频率非常高,同时键和值都是字符串。是集合中可以和IO技术相结合的对象。
  |--HashMap:底层是哈希表数据结构(不同步的,允许null作为键,允许null作为值)
    |--LinkedHashMap:可以保证hashMap存入顺序和取出顺序一致
  |--TreeMap:可以用来对map集合中的键进行排序。


如何获取集合中的所有元素?
一:
1,获取所有的键,再通过对所有的键进行遍历,在遍历中通过get方法获取每一个键的对应的值,使用keySet方法获取map集合中键的集合。
2,对set集合进行迭代器的操作。
Set<Integer> keySet = hm.keySet();
Iteraror it = keySet.itertor();
While(it.hasNext()){
Integer i = it.next();
String s = hm.get(i);
System.out.println(s+”...”+i);
}
二:
1,将map集合中的键值关系取出,并封装成一个键值关系对象,再存储到一个set集合中。
键值映射关系封装对象后的数据类型是map.entry(内部接口)
Entry就是一个map接口中的内部静态接口。
作为一个键值关系的数据类型存在。
使用entrySet获取map集合中的所有键值。
Set<Map.Entry<Integer,String>> entry = hm.entrySet();
Iterator<Map.Enrty<Integer,String>> it = entrySet.iterator();
While(it.hasNext()){
Map.Entry<Integer,String> me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+”...”+value);
}


hashMap:参考HashSet
存入的对象是无序的,想要保证有序。可以使用子类LinkedHashmap。存入和取出的顺序是一致的。

TreeMap:参考TreeSet


Utility:集合中的工具类:
如果有一堆元素。
要是元素重复,选择ArrayList集合,但是想要让元素按顺序排序,可以使用集合中的工具类。

工具类有两种。collections,Arrays
这两个工具类的特点:类中的方法都是静态的,不需要创建对象。


1,collections
Collections是集合对象的工具类,提供了操作集合的工具方法。

Fill(al,”kk”);将集合中的元素替换成指定的元素kk。

Reverse(al);集合元素反转,头尾对调

Swap(al,2,4);对集合中的元素进行位置的置换

Shuffle(al);对集合中的元素进行随机的位置置换

toArray();将集合变成数组
给toArray方法传递一个指定类型的数组。
当指定的长度小于集合的长度,该方法会自动创一个该类型的新数组长度和集合长度一致。用于存储集合中的元素,如果指定的数组长度大于集合的长度,那么该方法就不会创建新数组,而是使用传递进来的数组,存储完集合的元素后,其他的未存储的位置为null。
将集合变成数组后,限定了对元素的增删操作。

Xxx synchronizedList(xxx);可以将一个不同步的集合转成一个同步的list集合

2,Arrays
Arrays:是数组的工具类,提供了堆数组的工具方法。
asList(arr);将数组变成集合。
当数组变成集合后,就可以使用集合的方法来操作数组,而不用自己再定义指针进行数组的操作。(有些方法不可以用,只要是改变集合长度的方法都不能用,因为数组是固定长度的)

当数组中的元素时引用数据类型时,变成集合后,就将数组中的元素作为集合中的元素存在,当数组中的元素时基本数据类型时,变成集合后,会将这个数组变成集合中的元素。
List<int[]> list = Arrays.asList(arr);
System.out.println(list);



分享到:
评论

相关推荐

    java集合思维导图

    java集合 java集合思维导图 java集合总结

    【Java】Java集合框架思维导图。

    xmind格式的Java集合框架学习导图,包括Collection接口/Map接口以及具体实现类。 同样包含大厂面试题,也在导图中有所体现。 能学到什么: 更加成体系的知识框架,更加全面的、系统的知识。 思维导图: 思维导图具有...

    java 集合练习题

    键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台java 集合练习题

    java集合习题及答案

    java集合基础习题及答案,

    Java集合整体讲解

    Java集合整体讲解,其中包含了Collection,Map,Iterator和一些工具类,以及集合整体大框架

    java集合知识大全

    java 集合 List arrayList vector map set

    Java集合排序及java集合类详解.pdf

    Java 集合排序 及java集合类 详解.pdf

    Java基础篇:Java集合.pdf

    该文档主要详细总结了Java集合的相关知识,包括Collection和Map接口、Collection接口的子接口List和Set接口以及具体的实现类、存储原理等;Map接口的子接口HashMap、LinkedHashMap、TreeMap、Properties等

    Java 集合排序及java 集合类详解

    Java 集合排序及java 集合类详解,Java里面最重要、最常用也就是集合那部分了,能够用好集合和理解好集合对于做Java程序的开发拥有无比的好处。本教程详细解释了关于Java中的集合是如何实现的, 以及他们的实现原理...

    Java集合框架总结

    Java集合框架总结Java集合框架总结Java集合框架总结Java集合框架总结Java集合框架总结Java集合框架总结

    java集合框架面试题

    内含大量java集合框架方面常被面试官问到的经典面试题。

    Java集合排序及java集合类详解

    Java集合排序及java集合类详解,对list,set,map等java集合进行详细讲解

    Java集合框架.ppt

    集合是将多个元素组成一个单元的...Java集合框架,为我们提供了一套性能优良、使用方便的接口和类,我们不必再重新发明轮子,只需学会如何使用它们,就可以处理实际应用中出现的问题了Java集合框架位于java.util包中

    java集合资料整理

    关于java集合资料的整理 集合接口:6个接口,表示不同集合类型,是集合框架的基础。 抽象类:5个抽象类,对集合接口的部分实现。可扩展为自定义集合类。 实现类:8个实现类,对接口的具体实现。 在很大程度上,...

    Java集合框架详解

    Java集合框架详解Java集合框架详解Java集合框架详解

    java集合框架图

    java集合框架图java集合框架图java集合框架图java集合框架图java集合框架图

    Java集合详解,详细讲解java的集合类

    Java集合详解,详细讲解java的集合类,对java集合类的最详细的讲解。我自己的总结,保证大家看了很有收获

    java集合java集合java集合java集合java集合

    java集合

    java 集合分组与排序

    java 集合分组排序帮助类有好的意见可以互相交流不甚感激

Global site tag (gtag.js) - Google Analytics