java 集合
2021-03-05 08:29
标签:put oid 删除 lower 数据处理 default 方法 abc 双向链表 保存多个的引用对象 Java 集合可分为 Collection 和 Map 两种体系 iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。 Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。 iterato()都是实现Iterator接口 使用迭代器不能new 要通过集合的iterator()方法 增强for遍历集合时,底层是迭代器 增强for遍历数组时,底层是经典for循环 增强for统一了数组和集合的遍历方法集合:
集合的遍历:
使用iterato()方法:
返回类型
方法名
解释
boolean
hasNext()
如果迭代具有更多元素,则返回
true
。
E
next()
返回迭代中的下一个元素。
default void
remove()
从底层集合中删除此迭代器返回的最后一个元素(可选)。
注意事项:
迭代器(一钟设计模式)遍历集合:
@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
集合与数组的区别
集合 | 数组 | |
---|---|---|
存储对象 | 任意对象(只能是对象) | 任意数据类型 |
长度 | 可变 | 固定 |
类型 | 类型可变 | 类型不可变 |
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()原则
-
在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值
-
当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等
-
对象中用作 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主要区别
-
ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历。但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
-
ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator 没有此功能。
-
ListIterator有add()方法,可以向List中插入对象,而Iterator不能。
-
都可实现删除对象,但是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 中的 key 用Set来存放,不允许重复,即同一个 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 实现类,线程安全。
-
与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
-
与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
-
Hashtable判断两个key相等、两个value相等的标准,与hashMap一致。
Properties 处理属性文件
-
由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型
-
存取数据时,建议使用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