java集合笔记

Java知识点

集合

1.集合分类

 

 

使用集合前都是使用的数组,但是数组有缺点.

数组缺点:

1.长度固定不可修改;

2.保存的必须为同一类型元素;

3.增加删除元素麻烦;

集合的优点:

1.可以动态保存任意多个对象(动态扩容);

2.提供了操作对象的方法(增删改查:add ,remove,set,get);

3.可以保存不同类型的数据;

1.1collection集合体系图

collection 接口有两个重要的子接口,list和set,他们的实现子类都是单列集合.

 

 

1.2map集合体系图

map接口的实现子类是双列集合,存放的是k——v的键值对;

 

 

2.collection接口

1.collection接口的特点:

1.collection实现子类可以存放多个元素,元素类型可以说Object

2.Collection的实现类,有些可以存放相同元素,list可以存放 set不行

3.collection实现类 list是有序的,set无序

4.collection没有直接的实现子类,通过list,set接口实现的

2.1collection接口常用方法:

 

 

1.iterator

所有实现collection接口的子类都可以用iterator进行遍历,

iterator进行遍历示例代码:

//创建一个 collection 集合
Collection clo =new ArrayList();
//调用iterator方法
Iterator iterator = col.iterator();
//调用 hasNext方法判断是否还有元素,如果没有元素则返回false 循环结束
while(iterator.hasNext()){
//如果有元素则调用Next方法,则返回该元素
//返回元素类型为object
    Object object= clo.Next();

}

如果希望重置遍历

iterator=col.iterator();

iterator接口的方法和注意事项:

 

 

2.增强for

增强for增强for底层依然是迭代器

示例代码:

 public static void main(String[] args) {
      Collection collections = new ArrayList();
      collections.add("11");
      collections.add("12");
      collections.add("13");
      collections.add("14");
      ArrayList arrayList = new ArrayList();
      for (Object collection : collections) {
          arrayList.add(collection);
      }
      System.out.println(arrayList);
}
3.for each

for each 使用的话需要Consumer() 重写Consumer()方法,可以使用lomab表达式代替。

示例代码

public class demo1 {
  public static void main(String[] args) {
      Collection collections = new ArrayList();
      collections.add("11");
      collections.add("12");
      collections.add("13");
      collections.add("14");
      ArrayList arrayList = new ArrayList();


      collections.forEach(o -> {
          arrayList.add(o);
      });
      System.out.println(arrayList);

  }
}

3List

1.List接口基本介绍

1.list集合元素有序(取出是按添加顺序取出的),元素可重复;

2.list元素内的每个元素都有其对应的索引,索引与元素一一对应;

3.list集合支持索引删除;

2.List接口常用方法

 

 

3.1ArrayList

1.arrayList介绍

1.arrayList是线程不安全的,源码方法没有加synchronized(没加锁)

2.arrayList底层实现是数组,自动扩容

3.arrayList查询快,增删慢.

2.arrayList源码

 

 

1.transient 表示瞬间,短暂的 该属性不会被序列化

2.不指定长度时 elementData初次执行是一个空数组,指定长度,则为指定长度的数组。扩容时就是指定长度的1.5倍扩容

3.arraylist扩容机制

刚开始new 出来arraylist时(没有指定长度)默认创建一个长度为10的数组,如果指定长度则按照指定长度创建,继续添加数据,底层判断是否需要扩容,当数据添加满数组时则出发扩容(grow方法),数组长度增长为原来的1.5倍。

3.2.vector

1.vector基本介绍

 

 

2.vector和arrayList的比较

 

 

3.vector扩容机制

vector底层也是数组,不指定长度的化默认创建长度为10的数组,继续添加数据当数据填满数组时则触发扩容机制,长度为原来二倍。

3.3LinkedList

1.linkedLis介绍

1.linkedList底层实现了双向链表和双端队列特点

2.可以添加任意类型元素,包括null

3.线程不安全,没有实现同步

4.查询慢,增删快

2.LinkedList底层

 

 

