java集合

一.List接口
1.特点
  1. 有序
  2. 有索引
  3. 可重复,元素可为null
  4. 底层用数组实现
2. ArrayList
2.1 实现
public class MyArrayList {	
	/**
	 * 定义数组,保存数据
	 */
	private Object[] objects = null;
	/**
	 * 默认数组长度
	 */
	private final int DEFAULT_LENGTH = 10;
	/**
	 * 数组长度
	 */
	private int length;
	/**
	 * 数组元素个数
	 */
	private int size= 0;
	/**
	 * 默认构造函数,创建数组
	 */
	private final int LOAD = 2;
	public MyArray() {
		length = DEFAULT_LENGTH;
		objects = new Object[length];
	}
	/**
	 * 构造函数,根据用户传入长度创建数组
	 * @param length
	 */
	public MyArray(int length) {
		this.length = length;
		objects = new Object[length];
	}
	/**
	 * 向数组中添加元素
	 * @param o
	 */
	public void add(Object o) {
		//判断是否需要扩容
		if(size==length) {
			//元素个数等于了数组长度,需要扩容
			length = length*LOAD;
			objects = Arrays.copyOf(objects,length);
		}
		objects[size]=o;
		size++;
	}	
	public void add(int index,Object o) {
		if(index<0||index>size-1) {
			throw new ArrayIndexOutOfBoundsException("访问越界");
		}else {
			//判断是否需要扩容
			if(size==length) {
				//元素个数等于了数组长度,需要扩容
				length = length*LOAD;
				objects = Arrays.copyOf(objects,length );
			}
			//先将index位置处的元素已近后面元素向右移动
			System.arraycopy(objects, index, objects, index+1, size-index);
			objects[index] = o;
			size++;
		}
	}
	/**
	 * 数组移除操作
	 * @param index
	 */
	public void remove(int index) {
		if(index<0||index>size-1) {
			throw new ArrayIndexOutOfBoundsException("访问越界");
		}else {
			objects[index]= null;
			System.arraycopy(objects, index+1, objects,index , size-index);
			size--;
		}
	}
	/**
	 * 	查找元素所在的位置
	 * @param o
	 * @return
	 */
	public int indexOf(Object o) {
//		if(size==0) {
//			return size;
//		}else if(size==length) {
//			return -1;
//		}else if(size<length) {
//			return size;
//		}
		if(o==null) {
			return -1;
		}
		for (int i = 0; i < size; i++) {
			Object object = objects[i];
			if(o.equals(object)) {
				return i;
			}
		}
		return -1;
	}
	/**
	 * 	是否包含某个元素
	 * @param o
	 * @return
	 */
	public boolean contains(Object o) {
		int i = indexOf(o);
		return i>=0?true:false;
	}
	/**
	 * 移除所有元素
	 */
	public void removeAll() {
		Arrays.fill(objects, null);
		size =0;
	}
	/**
	 * 更新数组元素
	 * @param index
	 * @param o
	 */
	public void update(int index,Object o) {
		if(index<0||index>size-1) {
			throw new ArrayIndexOutOfBoundsException("访问越界");
		}
		objects[index] = o;
	}
	/**
	 * 查找某个索引处的元素
	 * @param index
	 */
	public Object get(int index) {
		if(index<0||index>size-1) {
			throw new ArrayIndexOutOfBoundsException("访问越界");
		}
		return objects[index];
	}
	/**
	 * 打印数组元素
	 */
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer("[");
		for (int i = 0; i < size; i++) {
			sb.append(objects[i]);
			sb.append(",");
		}
		sb.append("]");
		return sb.toString().replace(",]", "]");
	}
	/**
	 * 获取元素个数
	 * @return
	 */
	public int size() {
		return size;
	}
}
2.2 方法
方法描述
add(Object o)添加数据
add(int index,Object o)在制定索引处添加元素
size()获取元素个数
get(int index)获取索引处的元素
isEmpty()判断集合是否为空
indexOf(Object o)判断某个元素第一次出现的位置
E remove(int index)移除索引处元素,并返回该元素
boolean remove(Object o)移除元素
clear()清空元素
set(int index ,E e)修改索引处的元素
iterator()获取迭代器
trimToSize()减少容量指当前元素个数
contains(Object o)判断是否包含某个元素
lastIndexOf(Object o)判断某个元素最后一次出现的位置
toArray()将集合转换为数组
addAll(Collection<? extends E> c)集合中添加集合
addAll(int index, Collection<? extends E> c)索引处添加集合
retainAll(Collection c)求两个集合的交集
removeAll(Collection<?> c)移除传入集合内的元素
subList(int fromIndex, int toIndex)获取子集合
2.3List遍历
public static void main(String[] args) {
		//菱形语法
		ArrayList<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(4);
		list.add(2);
		for (Integer integer : list) {
			System.out.println(integer);
		}
   		//使用迭代器遍历
		Iterator<Integer> it = list.iterator();
		//判断是否有下一个元素
		while (it.hasNext()) {
			int i = it.next();
			System.out.println(i);
		}
}
3.LinkedList
3.1双向链表实现
public class MyLinkedList<E>{
	/**
	 * 链表元素个数
	 */
	private int size;
	/**
	 * 链表首节点
	 */
	private Node first;
	/**
	 * 链表尾结点
	 */
	private Node last;
	/**
	 * 默认构造创建一个空链表
	 */
	public MyLinkedList() {
		first = null;
		last = null;
		size = 0;
	}
	/**
	 * 在链表末尾添加元素
	 * @param e
	 */
	private void linkLast(E e) {
		if(first==null||last==null||size==0) {
			//说明链表为空链表
			//1.创建新节点
			//2.新节点指为first
			//3.新节点指为last
			Node<E> newNode = new Node(null,e,null);
			first = newNode;
			last = newNode;
		}else {
			
			//1.创建新节点
			Node<E> newNode = new Node(last,e,null);
			//2.将last节点指向新节点
			last.next = newNode;
			//3.将新节点改为last
			last = newNode;
		}
		size++;
	}
	
