2020.3.29

一.集合

1 集合的概念

Java集合类存放在Java.util包中,用来存放对象的容器。需要注意:集合只能存放对象;存放的是对象的引用,对象本身还是存放在堆内存中;可以存放多种数据类型。

2 集合的框架

在这里插入图片描述
在这里插入图片描述

3 详解

1)Iterable:迭代器,它是Java集合的顶级接口。(不包含map类型的集合,Map接口是Map类集合的顶级接口)
核心方法:
Object next():返回迭代器刚越过元素的引用;
boolean hasNext():判断容器中是否有可供访问的元素;
void remove():删除迭代器刚越过的元素。
Iterable接口封装了Iterator接口。

public interface Iterable<T> {
  Iterator<T> iterator();
}

只要实现了Iterable接口的类,都可以使用Iterator迭代器。Iterator主要有next(),hasNext();remove()三个方法。
如下是一个迭代器的实例

 //创建一个 List 集合
 List list = new ArrayList();
  //添加三个元素
  list.add(1);
  list.add(2);
  list.add(3);
 //构造 List 的迭代器
 Iterator it = list.iterator();
 //通过迭代器遍历元素
 while(it.hasNext()){
Object obj = it.next();
System.out.println(obj);
 }

for each循环其实内部也是依赖与Iterator迭代器.

for( Integer i:list){
	System.out.println(i);
}

反编译

Integer i;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
        i = (Integer)iterator.next();        
    }

2)Collection :存储无序的,不唯一的数据,是list和set接口的父接口。

public interface Collection<E> extends Iteration<E>{}

主要方法有:
boolean add(Object obj) 添加对象到集合
boolean addAll(Collection c)将集合C中所有元素添加到该集合
boolean remove(Object o)删除指定的对象
boolean removeAll(Collection c)从集合中删除集合C中包含的元素
boolean retainAll(Collection c)从集合中删除集合C中不包含的元素
void clear() 删除集合中的所有元素
int size() 返回集合中元素的个数
boolean isEmpty()判断集合是否为空
boolean contains(Object obj) 判断集合中是否有指定的元素
boolean containsAll(Collection c)判断集合中是否包含集合C中的元素
Iterator iterator()返回一个迭代器
3)List:有序的,可以重复的集合。List接口继承Collection。位置从0开始

public interface List<E> extends Collection<E>{}

因为List继承了Collection,所以List拥有Collection的方法,但它也有特定的方法。
List的主要方法:
void add(int index,Object obj)在指定位置上添加一个元素
boolean addAll(int index,Collection c)将集合C的元素添加到指定位置
Object remove(int index)删除指定的元素,返回被删除的元素
Object get(int index) 返回集合List中指定的元素
int indexOf(Object obj)返回第一个出现obj元素的位置,没有返回-1
Object set(int index,Object obj) 用元素obj取代位置index上的元素,返回被取代的元素

List 接口的实现:
①List list1 = new ArrayList();底层数据结构是数组,查询快,增删慢;线程不安全,效率高
②List list2 = new Vector(); 底层数据结构是数组,查询快,增删慢;线程安全,效率低,几乎已经淘汰了这个集合
③List list3 = new LinkedList(); 底层数据结构是链表,查询慢,增删快;线程不安全,效率高

4)Set:无序的,不重复的集合。继承了Collection。
Set接口的主要实现类
1.Set hashSet = new HashSet();
HashSet按元素的哈希值存储,是无序的,不可重复的,是非线程安全的,集合元素可以为null,但最多允许一个null元素。底层是一个数组,对于hashSet,两个对象通过equals()方法返回true,这两个对象的hashCode值也应该相同。
当向HashSet集合中存入一个元素时,HashSet会先调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置。
 如果 hashCode 值不同,直接把该元素存储到 hashCode() 指定的位置;如果 hashCode 值相同,那么会继续判断该元素和集合对象的 equals() 作比较:
 1.hashCode 相同,equals 为 true,则视为同一个对象,不保存在 hashSet()中。
 2.hashCode 相同,equals 为 false,则存储在之前对象同槽位的链表上。
 2.Set treeSet = new TreeSet();
 TreeSet是有序的,不可重复的,底层使用红黑树算法,默认是自然排序。
 红黑树:是一种特定类型的二叉树,左小右大。
 排序
 ①自然排序。添加元素必须实现comparable接口,重写compareto(Object obj)方法。