3.LinkedList代码模拟
public class LinkedList_ {
  public static void main(String[] args) {
      //创建三个节点 模拟三个数据
      Node cat = new Node("cat");
      Node dog = new Node("dog");
      Node fish = new Node("fish");
//将三个节点进行相互关联 ,nex指向下一个,pre指向上一个
      // cat-->dog-->fish
      cat.nex = dog;
      dog.nex = fish;
      //因为是双向链表,pre属性也要执行上一个
      // cat<--dog <--fish
      fish.pre = dog;
      dog.pre = cat;
//让first节点引用指向第一个节点,last指向最后一个节点
      Node first = cat;
      Node last = fish;
      //从fist节点(首节点)遍历
      while (true) {
          if (first == null) break;
          System.out.println(first);
          first = first.nex;
      }
      System.out.println("********************");
      //last(尾节点)遍历
      while (true) {
          if (last == null) break;
          System.out.println(last);
          last = last.pre;
      }
      //模拟删除数据
      System.out.println("**********删除***********");
        // 如果删除狗节点
        //修改节点关联的数据
      cat.nex = fish;
      first=cat;
      fish.pre = cat;
      last=fish;
      System.out.println("**********删除后查看*******");
      while (true) {
          if (first == null) break;
          System.out.println(first);
          first = first.nex;
      }
      //新增一个节点dog在cat和fish间
      System.out.println("*******新增**********");
      Node dog1 = new Node("dog1");
      cat.nex=dog1;
      dog1.nex=fish;
      fish.pre=dog1;
      dog1.pre=cat;
      first=cat;
      last=fish;
      while (true) {
          if (first == null) break;
          System.out.println(first);
          first = first.nex;
      }
  }
  //定义一个node类 模拟链表一个节点
  static class Node {
      public Object item;//真正存放数据
      public Node nex;//指向下一个节点
      public Node pre;//指向前一个节点
      public Node(Object name) {
          this.item = name;
      }
      public String toString() {
          return "Node name=" + item;
      }
  }
}
4.linkedList和arrayList的比较

 

 

4.1为什么arraylist比linkedlist查询效率高?

arrayList实现了了radomAcess有随机标识,也就是arraylist可以通过数组索引进行,随机查找,而linkedlist底层是链表只能一个个查找所以arraylist相比较linkedlist查询效率高,

4.2为什么linkedlist比arraaylist增删改效率高?

linkedlist添加,删除和修改只需要修改对象位置相邻节点的指向,而arraylist如果添加数据到数组中任意位置则需要其后所有数组进行改变,所以linkedlist增删改效率高。

 

4.set接口

1.set接口介绍

1.set接口是无序的(放入和取出顺序不一致),没有索引。

2.set集合元素唯一,不能重复,所以最多包含一个null。

2.set接口常用方法

1.set接口和list接口一样,可以使用collection接口的方法。

2.set遍历可以使用迭代器(iterator),增强for。

3.set没有所以。不能使用普通for循环。

4.set遍历也可以使用for each

4.1Hashset

1.hashset介绍

1.hashSet的底层是hashMap。

2.存放元素不能重复。null只能有一个。

3.hashSet不保证元素是有序的,取决于hash后,在 确定索引的结果.

4.hashSet执行add方法时是会返回一个Boolean值,成功为true失败为false。

5.hashSet不能添加相同元素,但是如果添加的是对象,但对象内容相同是可以添加的!

 

 

2.HastSet底层

1.hashSet的底层是hashMap。HashMap的底层是(数组+链表+红黑树)。

2.创建hashset时首先创建了一个16位大小的数组,添加进hashset的值通过hash运算得到索引值,确定值储存在数组的索引位置。如果数组上还没有值则把值添加进数组上,如果再次添加的数据通过hash运行,分配给了相同的数组即数组该位置已有值,则调用equals方法进行比较,如果比较结果相同则放弃添加,如果equals比较不相同则形成链表结构,把值最加进链表最后。如果链表大小到达8同时数组(table表)提升到64则自动转换为红黑树结构,提升效率。

 

 

3LinkedHashSet

 

 

特点:

1.linkedHashSet 加入元素顺序和取出一致。

2.linkedHashSet底层是.linkedHashMap。是HashMap的子类