	/**
	 * 在链表首部添加节点
	 * @param e
	 */
	private void linkFirst(E e) {
		if(first==null) {
			//1.创建新节点
			Node<E> newNode = new Node<E>(null, e, null);
			first = newNode;
			last = newNode;
		}else {
			Node<E> newNode = new Node<E>(null, e, first);
			first.pre = newNode;
			first = newNode;
			
		}
		size++;
	}
	/**
	 * 在节点之前添加节点
	 * @param index
	 * @param e
	 */
	private void linkBefore(int index,E e) {
		chcekRange(index);
		//1.创建新节点
		Node<E> node = new Node(null,e,null);
		//2.找到索引处的节点
		Node<E> indexNode = getNodeByIndex(index);
		//3.找到索引处的前置节点
		Node<E> pre = indexNode.pre;
		//4.新节点指向前置节点
		node.pre = pre;
		//5.前置节点指向新节点
		pre.next = node;
		//6.新节点指向索引处节点
		node.next = indexNode;
		//7.索引处pre指向新节点
		indexNode.pre=node;
		size++;
	}
	/**
	 * 在某个节点后插入新节点
	 * @param index
	 * @param e
	 */
	private void linkAfter(int index,E e) {
		chcekRange(index);
		//1.获取当前索引处的节点
		Node<E> indexNode = getNodeByIndex(index);
		//2.获取索引处后置节点
		Node<E> next = indexNode.next; 
		//3.创建新节点
		Node<E> newNode = new Node(indexNode,e,next);
		//4.索引处节点指向新节点
		indexNode.next = newNode;
		//5.索引处节点的后置节点指向新节点
		next.pre = newNode;
		size++;
	}
	
	/**
	 * 链表中添加节点,默认添加在尾部
	 * @param e
	 */
	public void add(E e) {
		linkLast(e);
	}
	/**
	 * 在指定索引处后面添加节点
	 * @param index
	 * @param e
	 */
	public void add(int index,E e) {
		linkAfter(index, e);
	}
	/**
	 * 删除索引处节点
	 * @param index
	 * @return
	 */
	public boolean remove(int index) {
		chcekRange(index);
		if(index==0) {
			Node<E> removeNode = first;
			first = first.next;
			first.pre = null;
			removeNode.next=null;
		}else if(index==size-1) {
			Node<E> removeNode = last;
			last = last.pre;
			last.next = null;
			removeNode.pre = null;
		}else {
			//1.找到索引处的节点
			Node<E> indexNode = getNodeByIndex(index);
			//2.找到索引处的后置
			Node<E> next = indexNode.next;
			//3.找到索引处的前置节点
			Node<E> pre = indexNode.pre;
			//4.将索引处前置节点的next指向索引处后置节点
			pre.next = next;
	 		//5.将索引处后置节点的pre指向索引处前置节点
			next.pre = pre;
			//6.减少元素个数
		}
		size--;
		return true;
	}
	
