Java学习笔记:集合

概述:提供一种存储空间可变的存储模型,存储数据容量可以随时发生改变


2021-01-23_214915.jpg
单列:                 双列
张三                   itcast   张三
李四                   itcast2 李四
王五                   itcast3 王五
单列可重复:           单列不可重复:
张三                   张三
李四                   李四
张三

ArrayList

ArrayList
可调整大小数组
是一种特殊数据类型、泛指 eg:ArrayList;ArrayList

ArrayList构造方法和添加方法

public ArrayList()创建一个空的集合对象
public boolean add(E e)将指定元素追加到此集合的末尾
public void add(int index,E element)在集合中的指定位置插入指定元素

ArrayList array = new ArrayList<>();
array.add("hello");
array.add("world");//此时array为[hello,world]
array.add(1,"javase");//此时array为[hello,javase,world]
array.add(4,"javase");//此时报错,显示结合越界

ArrayList集合常用方法

array.xxxxxx来调用,以下index都会出现越界报错
public boolean remove(Object 0)删除指定元素,返回删除是否成功
public E remove(int index)删除指定索引处元素,返回被删除元素
public E set(int index,E element)修改指定索引处元素,返回被修改元素
public E get(int index)返回指定索引处元素
public int size()返回集合中的元素个数

Collection

Collection集合概述和使用

Collection集合概述

  • 单例集合顶层接口,表示一组对象,这些对象也被成为collection的元素
  • JDK不提供该接口的直接实现,而是提供更具体的子接口(如Set和List)实现

创建Collection集合的对象

  • 多态的方式
  • 具体的实现类ArrayList
    Collection c = new ArrayList();

Collection集合常用方法

  • boolean add (E e):添加元素,返回boolean类型结果显示添加是否成功
    c.add("hello");c.add("world");//输出c为[hello,world]
  • boolean remove(Object o):从集合中移除指定的元素,返回boolean类型显示是否成功
    c.remove(hello);
  • void clear():清空集合中的元素
    c.clear;
  • boolean contains(Object o):判断集合中是否存在指定的元素,返回boolean类型结果
    c.contains("world");
  • boolean isEmpty():判断集合是否为空
    c.isEmpty();
  • int size():返回集合的长度,也就是集合中元素的个数
    c.size();

Collection集合的遍历

iterator:迭代器,集合的专用遍历方式

  • Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
  • 迭代器通过集合iterator()方法得到,所以我们说它是依赖于集合而存在的

Iterator中的常用方法

  • E next():返回迭代中的下一个元素
  • boolean hasNext():如果迭代具有更多元素,则返回true
Collection c = new ArrayList();//创建集合对象
String s = "hello";//创建元素
c.add(s);//添加元素到集合
c.add("world");//添加元素到集合
Iterator(String) it = c.iterator();//通过集合对象获取迭代器对象
while(it.hasNext()){
      String s = it.next();
      System.out.println(s);//先输出hello,再输出world
}

List

List集合概述和特点

List集合概述

  • 有序集合,用户可以精准控制列表每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中元素
  • 与set集合不同,列表通常允许重复的元素

List集合特点

  • 有序:存储和取出的元素顺序一致
  • 可重复:存储的元素可以重复
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("hello");// 元素可重复
Iterator it = list.iterator();//List继承自Collection,可以用迭代器方式遍历
while(it.hasNext()){
     String s=it.next();
     System.out.println(s);
}

List集合特有方法

Collection没有,但是ArrayList,LinkedList有

  • void add(int index,E element):在此集合中的指定位置插入指定的元素
  • E remove(int index):删除指定索引处的元素,返回被删除元素
  • E set(int index,E element):修改指定索引处元素,返回被修改的元素
  • E get(int index):返回指定索引处的元素

并发修改异常

