我是靠谱客的博主 干净板凳,最近开发中收集的这篇文章主要介绍Java基础(17)集合,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

十七.集合

集合:集合是一种容器  是用来进行数据存储的  并提供了丰富的方法  用来操作去所存的内容

集合与数组的区别:数组的长度是固定的,操作繁杂,开发起来效率低(写代码效率低)

集合则提供了很多方法用来操作所存内容操作简单 开发起来效率高(写代码效率高)

一.Collection类型集合的体系

二.Collection集合

1.能存什么内容

Collection集合  可以存储  Object类型的数据  对于其他没有做要求

2.有哪些实现类

collection集合  JDK仅仅提出了这样的一些标准规范,规定了这样的一个Collection集合

需要有什么方法 需要有什么特点  但是没有提供 官方的直接实现类  所以如果想使用Collection

结合的实现类,要么自己实现,要么使用间接实现类

3.常用方法

见API

三.List集合  超级重点

1.能存储什么内容

可以存储 object类型的数据  元素必须有序,有下标,是可以重复的

2.有哪些实现类

(1)ArrayList

他是在JDK1.2时出现的一种List集合的实现类

底层使用数组实现   效率高 线程不安全

(2)Vector     面试爱问 但是基本不用

他是JDK1.0时出现的一种List集合的实现类

底层使用数组实现  效率低  线程安全

(3)LinkedList

他是在JDK1.2时出现的一种List集合的实现类

底层使用链表实现   效率高 线程不安全

线性表——将数据进行连续的存储

数组 实际上的线性(连续)  查询快增删慢

链表  逻辑上的线性(连续)  查询慢增删快

这三种List集合的实现类  使用起来没有区别 但是在实现原理上存在区别

如果对于存储的数据  查询多增删少 用 ArrayList

如果对于存储的数据  查询时增删多  用LinkedList

3.List集合的常用方法

(1)增加

boolean add(E e) 默认往List集合末尾添加元素

void add(int index,E element)表示 向指定的下标位置添加元素

(2)查找

E  get(int index);通过下标来获取某个元素  返回值为获取到的元素

(3)更改

set(int index,E element); 第一个参数指的是  需要修改的元素下标

第二个参数是替换旧元素的新元素  返回值为被替换掉的元素

(4)删除

remove(int index);  通过指定下标  来删除某个元素  返回值为被删除的元素

remove(object obj);  删除第一个出现的  与参数内容相同的对象  返回值为是否删除成功 尽量避免与整数类型联用

(5)获取元素的个数

size() 返回值为元素个数  list集合元素  从0开始标号——size-1

注意:使用下标时,要使用合法的下标  比如查找时不能使用不存在的下标  

插入时不能使用大于元素个数的下标 ,

如果使用了不合法的下标会出现  java.lang.IndexOutOfBoundsException

4.泛型集合    以后凡是使用集合  必须添加泛型

如果我们想要一个集合中  只能存储指定类型元素  那么我们需要将该集合声明为一个泛型集合

集合名<泛型> 集合对象名=new 集合名<泛型>();

泛型:就是我们指定的该集合只能放置的数据类型,注意泛型想使用基本数据类型时,

一定是要包装类 因为集合中存储的应当是可以被Object类型管理的数据

例:

//创建一个list集合  专门用来储存管理学生对象

List<Student> list = new ArrayList<Student>();

list.add(new Student("五月",15,80.0));

list.add(new Student("大橙子",16,70.0));

list.add(new Student("小种子",17,90.0));

//list.add(new Dog("小孔",2));

//从今以后  一个集合中只存一种类型的数据  为了方便管理集合中的对象

List<Integer>  list2=new ArrayList<Integer>();

注意:

在JDK1.7之后,泛型结合的语法  可以写成以下形式;

集合名<泛型>  集合对象名=new 集合名<>();

List<Student> list = new ArrayList<>();

list.add(new Student("五月",15,80.0));

list.add(new Student("大橙子",16,70.0));

list.add(new Student("小种子",17,90.0));

五.List集合的遍历   非常非常重要

1.通过元素下标进行遍历

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

list.add("ABC1");

list.add("ABC2");

list.add("ABC3");

list.add("ABC4");

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

    String string=list.get(i);

    System.out.println(string);

}

注意:可以在下标遍历中进行元素的删除,并且如果向用remove(Object obj);删除元素时

JDK是根据equals方法的结果来验证两个是否是一个对象的,所以自定义类型记得重写equals

2.foreach遍历  非常重要

for(泛型类型  变量名a:目标集合){

}

例:

for(Student stu:list) {

      System.out.println(stu);

}

foreach遍历还可以做数组的遍历

for(数组类型 变量名a:目标数组){

}

