java基础--笔记16


对象:封装数据;
集合:封装对象;

数组和集合类同时容器,有何不同
     数组虽然也可以存储对象,但长度是固定。集合长度是可变的。
     数组中可以存储基本数据类型。集合只能存储对象。

集合框架为什么会出现这么多的容器?
因为每一个容器对数据的存储方式都不同。这个存储方式称之为:数据结构。

集合中存放的不是对象实体。和数组一样存的是引用(地址)。
add方法的参数类型是object,以便于接受任意类型对象。


Iterator迭代器原理
由于集合容器有很多,每个容器都有自身的数据存储结构,即每个容器自身最清楚自己中数据是如何存储的,容器这么多,每个容器数据存储又不相同,这时就在它们之间找取出元素的共性进行了抽取,抽取出集合容器取出元素的共同特点。
在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
集合中把这种取元素的方式描述在Iterator接口中。

for (Iterator it = coll.iterator(); it.hasNext();) {
System.out.println(it.next());
       }

注意:在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会发生java.util.NoSuchElementException没有这个元素异常


所有的Collection的具体容器的对象都有公共的取出元素的方式。就是Iterator。

阅读api文档发现Collection这个根接口中分了很多种情况。
1,有允许重复的,有不允许重复的
2,又可能是有序的,也有可能是无序的
提供了更为具体的字接口来完成集合划分。
子接口:
List:有序(存和取的顺序一致)的集合,可以通过索引操作元素,允许有重复元素。
Set:不允许有重复元素。

List的特有功能都是围绕索引展开的。
正因为有索引:
增:add(index , element)
删:remove(index)
改:set(ndex , element)
查:get(index) indexof(index , element)

获取所有元素:迭代器,索引遍历
在迭代过程中,出现其他的修改方式比如list.add();导致了不确定性。
List与个特殊的迭代器ListIterator,它能完成在迭代的时候插入和替换元素。

 列表迭代器:
* 1,是迭代器的子接口。
* 2,是List接口特有。
* 3,可以完成迭代过程中的增删改查。

了解一下List集合的具体子类,明确具体的数据结构区分。目的是在开发时,使用哪个容器更合适。

ArrayList:内部数据结构:大小可变数组,不同步,替代了Vector,查询较快。

Vector:内部数据结构:可增长的数组,是可同步的。查询,增删都慢。

LinkedList:内部数据结构:链接列表(链表),不同步的。增删较快。

两种简单的数据结构:
堆栈:先进后出,first in last out FILO
队列:先进先出,first in first out FIFO


面试题:用LinkedList完成一个队列结构。
//创建一个队列容器描述。



哈希表这个容器只能存 对象。
哈希表:存储的元素和哈希值的多个对应关系。
查询效率比数组高,不可以存储重复元素。
当两个元素哈希值相同时,称之为哈希冲突。继续判断元素内容是否相同,如果相同,视为重复元素,不存。如果不相同,存储,继续进行算法运算,拉链法。

存储过程:每一个对象在往哈希表中存储时,必须调用该对象的hashcode方法,获取其哈希值,添加时,判断该值是否有元素,如果有,继续用该对象的equals方法判断和已存在的元素内容是否相同,如果相同,不存。
尽量保证元素的哈希值不同,为了避免判断equals,而影响效率。

记住:对象往哈希表中存储时,必须重写hashcode和equals
HashSet:数据结构是哈希表,是不同步的。保证元素唯一的方式:判断元素的哈希值是否相同,以及相同后再次判断equals是否相等。

当需要保证元素唯一性,提高效率,且有序时,可以用HashSet的子类LinkedHashSet。

Collection中的contains 方法内部使用的是元素的equals方法在比较。
List中的contains方法内部也使用的是元素的equals方法在比较。
String中contains比较的是字符串内容。
String类中的equals比较的对象的内容是否相同。


Set:无序,不可以重复元素。
HashSet:数据结构是哈希表。线程是非同步的。保证元素唯一的方式:判断元素的哈希值是否相同,以及相同后再次判断equals是否相等。
TreeSet:可以对Set集合中的元素进行排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0。
       TreeSet集合排序功能,要求存放到集合中的元素必须具备比较功能。当对象具备比较功能之后,这时再给集合中存放元素时,集合就会调用对象的比较方法,从而确定对象的大小,进行排序。

TreeSet排序的第一种方式:让元素自身具备比较性。元素需要 实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或默认顺序。
记住:排序时,当主要条件相同时,一定要判断下次要条件。

TreeSet的第二种排序方式:当元素不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
可以定义一个 比较器Comparator,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
使用第二种方式时,定义一个类, 实现Comparator接口,覆盖compare方法。

记住:只不过二叉树结构使用了这两种比较方式,其他地方也能用着两种比较方式。

在使用迭代器时,类型有时候需要强转,是因为需要使用自己特有的方法。

foreach循环(底层是迭代器)
  格式:
  for( 集合或者数组的元素类型  变量名 : 集合或者数组容器名 ){}

  高级for循环只能遍历Collection集合或者数组,但无法去操作数组或者集合空间。它仅仅就是为了遍历数组和集合而生。

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

泛型:JDK1.5版本后出现的新特性。用于解决安全问题,是一个安全机制。
好处:
1,将运行时期出现的问题ClassCastException,转移到了编译时期。方便于程序员解决问题,让运行时期问题减少,安全。

2,避免了强制转换麻烦。

泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,只要见到<>就要定义泛型。
其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>即可。

什么时候需要定义泛型类
当类中要操作的 引用数据类型不确定的时候,早期定义Object来完成扩展。现在定义泛型来完成扩展。

泛型不仅可以定义在类上,还可以定义在方法上
泛型类定义的泛型,在整个类中有效。如果被方法使用,泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。

特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。定义在方法上书写格式要将泛型放在返回值类型的前面修饰符的后面。

泛型定义在接口上
泛型限定用于泛型扩展。向上限定,向下限定。
? extends E :可以接受E类型或者E的子类型。上限
? super E :可以接受E类型或者E的父类型。 下限

注意:使用泛型时,两边的泛型类型一致。当具体实际参数不确定时,可以传递一个通配符 ?(实参,而且必须放在<>中) 或者自定义泛型参数方式。两者的区别在于,如果要对具体的实参内容进行操作,需要用自定义泛型参数的方式。如果不对具体的实参进行操作,用?就可以了。

List:有序,可以通过索引操作元素,元素可以重复
     |-- ArrayList:内部数据结构为大小可变数组,不同步,查询快
     |-- LinkedList:内部数据结构为链表,不同步,增删快
     |-- Vector:底层数据结构为数组,同步,什么都慢。

Set:元素不可以重复
     |-- HashSet:数据结构是哈希表,不同步,保证元素唯一性的方式是判断元素哈希值,哈希值相同再通过equals判断,一样则不存。
                    |-- LinkedHashSet:不同步,有序,效率高。保证存和取得顺序一致。

     |-- TreeSet:可以对Set集合中的元素进行排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0.

总结:看到Array就要想到是数组结构,具备角标,可以根据角标操作数据。增删慢,查询快。
Linked,就要想到底层是链表结构,增删快,查询慢。有头有尾。根据头尾进行操作。
Hash,就想到底层数据结构是哈希表,要保证元素唯一必须复写hashCode和equals方法。
Tree,就想到底层是二叉树结构,要保证元素唯一,对象的comparaTo方法或者使用集合的比较器中的compare方法。参看比较方法的返回值是否return 0.

查看API的时候注意事项:
     针对集合而言,类名末尾的单词表示这个集合的所属体系,前面的表示集合的数据结构。从JDK1.2以后所有的集合都是不同步。
     以后给集合中存放自定义对象时,一般都需要复写HashCode和equals方法,有时也需要复写toString。
     如果需要元素自身具备比较功能,还需要实现Comoarable接口。


★★★★★
List<Person> list = new ArrayList<Person>();
addElement(list, new Student("lisi", 21));
addElement(list, new Worker("xiaoqiang1", 12));
System.out.println(list);
public static <T> void addElement(List<? super T> list, T element) {
list.add(element);
}
解析:List<Person> list = new ArrayList<Person>();表示创建的List集合里面元素的类型为Person类型。当运行到ddElement(list, new Student("lisi", 21));时,调用public static <T> void addElement(List<? super T> list, T element)函数,这个函数明确了接受的类型为List集合。由于元素不确定类型,当Student类型传进来后,T的类型也就是Student类型,泛型? Super T表示这个容器只能接受T或者T的父类(Person)。

若将super换成extends,T element就确定了元素的类型,而<? extends T>表示容器只能接受T或者T的子类,容器的类型不清楚为?。(List<? extnds T> list, T element)已经确定了元素T的类型,而容器的类型为T或者T的子类类型,再传进来T元素,若容器类型成T的子类类型,显然是不可以存储的。

关于System.out.println(list);为何能将集合中元素全部输出,是因为ArrayList继承了List的toString方法,而集合中的toString已经把Object中的toString复写。底层采用的是迭代器和StringBuilder,将元素全部转成字符串存放着。

public   static   <T   extends   Comparable<?   super   T>> T getMax_2(Collection<?   extends   T> coll) {
               // 1,定义一个变量用于记录较大的值。初始化为容器中的一个元素。
            Iterator<?   extends   T> it = coll.iterator();
            T max =  it.next();

               while   (it.hasNext()) {

                  T temp = it.next();

                     if   (temp.compareTo(max) > 0) {
                        max = temp;
                  }
            }
               return   max;
      }


解析:
public   static   <T  extends  Comparable<?  super  T>> T getMax_2(Collection<?  extends  T> coll)

定义这个获取最大值的函数时,由于不确定是什么容器中获取最大值,故将容器定义为泛型,用T表示要接受的容器类型。所以要先定义下T,然后再放在中用到了compareTo方法,只有实现了Comparable接口才能使用compareTo方法所以T必须是Comparable的子类  即 extends  Comparable 。是泛型定义的写法,与接口实现写法无关。而Comparable的类型可以是T类型,也可以是T的父类型。因为T的父类型的Comparable,T也能使用。即  Comparable<?  super  T>。获取到最大值后,返回去的元素的类型也是T类型。
Collection<?  extends  T>表示的是,这个容器可以接受T或者T的子类型,增加了扩展性,与限定,其实直接写T也一样。因为一个容器肯定可以装自己或自己的子类。


public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
//之所以extends Object,是因为,返回必然是集合中的元素,如果没有明确Object,会认为返回的是Comparable类型的子类。
//其实是,但是Comparable是接口,正常理解为返回的应该一个是对象,对象的最终类型是Object。为了便于阅读,就显示的指定了extends Object。
集合工具类Collections
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值