	/**
	 * 根据索引获取元素
	 * @param index
	 * @return
	 */
	public E get(int index) {
		chcekRange(index);
		Node<E> node = getNodeByIndex(index);
		return node.data;
	}
	/**
	 * 修改索引处的值
	 * @param index
	 * @param e
	 */
	public void set(int index,E e) {
		chcekRange(index);
		Node<E> current  = first;
		
		for (int i = 0; i < size&&current!=null;i++,current = current.next) {
			if(i==index) {
				current.data = e;
			}
		}
	}
	/**
	 * 清空链表
	 */
	public void clear() {
		first =null;
		last =null;
		size=0;
	}
	/**
	 * 链表是否为空
	 * @return
	 */
	public boolean isEmpty() {
		return size==0;
	}
	
	/**
	 * 根据传入的索引找到节点
	 * @param i
	 * @return
	 */
	private Node<E> getNodeByIndex(int index){
		//判断索引越界
		if(index<0||index>size) {
			throw new IndexOutOfBoundsException("访问越界");
		}
		if(index==0) {
			return first;
		}else if(index==size-1) {
			return last;
		}else {
			Node<E> current = first;
			for (int i = 0; i < size&&current!=null; i++) {
				if(i==index) {
					return current;
				}
				current = current.next;
			}
			
		}
		return first;
	}
	/**
	 * 判断访问是否越界
	 * @param index
	 */
	public void chcekRange(int index) {
		if(index<0||index>size-1) {
			throw new IndexOutOfBoundsException("访问越界");
		}
	}
	/**
	 * 打印链接
	 */
	@Override
	public String toString() {
		if(size==0) {
			return "[]";
		}
		Node<E> current = first;
		StringBuffer sb =new StringBuffer("[");
		for (int i = 0; i < size&&current!=null; i++,current=current.next) {
			sb.append(current.data);
			if(i!=size-1) {
				sb.append(",");
			}
		}
		sb.append("]");
		return sb.toString();
		
	}
	
	/**
	 *  定义非静态内部类表示节点
	 * @author MR.W
	 *
	 * @param <E>
	 */
	class Node<E>{
		Node<E> pre;
		E data;
		Node<E> next;
		public Node(Node<E> pre, E data, Node<E> next) {
			super();
			this.pre = pre;
			this.data = data;
			this.next = next;
		}
	}
	
}

3.2 方法
方法描述
add(Object o)添加数据
add(int index,Object o)在制定索引处添加元素
size()获取元素个数
get(int index)获取索引处的元素
isEmpty()判断集合是否为空
indexOf(Object o)判断某个元素第一次出现的位置
E remove(int index)移除索引处元素,并返回该元素
boolean remove(Object o)移除元素
clear()清空元素
set(int index ,E e)修改索引处的元素
addFirst(E e)链表首部添加元素
addLast(E e)链表末尾添加元素
removeFirst()移除首节点
removeLast()移除尾节点
getFirst()获取第一个节点
getLast()获取最后一个几点
二.Set接口
1.特点
  1. 无序
  2. 无索引
  3. 不可重复
2.HashSet
2.1方法
方法描述
add(Object o)添加元素
remove(Object o)移除元素
isEmpty()判断元素是否为空
2.2.HashSet遍历
public class Test {
	public static void main(String[] args) {	
		Set<String> set = new HashSet<>();
		//添加元素
		set.add("陈忠实");
		set.add("贾平凹");
		set.add("路遥");
		set.add("张爱玲");
		set.add("林徽因");
		boolean a = set.add("徐志摩");
		System.out.println(a);
		boolean b = set.add("徐志摩");
		System.out.println(b);
		//foreach
		for (String s : set) {
			System.out.println(s);
		}
		//iterator
		Iterator<String> it = set.iterator();
		while (it.hasNext()) {
			String s = it.next();
			System.out.println(s);
		}
	}
}
2.3重写hashCode规则
  1. 同一对象多次调用hashCode()方法时,返回值应该相同
  2. equals()方法返回值为true时,hashCode应该相同
  3. 所有参与equals方法的成员变量,都应该参与hashCode计算(为防止偶然和相等,造成hash冲突,应该用每个成员变量乘以一个质数)