3..linkedHashSet底层是(数组(taable)+双向链表)

4.第一次添加时,直接将数组(table)扩容到16

4.2treeSet

1.treeset介绍

1.TreeSet的底层是TreeMap,

2.添加的数据存入了map的key的位置,而value则固定是PRESENT(占位作用)。

3.TreeSet中的元素是有序且不重复的,因为TreeMap中的key是有序且不重复的

4.线程不安全

2.TreeSet对元素进行排序的方式:

1.TreeSet中判断元素唯一性的方法是:根据比较方法的返回结果是否为0,如果是 0,则是相同元素,不存,如果不是0,则是不同元素,存储

2.元素自身不具备比较功能,则需要实现(java.until包下)Comparator接口,并覆盖其compare方法。

3.元素自身具备比较功能,即自然排序,需要实现(java.lang包下)Comparable接口,并覆盖其compareTo方法。

public class DEMO2 {
  public static void main(String[] args) {
      TreeSet set =new TreeSet(new Comparator(){
          @Override
          public int compare(Object o1, Object o2) {
              return (int)o1-(int)o2;
          }
      } );
      set.add("3");
      set.add("1");
      set.add("a");
      set.add("b");
      System.out.println(set);
  }
}

*********************************************************
package com.wz.demo1;

import java.util.Comparator;
import java.util.TreeMap;
@SuppressWarnings("all")
public class treemap {
  public static void main(String[] args) {
      TreeMap treeMap=new TreeMap(new Comparator() {
          @Override
          public int compare(Object o1, Object o2) {
              return ((String)o1).compareTo((String) o2);
          }
      });
      treeMap.put("xing","熊王");
      treeMap.put("asd","猫王");
      treeMap.put("sfsa","狗王");
      treeMap.put("sfaf","虎王");
      treeMap.put("gfsa","鹅王");
      treeMap.put("qwe","鸟王");

      System.out.println(treeMap);

  }
}

 

3.treeSet和hashset的区别

1.HashSet 保存的数据是无序的,TreeSet保存的数据是有序的,

2.TreeSet可以自动排序。

3.TreeSet 依靠的是Comparable 来区分重复数据; 4.HashSet 依靠的是hashCode()、equals()来区分重复数据 5.Set 里面不允许保存重复数据。

4.treeSet和hashset是如何去重的

(1)HashSet的去重机制:hashCode()+equals0),底层先通过存入对象,进行运算得到一个 hash值,通过hash值得到对应的索引,如果发现table索引所在的位置,没有数据,就直接存放如果有数据,就进行equals比较[遍历比较],如果比较后,不相同,就加入,否则就不加入。 (2)TreeSet的去重机制:如果你传入了一个Comparator匿名对象,就使用实现的compare去重,如果方法返回0.就认为是相同的元素/数据,就不添加,如果你没有传入一个Comparator匿名对象,则以你添加的对象实现的Compareable接口的compareTo去重。

5.map接口

1.map接口介绍及常用方法

 

 

1.map以key-vaule形式存值;

2.不允许重复:当有相同的key时 后加的对象替换前对象,可以允许相同vaule

3.可以有一个key为null

4.常用字符串作为key(其他类型也可以!!!!)

 

 

2.map遍历

为了方便遍历,map把k-v的值放入entity集合中。

然后就可以用增强for获取这个entity集合。

  HashMap map=new HashMap();
      map.put(1,"a");
      map.put(2,"a1");
      map.put(21,"1a");
      map.put(11,"2a");

      Set set = map.entrySet();
      for (Object o : set) {
          System.out.println(o);
      }

Map接口常用方法:

1.containsKey:查找键是否存在;

2.keySet:获取所有的键;

3.entrySet:获取所有k-v键值对;

4.values:获取所有值;