例:

Student【】 stus={new Student("张三",15,80.0),new Studen("五李四",15,80.0)t,new Student("王五",15,80.0)};

for(Student student:stus){

     System.out.println(stu);

}

注意:可以通过foreach alt+/自动生成距离最近的集合或数组的foreach遍历

语法的含义:

每次只需for中的代码时,都会拿出一个元素,给变量a赋值,通过操作变量a间接操作每一个元素

从而达到遍历的效果

注意:

在进行foreach遍历时不要通过调用list对象的方法,进行元素的增加与删除

原因是foreach遍历实际上会在编译过后  变为迭代器遍历  而迭代器遍历存在  快速失败机制

3.迭代器遍历   不重要

a.获取迭代器

Iterator<Student> iterator=list.iterator();

b.通过迭代器的hasNext方法,搭配next方法进行遍历

hasNext方法:判断next标记是否还有内容

next方法:将被标记的内容返回 并将该元素使用remove标记  并将next标记移动到下一个元素

while(iterator.hasNext()){

     Student stu=iterator.next();

     System.out.println(stu);

}

c.通过迭代器的remove方法  可以删除remove标记所标记的内容

//使用迭代器的hasNext方法  可以验证当前的next标记是否标记在null上

while(iterator.hasNext()){

     Student stu=iterator.next();

     //删除remove标记所标记的元素  解决因为快速失败机制而不能使用list删除元素的方法  这样的问题

     if(stu.getName().equals("王五")){

          iterator.remove();

     }

}

for(Student student : list){

     System.out.println(student);

}

4.JDK1.8的自遍历  重要 可以简化很多书写内容

1.8后集合中多出了一个方法forEach方法  该方法的参数  是一个Consumer类型的参数

Consumer实际上是一个函数式接口:

public inerface Consumer<T>{

     void accept(T t);

}

我们可以实现Consumer接口 accept中的参数  就是每个元素 。方法的实现中就是对每个参数的操作的逻辑

(1)匿名内部类的实现:不推荐使用

Consumer<Student> consumer = new Consumer<Student>(){

     public void accept(Student t){

          System.out.println(t);

     }

}

list.forEach(consumer);

(2)使用Lambda来实现,推荐使用

Consumer<Student > consumer=(stu)->{System.out.println(stu));};

list.forEach(consumer);

或者

list.forEach((stu)->{System.out.println(stu);});

四.泛型  一般重要

1.泛型类

语法:

class 类名<T>{

     public T m1(T i){

           return null;

      }

}

当创建一个泛型的对象时,可以指定该泛型的类型,这时候,类中凡是使用泛型的地方都会被替换为指定类型

例:

class Myclass<T>{

     T i;

     public T m1(T i){

          return null;

     }

}

创建对象:

MyClass<String> mc=new MyClass<String>();

class MyClass<String>{

     String i;

     public String m1(String i){

          return null;

     }

}

所以使用T的地方都会变为String

2.泛型接口

语法:

interface 接口名<T>{

     public T test(T t);

}

在创建接口实现类时,可以指定接口的泛型 接口中凡是使用到泛型的地方,都会在实现类中替换成指定的类型

interface InA<T>{

     public T test(T t);

}

class Class implements InA<String>{

     pubic String test(String t){

          return null;

     }

}

3.注意

(1)如果没有指定泛型  那么泛型会被自动指定为Object

(2)泛型不可以参与实例化对象的语句,泛型只能用来做声明

以下为错误案例:

class Myclass<T>{

     T i;

     public T m1(T i){

          T t=new T();//错误

          T【】 ts=new T[] ;//错误         

          return null;

     }

}

(3)泛型不可以与instanceof关键字联用

以下为错误案例

class Myclass<T>{

     T i;

     public T m1(T i){

          if(i instanceof T){//错误

                    

          }

          return null;

     }

}

泛型存在着一种机制  泛型擦除

五.集合工具类

工具类往往放置的都是公开静态方法,这些公开静态方法都提供了独立的功能,帮助提高开发效率

1.Collections集合工具

reverse(List list);将目标集合的顺序倒置

shuffle(List list);将目标集合的内容乱序

sort(List list);将目标集合中的内容,按照某种规则升序排列,适用于可排序的类型,

实现了Comparable接口的类型JDK会提供他们的排序规则

sort(List list,Comparator c)第一个参数时目标集合  第二个参数时排序的逻辑

一般用于自定义类型  因为自动以类型JDK往往不会提供排序规则,自动以排序规则

六.Set集合

1.能存什么内容

可以存储Object类型的对象   元素是  无序  无下标  不可重复

2.有哪些实现类

(1)HashSet

JDK1.2出现  效率高  线程不安全

