java 集合

2021-03-05 08:29

阅读:469

标签:put   oid   删除   lower   数据处理   default   方法   abc   双向链表   

集合:

保存多个的引用对象

Java 集合可分为 Collection 和 Map 两种体系

 

集合的遍历:

使用iterato()方法:

iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素

所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。

Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。

iterato()都是实现Iterator接口

返回类型 方法名 解释
boolean hasNext() 如果迭代具有更多元素,则返回 true
E next() 返回迭代中的下一个元素。
default void remove() 从底层集合中删除此迭代器返回的最后一个元素(可选)。
注意事项:

使用迭代器不能new 要通过集合的iterator()方法

增强for遍历集合时,底层是迭代器

增强for遍历数组时,底层是经典for循环

增强for统一了数组和集合的遍历方法

迭代器(一钟设计模式)遍历集合:
    @Test
   public void iteratorTest(){
       ArrayList arrayList = new ArrayList();
       while (arrayList.size()10){
           int y = (int) (Math.random()*20);
           if (!arrayList.contains(y)){
               arrayList.add(y);
          }
      }
       // 1.调用集合对象的iterator()方法获取跌掉其,默认的游标指向第一个元素之前
       Iterator iterator = arrayList.iterator();
       //PS:迭代器获取后必须马上使用(否则当出现修改集合的操作,会导致数据不准确)
       // 2.循环中,询问当前游标是否有下一个元素,调用hasNext,如果有,则返回true,反之为false,循环结束
       while (iterator.hasNext()){
           // 3.如果真的有下一个,就获得下一个next
           Object next = iterator.next();
           //PS :next()方法在循环中必须只能s调用一次
           System.out.println(next);
      }
       //Pss:迭代器是一次性使用
  }

 

泛型:解决类型安全问题,Object多态的类型模糊问题.

约束集合 让集合中只能保存指定类型的对象 类型安全

约束集合, 让集合中只能保存指定类型的对象, 类型安全了. 因为集合中的对象类型是固定的了, 再获取元素时, 元素类型直接就是泛型类型. 只需要在左右的集合类名

例如:List list =new ArrayList();

集合与数组的区别

  集合 数组
存储对象 任意对象(只能是对象) 任意数据类型
长度 可变 固定
类型 类型可变 类型不可变

Collection接口:

内容:List、Set 和 Queue 接口的父接口,该接口里定义的方法 既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。

特点

无序:不按添加顺序保存元素

可重复:相等的元素可以多次放入

方法:

boolean add(Object obj) //添加对象到集合中, 返回true或false;
boolean contains(Object obj) //判断参数中的对象是否已经被集合包含
boolean remove(Object obj) //从集合中删除指定的对象
int size() //返回元素个数
Object[] toArray() //将集合转化为数组
T> T[] toArray(T[] a) //非静态方法 参数必须为数组 然后返回一个跟参数类型一样的数组

Set接口: 无序、不可重复

无序:不按添加的顺序进行存放数据(!! 不等于随机性,只不过获取的方式不根据下标获取)

不可重复:比较插入的对象内容是否相等(不是地址值)

hashCode() 方法

对于存放在Set容器中的对象,对应的类一定要重写equals(Object obj)和hashCode()方法,以实现对象相等规则。

例子:

Set set = new HashSet();
set.add("abc");
set.add(new Integer(200));
set.add("zzzz");
set.add(new Student(1, "小明", 5, 80));
boolean b1 = set.add("abc");
boolean b2 = set.add(100); // set.add(Integer.valueOf(100));
boolean b3 = set.add(200); // 自动装箱, 因为集合不能保存基本数据
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(set.size());// 5 因为是无序不可重复
System.out.println(set.contains(1000)); // 是否包含
System.out.println(set);
//set.remove("abc"); // 删除
System.out.println(set);

HashSet: 哈希算法 (数组+链表的结构)

按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。

无序: 当向HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。即:根据数据的哈希值存储和获取对象

HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

重写 hashCode()原则

  1. 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值

  2. 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等

  3. 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值

添加元素的过程
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,
此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断
数组此位置上是否已经有元素:
   如果此位置上没有其他元素,则元素a添加成功。 --->情况1
   如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
       如果hash值不相同,则元素a添加成功。--->情况2
       如果hash值相同,进而需要调用元素a所在类的equals()方法:
              equals()返回true,元素a添加失败
              equals()返回false,则元素a添加成功。--->情况3
**总结**
   if(hashA !=hashB ){
       add(a)
  }else{
       if(!a.equls(b)){
           add(a)
      }
  }
特点:

不能保证元素的排列顺序 HashSet 不是线程安全的 集合元素可以是 null

 

TreeSet: 红黑树(特殊的排序二叉树)

因为底层是红黑树,而红黑树的底层遍历与存储都是基于比较大小