@SuppressWarnings("all")
public class maaap {
  public static void main(String[] args) {
      HashMap map = new HashMap();
      person person1 = new person(001, 5000, "小王1");
      person person2 = new person(002, 4100, "小王2");
      person person3 = new person(003, 2800, "小王3");
      person person4 = new person(004, 3700, "小王4");
      person person5 = new person(005, 14400, "小王5");
      map.put(person1.id, person1);
      map.put(person2.id, person2);
      map.put(person3.id, person3);
      map.put(person4.id, person4);
      map.put(person5.id, person5);
      System.out.println("**************增强for遍历************");
      Set set = map.keySet();
      for (Object o : set) {
        person vaule = (person)map.get(o);
        if (vaule.getSal()>4000) System.out.println("员工的编号为:"+o+"   员工的名字为:"+vaule.name +"   员工的工资为:"+vaule.sal);
        else continue;
      }
      System.out.println("**************迭代器遍历************");
      //获取迭代器
      Iterator iterator = map.entrySet().iterator();
      while (true) {
          if (!iterator.hasNext()) break;
          Map.Entry next = (Map.Entry) iterator.next();

          person value = (person)next.getValue();
          if (value.getSal()>4000)
          System.out.println(value.getName()+value.getSal());
            else continue;
      }
  }

  static class person {
      int id;
      int sal;
      String name;
      @Override
      public String toString() {
          return "person{" +
                  "id=" + id +
                  ", sal=" + sal +
                  ", name='" + name + '\'' +
                  '}';
      }
      public int getId() {
          return id;
      }
      public void setId(int id) {
          this.id = id;
      }
      public int getSal() {
          return sal;
      }
      public void setSal(int sal) {
          this.sal = sal;
      }
      public String getName() {
          return name;
      }
      public void setName(String name) {
          this.name = name;
      }
      public person(int id, int sal, String name) {
          this.id = id;
          this.sal = sal;
          this.name = name;
      }
  }
}

 

3.map接口小结

5.1HashMap

1.HashMap扩容机制

 

 

详情见 4.1.2和hashset一样。

5.2hashtable

1.基本介绍

1.hashtable存放的也是键值对;

2.hashtable和hashmap相比,hashtable的键不能为null;

3.hashtable线程安全,方法都有锁;

4.hashtable以弃用,想要线程安全用ConcurrentHashMap;

2.hashtable扩容机制

1.hashtable底层是数组,初始值为11;

2.加载因子为0.75,当添加数组到达阈值则触发扩容 扩容长度为2n+1

3.hashMap和hashTable对比

 

 

5.3properties类

1.基本介绍

 

 

Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存属性集。不过Properties有特殊的地方,就是它的键和值都是字符串类型。

如果键相同后替换前面的

https://www.cnblogs.com/xudong-bupt/p/3758136.html

5.4ConcurrentHashMap

1.ConcurrentHashMap介绍

ConcurrentHashMap是HashMap的线程安全版本,内部也是使用(数组 + 链表 + 红黑树)的结构来存储元素。相比于同样线程安全的HashTable来说,效率等各方面都有极大地提高。

2.ConcurrentHashMap总结

ConcurrentHashMap的底层和hashmap相同但是它的方法上添加了synchronized锁,它并没有把整个map给锁住,它只是锁住了链表/红黑树头。

当添加数据时经过hash取模计算,其得到的值并不相同则相互之间并不影响操作.

5.5treeMap

1.treeMap介绍

 

 

1.TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。 2.TreeMap 实现了 SortedMap 接口,表示它的Key是有序的。支持获取头尾 Key-Value 元素,或者根据Key指定范围获取子集合等。插入的Key 必须实现Comparable 或者 提供额外的比较器 Comparator,所以Key不允许为null, 但是Value可以 3.TreeMap 实现 NavigableMap 接口继承了 SortedMap 接口,根据指定的搜索条件返回最匹配的Key-Value元素。不同于HashMap,TreeMap 并非一定要覆写hashCode 和 equals 方法来达到Key去重的目的。 4.TreeMap 实现了Cloneable接口,意味着它能被克隆。 5.TreeMap 实现了java.io.Serializable接口,意味着它支持序列化。

6.Collections工具类

1.介绍及基本方法

 

 

 

7.集合的选择

 

 

posted @ 2022-04-20 17:25  快去学习!  阅读(39)  评论(0编辑  收藏  举报

11111111