3.TreeSet
  1. TreeSet内添加对象的类必须实现Comparable接口并重写compareTo方法
  2. TreeSet通过compareTo方法判断两个对象是否相等
  3. 如果equals方法返回true,compareTo方法应该返回0
三.Map接口
1.HashMap
1.1方法
方法描述
put(K key,V value)添加键值对
get(Object key)根据键获取值
keySet()获取keySet
entrySet()获取entrySet
clear()清空
containsKey(Object key)判断是否存在key
remove(Object key)根据key删除键值对
remover(Object key,Object value)根据key和value删除键值对
size()获取元素个数
isEmpty()判断map是否为空
1.2HashMap遍历
//利用keySet()方法获取keySet
public static void main(String[] args) {
	Map<String,Integer> map = new HashMap<String, Integer>();
	map.put("阿紫",30);
	map.put("梦郎", 20);
	map.put("李秋水", 20);
	map.put("天山童姥", 60);
	map.put("梦姑",18);
	//先获取keySet
	Set<String> set = map.keySet();
	//获取迭代器
	Iterator<String> it = set.iterator();
	//利用迭代器遍历
	while (it.hasNext()) {
		String key = it.next();
		int i = map.get(key);
		System.out.println("key==========="+key);
		System.out.println("value========="+i);
	}
}
//利用entrySet()获取entrySet
public static void main(String[] args) {
	Map<String,Integer> map = new HashMap<String, Integer>();
	map.put("乔峰",30);
	map.put("虚竹", 20);
	map.put("李秋水", 20);
	map.put("天山童姥", 60);
	map.put("梦姑",18);
	//获取键值对集合
	Set<Entry<String, Integer>> set = map.entrySet();
	//遍历set
	for (Entry<String, Integer> entry : set) {
		String key = entry.getKey();
		Integer value = entry.getValue();
		System.out.println("key=========="+key);
		System.out.pintln("key=========="+value);
	}
}
1.3HashMap和Hashtable的 区别
  1. HashMap和Hashtable都是Map接口的子类
  2. HashMap的key和value都可以为null,只能存入一个为null的key,Hashtable的key和value都不能为null
  3. HashMap非线程安全,Hashtable线程安全
  4. HashMap数组初始长度为16,Hashtable初始长度为11
2.TreeMap
  1. key有序
  2. key必须实现Comparable接口,并重写comparableTo方法
四.面试题
  1. ArrayList,Vector,LinkedList的区别

    1. ArrayList,Vector底层实现是数组,LinkedList底层实现是双向链表
    2. Vector线程安全,ArrayList,LinkedList非线程安全
    3. ArrayList,Vector查找快,增删慢,LinkedList增删快,查找慢
    4. ArrayList,Vector,LinkedList都是List接口的实现类
    5. ArrayList,Vector,LinkedList都有序,有索引,可重复。
  2. 请简述ArrayList和Vector的区别

    1. ArrayList和Vector底层都是Object数组,查找快,增删慢
    2. ArrayList和Vector都继承了List接口
    3. ArrayList调用默认无参构造是,创建一个长度为0的空数组,当添加第一个元素时数组长度扩展为10,Vector调用默认无参构造时创建一个长度为10的空数组
    4. ArrayList扩容后数组为原长度的1.5倍,Vector扩容后数组长度为原长度的2倍
    5. ArrayList是非线程安全,Vector是线程安全的,但是效率低于ArrayList
  3. 请简述ArrayList和LinkedList的区别

    1. 都继承了List接口
    2. 都是非线程安全
    3. ArrayList底层实现是数组,LinkedList底层实现是双向链表
    4. ArrayList查找快,增删慢,LinkedList 增删快,查找慢
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值