package com.aem.sheep.test;

import java.util.Set;
import java.util.TreeSet;

public class test {

	public static void main(String[] args) throws Exception {
		Set t = new TreeSet();
		t.add(new Student(25, "aa"));
		t.add(new Student(22, "bb"));
		t.add(new Student(23, "cc"));
		t.add(new Student(22, "dd"));
		t.add(new Student(20, "ee"));
		t.add(new Student(20, "ee"));
		System.out.println(t);
		System.out.println(t.size());
	}
}

class Student implements Comparable {
	public Student(int age, String name) {
		this.age = age;
		this.name = name;
	}

	private int age;
	private String name;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [ age=" + age + ", name=" + name + "]";
	}

	public int hashCode() {
		return name.hashCode() + age * 37;

	}

	public boolean equals(Object obj) {

		if (!(obj instanceof Student)) {
			return false;
		}
		Student st = (Student) obj;

		return this.name.equals(st.name) && this.age == st.age;

	}

	@Override
	public int compareTo(Object obj) {
		// TODO Auto-generated method stub
		Student s = (Student) obj;

		if (this.age > s.age) {
			return 1;
		}
		if (this.age < s.age) {
			return -1;
		}
		return this.name.compareTo(s.name);

	}

}

②自定义排序。定义一个类实现comparator接口,重写compare()方法,并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。
当Comparable,Comparator都同时存在,以Comparator比较方式为主。

package com.aem.sheep.test;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

public class test {

	public static void main(String[] args) throws Exception {
		Set ts = new TreeSet(new MyComparator());
		ts.add(new Student("aa", 20));
		ts.add(new Student("bb", 25));
		ts.add(new Student("cc", 30));
		ts.add(new Student("dd", 23));
		ts.add(new Student("ab", 20));
		ts.add(new Student("bc", 20));
		System.out.println(ts);
		System.out.println(ts.size());
	}
}

class MyComparator implements Comparator {
	public int compare(Object obj1, Object obj2) {
		Student b1 = (Student) obj1;
		Student b2 = (Student) obj2;
		if (b1.getage() > b2.getage()) {
			return 1;
		}
		if (b1.getage() < b2.getage()) {
			return -1;
		}
		return b1.getName().compareTo(b2.getName());
	}
}

class Student {
	private String name;
	private int age;

	public Student() {
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getage() {
		return age;
	}

	public void setage(int age) {
		this.age = age;
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}

  1. Set linkedHashSet = new LinkedHashSet();
     LinkedHashSet是有序的,不可重复的,底层采用链表和哈希表算法,链表保证了元素的添加顺序,哈希表保证了元素的唯一性。
    5)queue:队列,遵循“先进先出”原则。LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。
    核心方法:
    add() 增加一个元索 如果队列已满,则抛IIIegaISlabEepeplian异常
    remove() 移除并返回队列头部的元素 如果队列为空,则抛出一个 NoSuchElementException异常
    element() 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
    offer() 添加一个元素并返回true 如果队列已满,则返回false
    poll() 移除并返问队列头部的元素 如果队列为空,则返回null
    peek() 返回队列头部的元素 如果队列为空,则返回null
    put() 添加一个元素 如果队列满,则阻塞
    take() 移除并返回队列头部的元素 如果队列为空,则阻塞
    推荐使用 offer(),poll(),peek()方法。
package com.aem.sheep.test;

import java.util.LinkedList;
import java.util.Queue;

public class test {