使用了散列结构来实现

存储自定义类型时  要重写hashCode方法 以及equals方法

为什么要重写hashCode?

为了保证内容一样的对象hashCode的返回值也好一样,继承而来的hashCode

返回值与地址有关,两个内容一致的对象地址不同,可能无法进入同一个hash桶  

从而无法发生去重验证

怎么重写hashCode?

让hashCode的返回值  进可能的与内容有关  保证内容一样的进入到同一个hash桶

为什么要重写equals?

继承而来的equals比较的是地址  我们需要比较的是内容

(2)LinkedHashSet

JDK1.4出现  效率高  线程不安全  是HashSet的子类

使用了散列结构  以及链表来实现   该链表是个双向链表  他会记录着存储的顺序

(3)SortedSet接口下的  TreeSet

JDK1.2出现  效率高  线程不安全

SortedSet接口  除了要求所存元素  是无序的 无下标  不可重复的以外   还要求了需要给所存元素进行排序

TreeSet 对所存元素进行排序

使用了红黑树结构来实现

3.常用方法

(1)增

boolean add(E e)  将一个元素放入set集合  插入成功则返回true  插入失败则返回false

(2)删

boolean remove(Obiect obj)  删除set集合中的该元素  返回值是否删除成功 成功true  失败false

(3)改

(4)查(只能查set集合的一些相关信息)

boolean contains(Object obj)  查询某个元素  在set中是否存在  如果存咋返回true  不存在返回false

int size() 获取元素的个数

4.Set集合的遍历

(1)foreach遍历   非常非常非常非常重要

for(泛型类型  变量名 : 目标集合){

     

}

每次会取出一个Set中的元素给变量赋值,通过操作该变量间接地进行遍历

for(String str:set){

     System.out.println(str);

}

(2)迭代器遍历 

a.获取迭代器对象

b.使用迭代器对象的next方法和hashNext方法进行取值

next方法:返回一个元素  并将标记向后传递

hasNext:查看当前标记内容是否为空

Iterator<String> iterator=set.iterator();

while(iterator.hasNext()){

     String next = iterator.next();

     if(next.equals("xxx")){

          iterator.remove();

     }

}

3.Set集合的自遍历  JDK1.8之后出现

1.8后集合中都多出了一个方法forEach方法  该方法的参数  是一个Consumer类型的参数

Consumer 实际上是一个函数式接口:

public interface Consumer<T>{

     void accept(T t);

}

我们可以实现Consumer接口  accept中的参数 就是每个元素  方法的实现就是对每个参数的操作逻辑

(1)匿名内部类实现  不推荐

Consumer<String> consumer = new Consumer<String>(){

     public void accept(String t){

          System.out.println(t);

     }

}

set.forEach(consumer);

(2)Lambda表达式 推荐

Consumer<String> consumer = t->System.out.println(t);

set.forEach(consumer);

七.Map集合

1.能存什么内容 很重要

Map集合存储的是键值对对象  键值对对象分为两部分 一部分为键(key)一部分为值(value)

键 key: 存储Object类型的对象  内容不可重复 且没有下标  无序  很像Set集合

值value:存储Object类型的对象  对其他无要求(可以重复 无下标 无序) 很像Collection集合

2.有哪些实现类

(1)HashMap

JDK1.2出现  效率高 线程不安全

(2)HashTable

JDK1.0出现效率低  线程安全

不允许键和值为null

     Properties

     JDK1.0出现  效率低  线程安全

     不允许键和值为null  常常和配置文件一起使用 是一种文档型的Map集合

为是么要重写键的hashCode?

在存放键值对时,需要使用键的hashCode来计算需要把键值对放置在哪个位置

继承而来的hashCode与地址无关  很有可能内容一致的键无法存入同一个hash桶

从而无法出发验证机制

怎么重写hashCode?

让hashCode的返回值,尽可能的与内容相关  保证内容一样的进入到同一个hash桶

为什么要重写equals?

继承而来的equals比较的是地址,我们需要比较的是内容

底层都以散列结构实现

(3)LinkedHashMap

JDK1.4出现  效率高 线程不安全

底层都以散列结构  与链表 实现 该链表也是双向链表  记录了键值对的存储顺序

(4)SortedMap接口下的TreeMap

SortedMap接口:对存储的键值对  按照键进行排序

TreeMap:对于SortedMap接口这种要求的实现 对键值对具有排序功能

TreeMAP底层也由红黑树实现

注意:TreeMap 与 TreeSet 去重时,不是使用hashCode与equals的去重机制,

而是以比较的规则作为去重机制

3.有哪些常用方法

(1)增   改

put(K key,V value); 将一对键值对存入Map集合  如果key已经存在 则将新的值替换掉老的值