所以只能存储具有比较大小能力的相同类型的对象。

特有方法(了解)

Comparator super E> comparator() Object first() Object last() Object lower(Object e) Object higher(Object e) SortedSet subSet(fromElement, toElement) SortedSet headSet(toElement) SortedSet tailSet(fromElement)

 

排序:取出元素时实现自然排序(从小到大进行排序)

定制排序:通过比较器(实现Comparator的类)来进行排序

interface Comparator:一个比较器的接口,可以通过这个接口实习比较工具类

作用:省略了对象实现比较接口而是将比较器关联(对象管理:通过构造器)给TreeSet()对象,让TreeSet自己进行比较传入的对象

自然排序:通过对象实现Comparable接口来进行比较大小进行排序

PS:当定制排序与自然排序同时存在时,以定制排序为准

例子:

    @Test
   public void treeSetTest(){
       //匿名内部类(这个比较器就在TreeSet用一次)
       TreeSet treeSet = new TreeSet(new Comparator() {
           @Override
           public int compare(Object o1, Object o2) {
               return (int)(((Person)o1).getHeight()-((Person)o2).getHeight());
          }
      });
       //Person对象 属性:name、age、height,重写了:toString()、
       //equals(Object o)、hashCode()、compareTo(Object o)方法
       Person p1 = new Person("小明", 15, 180);
       Person p2 = new Person("小红", 15, 170);
       Person p3 = new Person("小李", 15, 195);
?
       treeSet.add(p1);
       treeSet.add(p2);
       treeSet.add(p3);
       for (Object person : treeSet){
           System.out.println(person);
      }
  }

List接口:有序、可重复

有序:按添加顺序保存数据

根据索引来操作集合元素的方法
//指定下标添加新元素**
void add(int index, Object ele)
//获取指定下标的元素****
Object get(int index)
//检索obj的下标
int indexOf(Object obj)
int lastIndexOf(Object obj)
//删除指定下标的元素 返回要删除的对象
Object remove(int index)
//替换指定下标的元素,返回被替换元素
Object set(int index, Object ele)
//将List进行分割 返回的是一个副本,不会对原有的list产生影响
List subList(int fromIndex, int toIndex)

例子:以子类ArrayList为例

     List list = new ArrayList();
       list.add("abc");
       list.add(new Integer(200));
       list.add(new Person("小花", 3, 40));
       list.add("abc");
       list.add(100);
       list.add(2);
       list.add(3);
       System.out.println(list);
       System.out.println(list.get(0)); // 获取第一个元素
       list.add(2, "yyy"); // 插入元素
       System.out.println(list);
       System.out.println(list.contains(300));
       list.remove(2); // 删除指定下标
       list.remove(Integer.valueOf(2)); // 删除元素对象
       System.out.println(list);
       System.out.println("******************");
    for (Object tmp : list) {
        System.out.print(tmp+",");
    }
       list.subList(0,1);
       System.out.println("");
       System.out.println("******************");
    for (int i = 0; i list.size(); i++) {
           System.out.print(list.get(i)+",");
    }

ListIterator接口(了解)

List 额外提供了一个 listIterator() 方法,该方法返回一个 ListIterator 对象, ListIterator 接口继承了 Iterator 接口

静态抽象方法:

void add() boolean hasPrevious() Object previous() Boolean hasNext() Object next()

Iterator和ListIterator主要区别
  1. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历。但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。

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

  3. ListIterator有add()方法,可以向List中插入对象,而Iterator不能。

  4. 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。

ArrayList: 数组

ArrayList 是线程不安全的,

而 Vector(老方法,JDK 1.0就有的) 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector

Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。

Arrays.asList(…) 返回值是一个固定长度的 List 集合

LinkedList: 链表(双向链表) 需要补

对于频繁的插入或删除元素的操作 效率较高

void addFirst(Object obj)
void addLast(Object obj)
Object getFirst()
Object getLast()
Object removeFirst()
Object removeLast()

总结:

ArrayList与LinkedList的区别

时间复杂度:

操作 数组 链表
随机访问 O(1) O(N)
头部插入 O(N) O(1)
头部删除 O(N) O(1)
尾部插入 O(1) O(1)
尾部删除 O(1) O(1)

小结

  • 同样查找, 时间复杂度都是O(N), 但是数组要比链表快

    因为数组的连续内存, 会有一部分或者全部数据一起进入到CPU缓存, 而链表还需要在去内存中根据上下游标查找, CPU缓存比内存块太多

  • 数据大小固定, 不适合动态存储, 动态添加, 内存为一连续的地址, 可随机访问, 查询速度快

  • 链表代销可变, 扩展性强, 只能顺着指针的方向查询, 速度较慢

Collection中的比较:

 * Collection : 保存一个一个对象, 无序可重复