	public static void main(String[] args) throws Exception {
		Queue q = new LinkedList();
		q.offer("aa");
		q.offer(11);
		q.offer("bb");
		q.offer(22);
		q.offer("cc");
		q.offer(33);
		System.out.println(q);
		System.out.println("删除的元素:" + q.poll());
		System.out.println(q);
		System.out.println(q.peek());
		System.out.println(q);

	}
}


6)Map:key-value形式的键值队,key不允许重复,value可以重复。
主要的方法:
Object put(Object key,Object value);添加元素,指点相关联的key,value值。
void putAll(Map map);将指定map 中的所有映射复制到此集合中。
int size ();返回键值映射的数量。
boolean isEmpty();不包含键值映射返回true。
void clear();删除map中的所有键值映射。
Object remove(Object key);删除map中指定的指定的key和相关的值。
Object get(Object key);返回指定key关联的值。
Set<Entry<Object, Object>> entrySet(); 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素。
Set keySet();返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)。
boolean containsKey(Object key); 如果 Map 包含指定键的映射,则返回 true。
boolean containsValue(Object value);如果此 Map 将一个或多个键映射到指定值,则返回 true。

package com.aem.sheep.test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class test {

	public static void main(String[] args) throws Exception {
		Map<String, Integer> map1 = new HashMap<String, Integer>();
		Map<String, Integer> map2 = new HashMap<String, Integer>();
		map1.put("A1", 1);
		map1.put("A2", 2);
		map2.put("B1", 11);
		map2.putAll(map1);
		// entrySet() 迭代器速度最快
		Set<Entry<String, Integer>> set = map2.entrySet();
		Iterator<Entry<String, Integer>> it = set.iterator();
		while (it.hasNext()) {
			Map.Entry<String, Integer> m = it.next();
			System.out.println(m.getKey() + ":" + m.getValue());
		}
		// 合并
		Iterator<Map.Entry<String, Integer>> it1 = map2.entrySet().iterator();
		while (it1.hasNext()) {
			Map.Entry<String, Integer> m1 = it1.next();
			System.out.println(m1.getKey() + ":" + m1.getValue());
		}

		// keySet();
		Set<String> set2 = map2.keySet();
		Iterator<String> it2 = set2.iterator();
		while (it2.hasNext()) {
			String key = it2.next();
			Integer value = map2.get(key);
			System.out.println(key + ":" + value);
		}
		// 合并
		Iterator<String> it3 = map2.keySet().iterator();
		while (it3.hasNext()) {
			String key = it3.next();
			Integer value = map2.get(key);
			System.out.println(key + ":" + value);
		}
	}
}


实现方式
1.Map hashmap = new HashMap();
HashMap最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null。非同步的。
实现原理:
当往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

  1. Map treeMap = new TreeMap();
    TreeMap能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
    3.Map hashMap = new Hashtable();
    Hashtable与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
    4.Map linkedHashMap = new LinkedHashMap();
    LinkedHashMap保存了记录的插入顺序,在用Iterator遍历时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。

二.集合的总结(比较好记忆的)

一个记忆导图

在这里插入图片描述

一 Iterable

在介绍java Collection之前 先介绍一下 Clloection的父接口Iterable。
Iterable与集合不同的是,Iterable在java.lang目录下,而Iterator,Collection及其子接口,子类都位于Java.util目录下。
Iterator

1:next(): 最初迭代器在所有元素的左边,调用next()之后,迭代器移到第一个和第二个元素之间,next()方法返回迭代器刚刚经过的元素。
2:hasNext(): hasNext()若返回True,则表明接下来还有元素,迭代器不在尾部。
3: remove(): remove()方法必须和next方法一起使用,功能是去除刚刚next方法返回的元素。
4: 遍历方式:for-each循环可以与任何实现了Iterable接口的对象一起工作,而Collection接口扩展了Iterable接口,故标准类库中的任何集合都可以使用for-each循环

