java基础---集合篇

那年仲夏 提交于 2020-01-18 05:05:39

List集合

该添加方法是在集合的指定位置添加元素,指定位置原有元素的位置向后挪了一位(即下标加1):

List.add(集合下标,添加元素);(集合实现类:ArrayList()

 

该添加方法是将另外一个集合(参数)的元素添加到集合的结尾处:

List.addAll(Collection  c );

 

List集合的底层实现:

List集合的子类包括:ArrayList

底层使用的是:数组

注意:实现数组长度可变,指的是重新创建一个新的数组,长度大于旧数组

LinkedList

底层使用:链表结构

特点:每一个元素,前半部分是具体的值,后半部分是地址值

 

List集合的特点:

元素可重复,不唯一,有序(添加顺序/索引顺序/先后顺序)

集合只能存储对象或引用数据类型,基本数据类型不允许存放在集合当中。

当集合添加基本数据类型的时候,会自动装箱(将基本数据类型转换成引用数据类型)。

引用数据类型可以使用“==”和equals()方法比较,使用equals()方法比较集合元素是否重复。

 

List集合输出的三种方式:

标准for循环,增强for循环

以及迭代器(重点):(集合中的标准输出方法)

System.out.println("==============迭代器输出===================");
//获取迭代器----List集合当中存在一个方法----iterator()  返回值类型是Iterator
Iterator<Integer> iter=list.iterator();
//借助while循环语句
while(iter.hasNext()){
    System.out.print(iter.next()+"\t");
}

迭代器常用的三个方法:

判断是否有下一个元素:hashNext() 获取当前元素:next() 移出当前元素:remove()

 

泛型的设置:

位置:可以在类上以及接口设置泛型,泛型的形式<T>

T:输入具体的数据类型,则此时的T就代表什么类型,特点:对集合和接口等增加了约束。

泛型的应用:可以应用在方法上,类以及接口上。

 

理解面向接口编程:

接口的作用:添加约束,本质是一个契约,需要遵守:如果你是。。。则必须能。。。的思想

 

Collection集合:

Collection的定义:

此集合是集合框架当中层次结构的根集合。

Collection表示一组对象,这些对象也称为collection的元素。

public interface Collection<E> extends Iterable<E>

虽然Collection集合作为跟集合存在,但是他也有一个父几口,就是Iterable(迭代器)接口。

 

特点:

不唯一:说明集合元素可以重复,并且打印输出集合元素的时候,也会跟着输出

无序:不是按照添加元素,也不是按照自然顺序(升序/排序)

 

Collection和它的子集合List和Set集合:

(凡是list集合以及set集合的实现类,都是collection集合的实现类)

List:子集合大量的扩充父集合当中的方法,子集合存在很多父集合当中没有的方法。

eg:List.add(int index,E e);list.remove(int index);

Set:set集合基本上没有扩充父集合当中的方法

 

Collection当中的一些常用方法:

添加元素的方法:add(E e) addAll(Collection c);

删除元素的方法:remove(Object obj)

修改元素的方法:Collection集合没有,不过list集合中存在set()方法

获取元素的方法:Collection集合没有,不过list集合中存在get()方法

获取迭代器的方法:Iteration()方法

获取集合容量大小:size()方法

清除集合元素的方法:clear()方法

 

ArrayList集合:(重写List)

List集合的底层使用的是长度可变的数组。

实现长度可变的数组--此处的数组并不是指的同一个数组,而是创建新数组,新数组的长度是就数组的2倍,把旧数组的元素重新赋值给新数组。

 

空数组,表现形式:

int[] arr = null;  代表的是在栈内存当中声明数组,没有在堆内存当中开辟空间

int[] arr = {};   代表的是数组元素个数为0;

 

根据jdk当中的ArrayList集合,初始容量是10个,所以在自定义ArrayList类的时候,写空参构造方法,需要指定容量,其实就是调用另外一个有参构造方法

 

LinkedList集合:

LinkedList集合的定义:

使用连接列表实现list集合接口的类,叫链表类。(此实现不是同步的)

底层使用的是链表结构:

优点:插入删除元素效率比较高

缺点:遍历和随机访问元素效率低下

常用方法:

添加元素:

add(E e)

        add(int index E e)

        addFirst(E e)

        addLast(E e)

删除的方法:

remove(E e)

Remove(int index,E e)

removeFirstr()

removeLast()

获取的方法:

get(int index)

getFirst()

getLast()

修改的方法:

public E set(int index,  E element)

获取但不异常此列表的头(第一个元素)

public E peek()  public E element()

获取并移除此列表的头(第一个元素)

public E poll()

 

Set<E>集合:

定义:

一个不包含重复元素的集合,更确切的说,set不包含内容相同的元素,并且最多包含一个null元素,就是说也可以存null

特点:无序且唯一

常用的一些子类有:

HashSet:采用Hashtable哈希表存储结构,优点:添加查询删除速度快,缺点:无序(☆)

LinkedHashSet:采用哈希表存储结构,同时使用链表维护次序(有序:添加顺序)

TreeSet:采用二叉树(红黑树)的存储结构

优点:有序 查询速度比list快(按照内容查询)

缺点:查询速度没有hashset快

Set集合的底层原理有哪些结构完成:

第一种:使用哈希表---HashSet

第二种:使用二叉树--TreeSet

链表结构+哈希表接口----->保证元素的有序和唯一,此处的有序指的是添加顺序。

二叉树结构-----> 保证元素的有序和唯一,此处的有序指的是自然顺序。

自然顺序: 如果是数值型,则从小到大;如果是字母,则按照从a--z的顺序;如果是汉字,则按照Unicode编码表中的顺序进行排序

List集合的特点:要求元素不唯一而且有序!

 

Set集合的常用方法:

增加元素

add(E  e )

特点: 没有在指定位置进行添加的方法   List集合当中存在一个

删除元素

remove(Object o); 按照元素的内容进行删除

注意: 没有按照索引位置进行删除的方法,List集合当中存在一个

修改的方法,Set集合没有

获取元素的方法----get()方法,Set集合也没有

注意: 推论,既然没有get方法,那么能够使用标准for循环进行遍历Set集合!

判断是否为空   ---  isEmpty()

获取迭代器      ---   iterator()

注意: 推论  凡事属于Collection集合的子集合,都具备迭代器输出的功能

获取集合容量大小/获取集合元素个数---size()方法

集合转换数组的方法

Object[] toArray()

该方法的参数是个数组(你想转换成啥类型的数组,长度为set集合的长度),这样下边那个转换数组的方法返回的数组就是你声明的这个数组,实际上就是提前给这个方法声明个容器

T[] toArray(T[] t);

注意:1. T代表的是Type单词的缩写,指的是数据类型

  1. 在进行传参的过程当中,必须是一个具体的,在堆内存当中开辟空间的数组。

 

特性:(HashSet为例)

在添加某些对象时,可以添加匿名对象,好处: 不用再单独创建对象了,直接是以实参的方式进行传递。(“new Test();”这就是一个匿名对象,但是,在Java一般不这么使用,因为没有意义,因为这样写完后,由于没有对该对象进行引用,所以马上就被内存回收了,所以没有实际意义)

 

在创建集合时,对集合进行遍历输出,推荐使用迭代器输出,原因: 迭代器专门为集合而生!

凡事属于Collection集合的子集合,都具有迭代器的功能/方法

关键问题: 在编写迭代器时,泛型的类型要和集合的泛型保持一致!

 

对于重复元素,Set集合要保持元素的唯一性,但是我发现,在使用Student类充当泛型时,重复元素可以打印输出。

原因:Student类没有重写equals()方法和hashCode()方法,对于JDK存在的类,例如Integer Double String等类,

已经重写了equals()方法和hashCode()方法。

 

LinkedHashSet子类的特点

采用哈希表存储结构,同时使用链表维护次序(有序(添加顺序))

常用的方法----基本上都是继承而来的方法

添加的方法

 add(E  e) --- 继承Set接口当中的方法

删除的方法

remove(Object obj)

迭代输出的方法

iterator()

TreeSet集合:

TreeSet的定义:

此类是以二叉树的存储结构,按照子软顺序进行排序的一个集合子类!

TreeSet集合的特点

效率问题: TreeSet执行效率要高于List集合,但是低于HashSet集合

有序而且元素唯一: 有序   (自然顺序)

常用方法

添加的方法

add(E  e)

删除的方法

remove(Object o);

通过元素的索引值进行获取元素---get(int index)

听过元素的索引值进行修改元素---set(int index)

清除集合当中所有的元素----clear()

比较的方法---comparator()

注意: 此方法的返回值类型是Comparator接口,它是一个内部比较器

外部比较器----Comparable

判断是否包含指定的元素---- contains(Object o)

返回Set集合当中的第一个元素----public E first();

返回Set集合当中的最后一个元素----public E last()

 

内部比较器----Comparable接口

此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。

返回结果,分别返回不同的数据:
如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数

发现:此接口,只存在一个抽象方法,此方法的定义如下:

public  int  comparaTo(Object obj); 比较此对象与指定对象的顺序。

分析: 此接口为什么叫内部比较器?

原因: 1.从字面意思上理解,肯定还有一个外部比较器---Comparator<T>

   2.在集合当中,有的集合对元素要进行排序----特指的是Set集合当中,TreeSet要求按照自然排序

在去使用此集合的时候,泛型类型都自动的实现了此接口,例如: Integer  String  Double类等

自定义类来充当集合的泛型,如果对其进行排序(内部自动的排序),则此类也要实现Comparable接口,否则会出现ClassCastException

 

MAP集合:

获取所有的value值,把他们存放大Collection集合当中

public Collection<v> values();

直接获取键和值,而不是分开获取的方法

public Set<Map.Entry<K,V>> entrySet()

注意: 发现此方法,返回的是Set集合

发现: 如果把Map集合当中所有的元素放到Set集合当中,发现不妥,也就是说不能把包含键值对的元素放到Set集合当中,因为Set集合只能存储单值元素

解决:Set集合是否可以编写泛型----可以的

  Map集合当中有一个嵌套的子集合---Entry<K,V>

换句话说: 把Set集合的泛型,改为Entry<k,v>

      格式: Set<String>  Set<Integer>  ---- 发现:String  Integer都是属于类

 Set<Entry<k,v>>  -----发现:Entry<K,V>是接口形式存在

结论: 泛型的类型,可以是引用数据类型,其中包括: 类和接口

遍历map集合的两种方式:

第一种: 单独的获取所有的key  和   value

第二种: 使用entrySet()方法,把Map集合转换成Set集合,再通过迭代器输出

 

LinkedHashMap类:

底层使用到了链表+哈希表。

特点: 解决了Map集合存储数据以及遍历集合时,无序的状态 --- 按照添加元素/先后顺序。

注:在编写泛型类型的时候,只允许编写引用数据类型的数据,不能写基本数据类型。

此处JVM是不会吧int进行包装,变成包装类。

 

TreeMap:有序(自然顺序)

TreeMap类底层使用了二叉树(红黑树)结构,会自动的对产品进行排序。

使用TreeMap集合,是有序的,而且这个有序指的是自然顺序---从小到大的顺序

String类型,怎么看从小到大?

如果字符串当中存在多个字符,第一次进行比较是,会按照第一个在Unicode编码表中出现的位置,进判定

 

Iterator接口的子接口----ListIterator:

两者之间的关系

从定义可知,他们是继承关系,也就是说Iterator是父接口,-ListIterator是子接口

public interface ListIterator<E> extends Iterator<E>

ListIterator和Iterator的区别

相同点:

功能相似,都可以对集合进行遍历

可以产生一个迭代器对象

不同点:

使用范围不同

Iterator可以应用于更多的集合,Set、List和这些集合的子类型。

而ListIterator只能用于List及其子类型。

遍历顺序不同

  Iterator只能顺序向后遍历; ListIterator还可以逆序向前遍历

Iterator可以在遍历的过程中remove();ListIterator可以在遍历的过程中remove()、add()、set()

ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

 

集合操作类---Collections:

常用方法:

说明: 对于某些方法,里面的参数类型,只能是List集合,体现出了集合工具类的局限性。

例如: 排序----只针对List集合有效,其他集合无效

二分搜索法----只针对List集合有效,其他集合无效,此方法的前提,必须要保证List集合是自然顺序(从小到大)进行存储数据。

查询元素,如果存在则返回元素在集合当中的索引值
int index=Collections.binarySearch(list, 11);

排序的方法---局限性只能是List集合
Collections.sort(list);

复制集合的方法:

注意点:
*   1.List集合对象,默认的初始容量是10
*   2.目标列表(list)的长度至少必须等于源列表
*   3.目标集合必须要有元素,而且元素的个数不能少于源集合(list4)

实际操作就是吧list4中的元素复制到了list中,如果list4中有三个元素,list中有9个元素,那么list4中的三个元素在list中下标为0,1,2这三个位置上,原位置数据没了,等于覆盖了。

Collections.copy(list, list4);

求最大值和最小值
int max=Collections.max(list);
int min=Collections.min(list);

集合元素输出时进行反转
Collections.reverse(list);

线程安全化 ---- ArrayList类,特点: 重效率轻安全
List<Integer> list3=Collections.synchronizedList(list);

填充的方法(该方法会把list集合中的元素全部替换成520,慎用)
Collections.fill(list, 520);

 

外部比较器:

(Bean1是我创建的一个类,hp是类中的属性)

直接调用sort会出现编译错误,因为Bean1有各种属性
到底按照哪种属性进行比较,Collections也不知道,不确定,所以没法排
所以,即使使用的是List集合,也不太确定到底是按照什么顺序和属性进行排序的
此时,需要指定一个外部比较器,来确定排序规则。

Comparator<Bean1> h = new Comparator<Bean1>(){
    @Override
    public int compare(Bean1 h1, Bean1 h2) {
        //按照hp进行排序
        if(h1.hp>=h2.hp)
            return 1;  //正数表示h1h2要大
        else
            return -1;
    }
};

写完排序规则后,再次调用排序方法,这时候则就会开始从大到小排序了

Collections.sort(list,h);该list是要排序的集合,h是外部比较器,也就是上边的那个

 

 

 

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!