会将替换掉的老值返回给调用者  如果返回null说明是添加操作

(2)删

V  remove(Object key); 通过键  删除某个键值对 返回被删掉键值对的值  如果该键不存在则返回null

(3)查

get(Object key)通过某个键  获取该键对应的值

size()获取所存键值对的个数

Set<K>   keySet()获取所有键 并把所有的键生成一个Set集合

Collection<V> values()获取所有值  并把所有的值生成一个Collection集合

Set<Entry<String,String>>  entrySet()获取所有的键值对  并把所有的键值对生成一个set集合

  

4.Map集合的遍历

注意Map集合没有直接的foreach遍历  foreach遍历遍历这种遍历方式是专门Collection类型的集合提供的

(1)键遍历

a.获取所有的键

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

b.通过所有的键获取所有的值  使用map集合的get方法

for(String key:keySet){

     String value=map.get(key);

}

(2)值遍历

注意  值遍历只能遍历值 不能通过值获取键

a.获取所有值

Collection<String> values=map.values();

b.遍历所有的值

for(String value:values){

     System.out.println(value);

}

(3)键值对遍历

a.获取所有键值对  键值对对象的类型是Entry<K,V> K设置的是键的泛型 V设置的是值的泛型

Set<Entry<String,String>>  set=map.entrySet();

b.遍历所有的键值对对象  拿到每个键值对对象后  通过其getKey来获取键值对的键部分  通过其getValue来获取值部分

for(Entry<String,String> entry: set){

     String key=entry.getKey();

     String value=entry.getValue();

     System.out.println("key:"+key+"value:"+value);

}

(4)Map集合的自遍历

Map集合在1.8之后  也有了一个forEach方法进行Map集合的自遍历  forEach方法需要一个BiConsumer对象

BiConsumer是一个函数式接口  有一个accept方法该方法有两参数

书写BiConsumer实现类时,两个参数分别代表K与V  accpet方法中书写的是对map遍历的逻辑

pubic interface BiConsumer<T,U>{

     void accept(T t,U u);

}

a.匿名内部类实现  不推荐

BiConsumer<String,String> biConsumer=new BiConsumer<String,String>(){

     public void accept(String t,String u){

          System.out.println(t+"-"+u);

     }

};

map.forEach(biConsumer);

b.Lambda表达式 推荐

BiConsumer<String,String>  biConsumer=(k,v)->System.out.println(k+"-"+v);

map.forEach(biConsumer);

散列结构

一种为保证增删效率与查询效率的数据结构  常见的形式是数组+链表

散列结构的称呼:散列 哈希 杂凑

一.名词解释

1.散列表/hash表:散列结构中的数组  就是所说的散列表/hash表

2.hash函数/散列函数:用来计算一个元素  应该存放在hash表中的哪个位置  

比如取余法(模地址法)对关键信息和hash表的长度进行取模操作  为保证

计算出的位置一定在hash表中

3.hash碰撞:当两个数据  计算出的hash表中的位置相同时,这种现象被称为hash碰撞

4.hash桶:为了解决hash碰撞  所以产生hash桶  一个hash桶中存储

了所有发生hash碰撞的元素  链表就是hash桶的一种实现方式(链地址法/拉链发)

二.散列存储数据的流程

1.获取关键数据

2.通过hash函数  计算该数据需要存放在hash表的哪个位置

3.如果没有发生hash碰撞  则放在该位置

4.如果发生了hash碰撞  形成hash桶(链表)

三.hashSet在储存数据时的流程

1.获取关键数据——通过元素的hashCode方法的返回值来获取

2.通过hash函数  计算该数据需要存放在hash表哪个位置

3.如果没有发生hash碰撞  则放在该位置

4.如果发生了hash碰撞  形成hash桶(链表)

形成链表时会触发去重的机制  新来的元素要个链表中每一个元素进行

equals  如果重复则不插入  如果不重复则插在链表末尾(JDK1.8)

而JDK1.7则会插入在链表的最前面

四.hashMap在存储数据时的流程

1.获取关键数据——通过键的hashCode方法的返回值来获取

2.通过hash函数  计算该数据需要存放在hash表哪个位置

3.如果没有发生hash碰撞  则放在该位置

4.如果发生了hash碰撞  形成hash桶(链表)

形成链表时会触发去重的机制  新来的键值对要  使用键和链表中每

一个键进行equals    如果重复替换掉重复键值对的值  如果不重复则插在链表末尾(JDK1.8)

而JDK1.7则会插入在链表的最前面

最后

以上就是干净板凳为你收集整理的Java基础(17)集合的全部内容,希望文章能够帮你解决Java基础(17)集合所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部