二 Collection接口

Collection

Collection接口 是集合的顶级接口.Collection接口继承Iterable接口,Collection接口在java.util目录下,

Collection接口的方法列表结果
size()返回集合中的项数
isEmpty()判断是否为空
add(E)添加元素
contains(Object)检测是否存在某个元素
clear()清除
Iterator()迭代器 遍历集合
remove(Object)删除元素

Collection接口的remove()方法和Iterator接口的remove()方法区别?

首先最直观的不同就是参数:Collection接口的remove()方法带参数,Iterator接口的remove()方法不带参数

然后在性能方面:Collection的remove方法必须首先找出要被删除的项,采用的是单链表结构查询,单链表查询效率比较低,需要从集合中一个一个遍历才能找到该对象;而 Iterator的remove方法结合next()方法使用,有下一项就删除,没有就不删,比如集合中每隔一项删除一项,所以Iterator的remove()效率更高。

最后在容错方面看:前提,在使用Iterator遍历时,使用Collection的remove()会报异常,用Collection的remove()的时候会调用到父类Iterable的Iterator,就有两个集合遍历,遍历移除的时候是移除Iterable里面的,没有移除Collection里面的所以会出现ConcurrentModificationException,因为集合中对象的个数会改变而Iterator 内部对象的个数不会,不一致则会出现该异常;但是在使用Iterator遍历时,不会报错,因为iterator内部的对象个数和原来集合中对象的个数会保持一致。

List、Set、Queue接口

List、Set、Queue接口都继承于Collection,而各有各自的特色;

List

list有两个实现类 ArrayList,LinkedList
ArrayList: 数组结构 get和set调用,查询的速度快;但是添加删除的速度慢。
LinkedList: 链表结构 get和set的调用花费昂贵,不适合做查询;添加和删除的速度快。

Set

Set 有三个实现类 HashSet,TreeSet,LinkedHashSet
HashSet 效率最高 速度最快,没顺序保存元素,集合元素可以保存null,但只可以存一个null,存储对象
TreeSet 有序 升序保存对象
LinkedHashSe t 有顺序 按照被添加的顺序保存对象

Queue

Queue队列,先进先出

1.Array与ArrayList有什么区别?

其实问的就是数组与集合的区别?看懂这个就好办事儿了,Array是Java中的数组,ArrayList是集合,也就是动态数组,数组的复杂版本,可以动态的添加和删除元素。首先要搞懂数组的声明有三种方式,定义一个数组的时候,必须指定这个数组的数据类型及数组的大小,也就是说数组中存放的元素个数固定并且类型一样。而这个ArrayList的声明,在不使用泛型的情况下,这个list是可以添加进不同类型的元素的,而且arraylist是可以不用指定长度的。在使用泛型时,我们就只能添加一种类型的数据了
不同点:
ArrayList是Array的复杂版本
存储的数据类型:Array只能存储相同数据类型的数据,而ArrayList可以存储不同数据类型的数据
长度的可变:Array的长度是固定的,而ArrayList的长度是可变的

2.数组与list之间的相互转换

(1).数组转list,可以使用Arrays.asList(数组)
(2).List转数组,使用list.toArray()

Map

Map接口 不继承于Collection接口,Map接口下有三个实现类

HashMap 效率最高 提供了最快的访问技术,没有按照明显的顺序保存元素,键值对
TreeMap 升序保存键
LinkedHashMap 有顺序 按插入保存键,同时保留HashMap的查询速

HashMap的实现原理

1.存储对象时:将键值对传给put方法,调用hashcode计算hash 得到bucket(容器,比喻成桶)位置,进一步存储。

2 .获取对象时:我们将K传递给get,他调用hashcode计算hash从而得到bucket位置,并进一步调用equals()方法确认键值对

HashMap和HashSet区别
HashMap相对于HashSet较快,因为它是使用唯一的键获取对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值