*      Set : 无序不可重复
*          HashSet : 使用哈希算法实现的Set集合, 适用于内存不是很少的地方, 绝对优先使用它.
*              近乎完美数据结构. 基于数组, 使用散列算法实现. 对象的插入取决于对象自己的散列码, 插入速度最快
*              检索和删除时也是根据对象自身的散列码, 都是最快的.
*              唯一缺点就是要求内存连续, 用空间换时间.
*          TreeSet : 基于二叉搜索树(红黑树)实现的Set集合, 适用于频繁检索, 偶尔修改数据
*              优点 : 对内存要求低, 不要求连续, 内部要自然排序, 检索性能好(二分法)
*              缺点 : 插入删除速度慢, 有大量的比较, 还有旋转.
*      List : 有序可重复
*          ArrayList : 基于数组实现的List集合, 适用归档数据和末端数据操作
*              缺点 : 对内存要求高, 要求内存连续, 非末端数据的插入和删除都是最慢, 因为会有大量元素的移动.
*              优点 : 末端数据处理快, 检索速度快
*          LinkedList : 基于链表实现的List集合, 适用于频繁修改数据,偶尔检索
*              优点 : 对内存要求低, 不要求内存连续, 删除, 插入只修改2个指针, 速度非常快
*              缺点 : 检索速度最慢

 

Map接口:一对一保存对象

Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value

Map 中的 key 和 value 都可以是任何引用类型的数据

Map 中的 keySet来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法。 key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value。

方法:

添加、删除操作:

Object put(Object key,Object value) :写入词条,保存 键值对 对象 Object remove(Object key):删除参数指定键对象和值对象 void putAll(Map t) void clear()

元视图操作的方法:

Set keySet(): 返回保存所有键对象的Set子集合 Collection values() Set entrySet():获取所有键值对

元素查询的操作:

Object get(Object key): 根据参数指定的键对象, 获取到它映射的值对象. 像查词条 boolean containsKey(Object key) boolean containsValue(Object value) int size() boolean isEmpty() boolean equals(Object obj)

方法例子:

        MapInteger, String> map = new HashMapInteger, String>();
       // 写入词条
       map.put(3, "three");
       map.put(8, "eight");
       map.put(3, "ThREE"); // 替换成新值
       System.out.println(map.size());
       System.out.println(map);
       // 查词典
       String s = map.get(8);
  System.out.println(s);
System.out.println("********************");
       SetInteger> set = map.keySet(); // 获取所有键对象
       IteratorInteger> iterator = set.iterator();
       while (iterator.hasNext()) {
           Integer key = iterator.next();
           String value = map.get(key); // 根据键获取相应的值对象
           System.out.println(key + "----> " + value);
      }

 

HashMap : 哈希算法,针对的是键

key 相等的标准:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。 value相等的标准:两个 value 通过 equals() 方法返回 true。

LinkedHashMap: HashMap的子类

LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

HashTable :(没人用)

HashMap的古老版本,线程安全,不允许使用 null 作为 key 和 value

Properties

HashTable 的子类,对象用于处理属性文件

属性文件里的 key、value 都是字符串类型,

所以 Properties 里的 key 和 value 都是字符串类型

存取数据时,使用setProperty (String key,String value)方法和getProperty (String key)方法

TreeMap: 红黑树(特殊的排序二叉树)

排序

自然排序:

TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException

定制排序:

创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口

key相等的标准:两个key通过compareTo()方法或者compare()方法返回0

PS:自定义类作为TreeMap的key,所属类需要重写equals()和hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0。

Hashtable 古老的 Map 实现类,线程安全。

  1. 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value

  2. 与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序

  3. Hashtable判断两个key相等、两个value相等的标准,与hashMap一致。

Properties 处理属性文件

  1. 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型

  2. 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法

Collections: 工具类

操作 Set、List 和 Map 等集合的工具类

提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法

方法:

排序操作:(均为static方法)

reverse(List):反转 List 中元素的顺序 shuffle(List):对 List 集合元素进行随机排序 sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序 sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序 swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

查找、替换

Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素 Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素 Object min(Collection) Object min(Collection,Comparator) int frequency(Collection,Object):返回指定集合中指定元素的出现次数 void copy(List dest,List src):将src中的内容复制到dest中 boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

例子:

ListInteger> list = new ArrayListInteger>();
for (int i = 0; i 10; i++) {
   list.add((int)(Math.random() * 20));
}
System.out.println(list);
System.out.println(Collections.max(list)); // 最大值
Collections.sort(list); // 排序
System.out.println(list);
Collections.reverse(list); // 反转
System.out.println(list);
Collections.shuffle(list); // 洗牌
System.out.println(list);

 

java 集合

标签:put   oid   删除   lower   数据处理   default   方法   abc   双向链表   

原文地址:https://www.cnblogs.com/wzzr/p/14324809.html


评论


亲,登录后才可以留言!