Iterator it = list.iterator();
while(it.hasNext()){
     String s=it.next();
     //用迭代器获取元素时modCount(实际修改值)和expectedModCount(预期修改值)会比较是否相同
     if(s.equals("world")){
           list.add("javaee");//单独添加元素会使集合中元素长度改变,造成两值不一致,进而抛出异常
     }
     System.out.println(s);
}
//会抛出ConcurrentModificationException的异常
修改为
for(int i=0;i

ListIterator(该集合特有遍历方式)

ListIterator:列表迭代器

  • 通过List集合的listIterator()得到,所以说它是List集合特有的迭代器
  • 运行程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,别获取列表中迭代器当前位置

ListIterator中常用方法
E next():返回迭代中的下一个元素
boolean hasNext():如果迭代具有更多元素,则返回true
E previous():返回列表中的上一个元素
boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
void add(E e):将指定的元素插入列表

List list=new ArrayList();
......
ListIterator lit=list.listIterator();
while(lit.hasNext()){//正向遍历
       String s=lit.next();
       System.out.println(s);
}
while(lit.hasPrevious()){//反向遍历
       String s=lit.pervious();
       System.out.println(s);
}
while(lit.hasNext()){//直接通过lit添加,而不像之前通过list才能添加
       String s=lit.next();
       if(s.equals("world")){
                  lit.add("javaee");
       }
}

增强for循环(最方便遍历方式)s

目的:简化数组和Collection集合的遍历

  • 实现Iterable接口的类允许其对象成为增强型for语句的目标
  • 内部原理是一个Iterator迭代器

格式

for(元素数据类型  变量名: 数组或者Collection集合){
    //在此处使用遍历即可,该变量就是元素
}
eg:
int[ ]  arr={1,2,3,4,5};
for(int i : arr){
   System.out.println(i);
}
String[ ] strArray={"hello","world","java"};
for(String s : strArray){
   System.out.println(i);
}

List集合子类特点

List集合常用子类:ArrayList,LinkedList

  • ArrayList:底层数据结构是数组,查询快,增删慢
    ArrayList array = new ArrayList()
  • LinkedList:底层数据结构是链表,查询慢,增删快
    LinkedList array = new LinkedList()

LinkedList集合的特有功能

  • public void addFirst(E e)在该列表开头插入指定的元素
  • public void addLast(E e)将指定的元素追加到此列表的末尾
  • public E getFirst()返回此列表的第一个元素
  • public E getLast()返回此列表中的最后一个元素
  • public E removeFirst()从此列表删除并返回第一个元素
  • public E removeLast()从此列表删除并返回最后一个元素

Set

Set集合概述和特点

set集合特点

  • 不包含重复元素的集合
  • 没有带索引的方法,所以不能使用普通for循环遍历

set存储字符串并遍历

Set set=new HashSet();
//HashSet对集合的迭代顺序不做任何保证
set.add("hello");
set.add("world");
set.add("java");
for(String s : set){
     System.out.println(s);//输出字符串的顺序不一定和输入的一样,但一定不重复
}

哈希值

定义:JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中返回哈希值方法

  • public int hashCode():返回对象的哈希码值
  • 同一个对象多次调用hashCode()方法返回的哈希值相同
  • 默认情况下,不同对象哈希值不同,但是重写类中hashCode()方法,可以让不同对象哈希值相同
    eg:System.out.println("hello".hashCode())
    s1,s2两对象相同,不想重复录入,就要在类中重写equals和hashCode方法

HashSet集合概述和特点

HashSet集合特点

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不作任何保证(存储和取出元素顺序不一定一致)
  • 没有带索引的方法,不能使用普通for循环遍历
  • 由于是Set接口实现类,不包含重复元素集合

HashSet存储字符串并遍历

HashSet hs=new HashSet();
hs.add("hello");
hs.add("world");
hs.add("java");
for(String s : hs){
     System.out.println(s);
}

HashSet集合保证元素唯一性流程

要保证元素唯一性,需要重写hashCode()和equals()方法


屏幕截图 2021-01-26 154733.png

哈希表

JDK8前,底层采用数组+链表实现,是一个元素为链表的数组
JDK8之后,在长度比较长的时候,底层实现了优化


2021-01-26_155324.jpg

LinkedHashSet集合概述和特点

LinkedHashSet集合特点

  • 哈希表和链表实现的Set接口,具有可预测的迭代次序
  • 由链表保证元素有序,元素的存储和取出一致
  • 由哈希表保证元素唯一性,没有重复元素

LinkedHashSet存储字符串并遍历

LinkedHashSet lhs=new LinkedHashSet();
hs.add("hello");
hs.add("world");
hs.add("java");
for(String s : lhs){
     System.out.println(s);
}

TreeSet集合概述和特点

TreeSet集合特点

  • 元素有序,但并非存储和取出顺序,而是根据构造方法按照一定规则排序
    TreeSet():根据其元素的自然排序进行排序(从小到大顺序)
    TreeSet(Comparator comparator):根据指定的比较器进行排序
  • 没有带索引的方法,不能用普通for循环遍历
  • 由于是Set接口实现类,不包含重复元素集合

TreeSet存储整数并遍历

TrssSet ts=new TreeSet();//基本类型存储时用的是对应包装类类型,所以int用Integer
ts.add(30);
ts.add(40);
ts.add(20);
for(Integer i : ts){
     System.out.println(i);
}

自然排序Comparable使用
存储对象并遍历,使用TreeSet无参构造方法,年龄由小到大排序,否则按照姓名字母排序

Student类
public class Student implements Comparable{//类中必须添加Comparable接口
    private String name;
    private int age;
    ......
    public int compareTo(Student s){
        //return 0;s1和s2比较时,返回值一直一致,s2无法添加
        //return -1;s1和s2比较时,s2一致比s1小,先输出
        //return 1;s1和s2比较时,s2一致比s1大,后输出
        int num=this.age-s.age;//获取s2的值减去s1的值的差
        int num2=num==0?this.name.compareTo(s.name):num;//获取s2和s1相比首字母大小
        return num2;
    }
}
Main主函数
TreeSet ts=new TreeSet<>();
Student s1=new Student("Tom",24);
Student s2=new Student("Jack",18);
ts.add(s1);
ts.add(s2);
for(Student s:ts){
            System.out.println(s.getName()+","+s.getAge());
}

自然排序就是让元素所属的类实现Comparable接口,重写compareTo(E e)方法
重写方法时分清主要和次要比较条件
比较器排序Comparator使用
存储对象并遍历,使用TreeSet带参构造方法,年龄由小到大排序,否则按照姓名字母排序

public static void main(String[] args) {
//主函数中用匿名内部类直接重写compare方法
        TreeSet ts=new TreeSet(new Comparator() {
            @Override
            public int compare(User u1, User u2) {
                int num=u1.getAge()-u2.getAge();
                int num2=num==0?u1.getName().compareTo(u2.getName()):num;
                return num2;
            }
        });
       ......
}

比较器排序时,就是让集合构造方法接收Comparator的实现类对象,重写compare(E e1,E e2)方法;重写方法时分清主要和次要比较条件;

泛型

概述

泛型提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型
本质是参数化类型:将类型由原来具体类型参数化,然后在调用时传入具体类型
应用:泛型类、泛型方法、泛型接口

定义格式

  • <类型>:指定一种类型格式,这里类型可以看成形参eg:Collection
  • <类型1,类型2>:指定多种类型格式,这些类型都可以看作形参
  • 具体调用时候给定类型可以看成实参,且只能是引用数据类型

优势

  • 把运行时期的问题提前到了编译期间
    -避免了强制类型转换

泛型类

定义格式
修饰符 class 类型<类型>{ }
eg:
public class Generic{//E为任意标识,是个形式参数表示泛型
     private E e;
     public E getE(){return e;}
     public void setE(E e){this.e = e;}
}
使用泛型类
Generic g1 = new Generic(); g1.setE("Jack");
Generic g2 = new Generic(); g2.setE(30);
Generic g3 = new Generic(); g3.setE(true);

泛型方法

定义格式
修饰符 <类型> 返回值类型 方法名(类型 变量名){ }
eg:
public class Generic{
    public  void show(T t){ //泛型方法写在任意类都可
        System.out.println(t);
    }
}
使用泛型方法
Generic g = new Generic();
g.show("Jack");
g.show(30);
g.show(true);

泛型接口

定义格式
修饰符 interface 接口名<类型>{ }
eg:
//泛型接口
public interface Generic{
    void show;
}
//泛型接口对应实现类
public class GenericImpl implements Generic{
   public void show(T t){
         System.out.println(t);
   }
}
主函数中使用泛型接口
Generic g1=new GenericImpl();
g1.show("Jack");
Generic g2=new GenericImpl();
g2.show(30);

类型通配符

类型通配符:

  • 表示各种泛型List的父类
  • List表示元素类型未知List,它的元素可以匹配任何的类型
  • List仅表示它是各种泛型List的父类,并不能把元素添加其中
List list1 = new ArrayList();
List list2 = new ArrayList();
List list3 = new ArrayList();
 
 

类型通配符上限:

  • List只代表某一类泛型List的父类
  • List表示类型是Numbers或者其子类
List list5 = new ArrayList();
List list6 = new ArrayList();

类型通配符下限:

  • List表示类型是Numbers或者其父类
List list7 = new ArrayList();
List list8 = new ArrayList();
 
 

可变参数

即参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的

格式:修饰符 返回值类型 方法名(数据类型...变量名){ }
System.out.println(sum(10,20,30));
System.out.println(sum(10,20,30,40));
public static int sum(int...a){//此时a实际上就是一个数组名,所以可以用增强for求和
      int sum=0;
      for(int i : a){
            sum+=i;
      }
      return sum;
}
public static int sum(int b,int...a){......}
//此形式下第1个数存入b,其余的存入数组a

方法中形参实际是一个数组
如果一个方法由多个参数,包含可变参数,可变参数要放在最后
可变参数使用
Arrays工具类中有一个静态方法

  • public static List asList:返回由指定数组支持的固定大小的列表
    List list=Arrays.asList("hello","world","java");//可以修改元素,但不可增删

List接口中有一个静态方法

  • public static List of(E...elements):返回包含任意数量元素的不可变列表
    List list=List.of("hello","world","java","world");//不可增删修改

Set接口中有一个静态方法

  • public static Set of(E...elements):返回一个包含任意数量元素的不可变集合
    Set set=set.of("hello","world","java");//不可增删,不可有重复元素,无修改方法

Map集合

Map集合概述和特点

Map集合概述

  • Interface Map K是键的类型,V是值的类型
  • 将键映射到值的对象;不能包含重复的键;每个键可以映射最多一个值
    eg:B17041223 张三 (学号不重复做键,姓名做值)

创建Map集合对象

  • 多态方式
  • 具体实现类HashMap
Map map = new HashMap();
map.put("B17041223","张三");
map.put("B17041231","李四");
map.put("B17041223","王五");//此时会根据键,把原来的张三替换成王五

Map集合的基本功能

  • V put(K key,V value)添加元素
  • V remove(Object key)根据键删除键值对应元素
  • V clear()移除所有的键值对应元素
  • boolean containsKey(Object key)判断集合是否包含指定的键
  • boolean containsValue(Object value)判断集合是否包含指定的值
  • boolean isEmpty()判断集合是否为空
  • int size()集合的长度,可就是集合中键值对的个数

Map集合的获取功能

  • V get(Object key)根据键获取值
  • Set keySet()获取所有键的集合
    Set keySet=map.keySet()
  • Collection values()获取所有值的集合
    Collection values=map.values()
  • Set> entrySet()获取所有键值对对象的集合

Map集合的遍历

方式1
1.获取所有键的集合,用keySet()方法实现
2.遍历键的集合,获取到每一个键,用增强for实现
3.根据键去找值,用get(Object key)方法实现

Map map = new HashMap();
map.put("张无忌","赵敏");
map.put("黄蓉","郭靖");
map.put("杨过","小龙女");
Set keySet = map.keySet();
for(String key:keySet){
       String value = map.get(key);
       System.out.println(key+","+value);
}

方式2
1.获取所有键值对对象的集合
Set> entrySet()方法
2.遍历键值对对象的集合,得到每一个键值对对象
增强for实现,得到每一个Map.Entry
3.根据键值对对象获取键和值
getKey()得到键
getValue()得到值

Map map = new HashMap();
        map.put("张无忌","赵敏");
        map.put("黄蓉","郭靖");
        map.put("杨过","小龙女");
        Set> entrySet = map.entrySet();
        for(Map.Entry me:entrySet){
            String key=me.getKey();
            String value=me.getValue();
            System.out.println(key+","+value);
        }

案例
键盘录入1个字符串,统计字符串中每个字母出现次数,输出形式为“a(5)b(7)c(2)”

        //键盘录入字符串
        Scanner sc =new Scanner(System.in);
        System.out.println("请输入1个字符串:");
        String line = sc.nextLine();

        //创建HashMap集合,键是Character,值是Integer
        HashMap hm=new HashMap<>();

        //遍历字符串得到每1个字符
        for(int i=0;i keySet = hm.keySet();
        for(Character key:keySet){
            Integer value=hm.get(key);
            sb.append(key).append("(").append(value).append(")");
        }
        String result=sb.toString();
        //输出结果
        System.out.println(result);

集合嵌套案例

创建ArrayList集合,存储3个元素,每个元素都是HashMap,每个HashMap键和值都是String,并遍历

//创建ArrayList集合
ArrayList> array=new ArrayList>();

//创建HashMap集合,并添加键值对元素
HashMap hm1=new HashMap<>();
hm1.put("孙策","大乔");
hm1.put("周瑜","小乔");
//把HashMap作为元素添加到ArrayList集合
array.add(hm1);

//创建HashMap集合,并添加键值对元素
HashMap hm2=new HashMap<>();
hm2.put("郭靖","黄蓉");
hm2.put("杨过","小龙女");
//把HashMap作为元素添加到ArrayList集合
array.add(hm2);

//创建HashMap集合,并添加键值对元素
HashMap hm3=new HashMap<>();
hm3.put("令狐冲","任盈盈");
hm3.put("张无忌","赵敏");
//把HashMap作为元素添加到ArrayList集合
array.add(hm3);

//遍历ArrayList集合
for(HashMap hm:array){
   Set keySet = hm.keySet();
   for(String key:keySet){
           String value = hm.get(key);
           System.out.println(key+","+value);
    }
}

创建1个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,每个ArrayList的元素是String,并遍历

//创建HashMap集合
HashMap> hm=new HashMap<>();

//创建ArrayList集合,并添加元素
ArrayList sgyy=new ArrayList<>();
sgyy.add("诸葛亮");
sgyy.add("刘备");
//把ArrayList作为元素添加到HashMap集合
hm.put("三国演艺",sgyy);

//创建ArrayList集合,并添加元素
ArrayList xyj =new ArrayList<>();
xyj.add("唐僧");
xyj.add("孙悟空");
//把ArrayList作为元素添加到HashMap集合
hm.put("西游记",xyj);

//创建ArrayList集合,并添加元素
ArrayList shz=new ArrayList<>();
shz.add("武松");
shz.add("鲁智深");
//把ArrayList作为元素添加到HashMap集合
hm.put("水浒传",shz);

Set keySet = hm.keySet();
for(String key:keySet){
       System.out.println(key);
       ArrayList value = hm.get(key);
       for(String s:value){
           System.out.println("\t"+s);
       }
}

Collections

Collections概述和使用

Collections类的概述

  • 针对集合操作的工具类

Collections类的常用方法

  • public static > void sort(List list)将指定的列表按升序排序
  • public static void reverse(List list)反转指定列表中的元素的顺序
  • public static void shuffle(List list)使用默认的随机源随机排列指定的列表
List list = new ArrayList();
list.add(20);list.add(10);list.add(40);list.add(30);
Collections.sort(list);
Collections.reverse(list);
Collections.shuffle(list);

你可能感兴趣的:(Java学习笔记:集合)