JCF框架(集合)


**集合框架图
在这里插入图片描述

Collection

集合类的上级接口,继承他的接口有List,Set,Queue;Collection接口指定一组对象,对象即为它的元素。

List接口

其元素以线性方式存储(有序),集合中可以存放重复对象

ArrayList接口实现类

长度可以改变的数组,可以对元素进行随机的访问,向ArrayList()中插入和删除元素比较慢;线程不安全,效率高。
一:部分api的功能代码实现:
1)定义List接口

package com.dyit.a;

public interface IList<E> {
	/**
	 * 定义List接口
	 * 
	 * @return
	 */
	int size(); // 容量大小

	boolean isEmpty(); // 判断是否为空

	void add(E element); // 增加元素

	void add(int index, E element); // 根据位置增加元素

	void remove(int index); // 删除元素

	void set(int index, E element); // 修改元素

	void clear(); // 清空集合

}

2)定义所写的ArrayList接口实现类

package com.dyit.a;

import java.util.Arrays;

import com.dyit.b.MyException;

public class MyArrayList<E> implements IList<E> {

	private Object[] elements = new Object[10];// 定义容量为10的数组
	private int size; // 定义容量

	@Override
	public int size() {

		return this.size;
	}

	@Override
	public boolean isEmpty() {

		return this.size == 0;// 当容量大小为0时,即为空
	}

	/**
	 * 增加元素。。思路:增加数据首先考虑数组是否需要扩容 ,若需要则需扩容为原来的1.5倍
	 */
	@Override
	public void add(E element) {
		if (this.size + 1 >= elements.length) {
			Object[] newelements = new Object[elements.length + (elements.length >> 1)];// 实现扩容
			// 数据的拷贝:
			System.arraycopy(elements, 0, newelements, 0, elements.length); // 方法一
			elements = newelements;
			// elements = Arrays.copyOf(elements,elements.length >> 1 );//方法二:
		}
		elements[size++] = element;
	}

	/**
	 * 删除元素。。思路:先考虑位置的异常情况,在考虑找到位置后的删除方法
	 */
	@Override
	public void remove(int index) {
		if (index < 0 || index > this.size) {
			throw new MyException("越界异常");
		}
		for (int i = index; i < this.size - 1; i++) { // 从要删除的位置起始开始后面的均往前移一位
			elements[i] = elements[i + 1];
		}
		elements[this.size - 1] = null; // 将其滞空
		this.size--;
	}

	/**
	 * 修改元素
	 */
	@Override
	public void set(int index, E element) { // 修改就是将原来位置的值覆盖
		if (index < 0 || index > this.size) {
			throw new MyException("越界异常");
		}
		elements[index] = element;
	}

	/**
	 * 根据指定位置,添加元素。。思路:先考虑界限异常情况,在考虑增加后的移动情况,可从前往后也可从后往前
	 */
	@Override
	public void add(int index, E element) {
		if (index < 0) {
			throw new MyException("越界异常");
		}
		if (index < elements.length && index >= size) {
			add(element); // 在尾部的时候直接插入
			return;
		}
		for (int i = this.size; i > index; i--) {
			elements[i] = elements[i - 1];
		}
		elements[index] = element;
		this.size++;

	}

	/**
	 * 清空元素。。思路:for循环遍历,将数组中每个元素滞空
	 */
	@Override
	public void clear() {
		for (int i = 0; i < this.size; i++) {
			elements[i] = null;
		}
		size = 0;

	}

	@Override // 打印语句
	public String toString() {
		return "MyArrayList [elements=" + Arrays.toString(elements) + ", size=" + size + "]";
	}
}

3)测试功能:

package com.dyit.a;

import static org.junit.Assert.*;

import org.junit.Test;

public class ListTest {

	@Test
	public void test() {
		IList<Integer> list = new MyArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		
		//System.out.println(list); //增加元素
		//输出>>>MyArrayList [elements=[1, 2, 3, 4, 5, null, null, null, null, null], size=5]
		
		//list.add(3, 99);; //根据位置增加元素
		//System.out.println(list);
		//输出>>>MyArrayList [elements=[1, 2, 3, 99, 4, 5, null, null, null, null], size=6]
		
		//list.remove(3);
		//System.out.println(list);
		//输出>>>MyArrayList [elements=[1, 2, 3, 5, null, null, null, null, null, null], size=4]
		
		//list.set(1, 88);
		//System.out.println(list);
		//输出>>>MyArrayList [elements=[1, 88, 3, 4, 5, null, null, null, null, null], size=5]
		
		list.clear();
		System.out.println(list);
		//输出>>>MyArrayList [elements=[null, null, null, null, null, null, null, null, null, null], size=0]
	}

}

LinkedList接口实现类

底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复数据
LinkedList代码实现:
1)建node构造器

private static class Node<E> {
		Node<E> next; // 下一个节点
		Node<E> prev; // 上一个节点
		E item;

		Node(Node<E> prve, E element, Node<E> next) { // 内部类,Node表示结点
			this.prev = prve;
			this.item = element;
			this.next = next;
		}
	}

2)添加元素:

public boolean add(E e) { // 链表添加元素
		LinkLast(e); // 调用方法
		return true;
	}

	void LinkLast(E e) { // 方法
		final Node<E> as = last; // 获取走在前面的最后一个元素
		final Node<E> newNode = new Node<>(as, e, null);// 初始化Node
		last = newNode; // 将创建的新节点指定为last节点
		if (as == null) { // 当as==null时,将新节点指定为头结点
			first = newNode;
		} else { // 否则as的下一个节点next直接指向新节点
			as.next = newNode;
		}
		size++;// 链表大小+1
	}

3)删除元素:

public E remove(int index) {
		checkElementIndex(index);// 检查index是否越界,index >= 0 && index<size
		return unlink(node(index));// 调用删除
	}

	Node<E> node(int index) { // 获取Node
		if (index < (size >> 1)) { // 判断index的范围,按位运算符获取链表的中间值
			Node<E> x = first; // 小于中间值则从first节点开始遍历
			for (int i = 0; i < index; i++) {
				x = x.next;
			}
			return x;
		} else { // 大于中间值则从last末尾节点开始遍历
			Node<E> x = last;
			for (int i = size - 1; i > index; i--) {
				x = x.prev;
			}
			return x; // 返回节点
		}
	}

	E unlink(Node<E> x) {
		final E element = x.item; // 获取删除节点的元素
		final Node<E> next = x.next;// 获取当前删除节点的下一个节点
		final Node<E> prev = x.prev;// 获取当前删除节点的上一个节点
		if (prev == null) {// 若删除节点的上一个节点是null,证明他就是头结点head,将删除节点的下一个节点指定为head
			first = next;
		} else { // 否则将删除节点的上一个节点的next指向删除节点的next节点
			prev.next = next;
			x.prev = null; // 将删除节点的上一个节点赋值为null
		}

		if (next == null) { // 如果next为null,证明删除节点没有下一个节点,则将删除节点的上一个节点指定为last
			last = prev;
		} else {
			next.prev = prev;
			x.next = null; // 将删除节点的下一个节点赋值为null,等着被删除
		}
		x.item = null;
		size--; // 长度减1
		return element;

	}

Vector接口实现类

底层数据结构是数组,查询快,增删慢;线程安全,效率低
实现可增长数组的功能,初始化数组容易为10,后面扩容时成2倍增长。``
api使用:

public class VectorX {
     public static void main(String[] args) {
		Vector<Integer> vs = new Vector<>();
		vs.add(1);
		vs.add(2);
		vs.add(3);
		vs.add(4);
		vs.add(5);
		vs.add(6);
		//System.out.println(vs); //打印添加元素
		//输出>>[1, 2, 3, 4, 5, 6]
		
		//vs.insertElementAt(99, 1); //根据指定位置插入
		//System.out.println(vs);
		//输出>>[1, 99, 2, 3, 4, 5, 6]
		
		//vs.set(3, 88);  //根据位置修改元素
		//System.out.println(vs);
		//输出>>[1, 2, 3, 88, 5, 6]
		
		//vs.remove(2);  //删除元素
		//System.out.println(vs);
		//输出>>[1, 2, 4, 5, 6]
		
		//vs.clear(); //清空数组
		//System.out.println(vs);
		//输出>>[]
		
		
		
	}

Set接口

Set集合不允许包含相同的元素,若把两个相同的元素加入到同一个set集合中,则添加操作失败,add()方法中会返回false,新元素也不会被添加

HashSet接口实现类

HashSet是Set接口的实现类,底层结构是哈希表;特点:集合元素值可以是null;HashSet不是同步的;不能保证元素的排列顺序,顺序可能与添加顺序不同,可能发生变化
一:功能展示

public class HashSetX {
     public static void main(String[] args) {
		Set<Integer> s = new HashSet<Integer>();
		s.add(2);
		s.add(3);
		s.add(4);
		s.add(5);
		s.add(5);
		
		//System.out.println(s);  //添加元素,且可以看出不能出现重复元素
		//输出>>[2, 3, 4, 5]
		
		//s.clear();
		//System.out.println(s); //清空集合
		//输出>>[]
		
		//s.remove(3);   //根据指定内容删除
		//System.out.println(s);
		//输出>>[2, 4, 5]
		
		
	}

lambda表达式

函数式编程,在使用它时必须要有函数式接口:Functional Interface,并且在定义的接口中必须只能有一个方法。 优点:可以替代“匿名内部类”,并且还可以对集合或者数组进行循环操作也可以使书写的代码量减少。
一:使用展示
1)定义接口:

package com.dyit.d;
@FunctionalInterface
public interface TranSport {
	void run();
}

2)匿名内部类写实现:

/**
	 * 匿名内部类写法:
	 */
	
	public static void someTranSport() {
		TranSport ts = new TranSport() {

			@Override
			public void run() {
				System.out.println("汽车跑得慢...");

			}
		};
		ts = new TranSport() {

			@Override
			public void run() {
				System.out.println("飞机跑得快...");

			}
		};
	}

3)Lambda表达式写实现:

/**
	 * Lambda表达式:
	 */
	
	@Test
	public void test() {
		TranSport ts = ()->{System.out.println("汽车跑得慢");};
		ts.run();
	}

二:Lambda表达式对List的使用:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class ListFun {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		Random r = new Random();
		for (int i = 0; i < 9; i++) {
			list.add(r.nextInt(20) + 1); // 在1-20内随机产生9个数
		}
		// list.forEach(i->System.out.print(i+"\t")); //遍历
		// 输出>>6 2 3 1 8 14 1 9 8

		//List<Integer> n = list.stream().filter(data -> data > 3).collect(Collectors.toList()); // 根据所给的条件找出对应元素
		//list.forEach(i -> System.out.println(n));
		// 输出>>[5, 18, 17, 14, 7, 20, 12, 15]
		
		list.stream().sorted(Integer::compareTo).collect(Collectors.toList())
		.forEach(n->System.out.print(n+"\t"));  //排大小
		//输出>>1	4	5	12	14	15	17	17	18
	}

}

Map接口

Map与Collection是平行关系,没有继承;
Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),
其中每个键映射到一个值。从概念上而言,您可以将 List 看作是具有数值键的 Map。而实际上,除了 List 和 Map 都在定义 java.util 中外,两者并没有直接的联系。

HashMap接口实现类

HashMap是Map接口的的一个实现类
一:部分功能底层代码实现
1)定义接口;

public interface IMap<K, V> {
	boolean isEmpty();

	int size();

	void put(K key, V value);

	V get(K key);
}

2)书写实现类

public class MyHashMap<K, V> implements IMap<K, V> {
	static final int sgg = 1 << 4; // 16
	private int size;
	private Node<K, V>[] table = new Node[sgg]; // 定义数组且容量大小为16

	@Override
	public boolean isEmpty() {

		return this.size == 0;
	}

	@Override
	public int size() {

		return this.size;
	}

	/**
	 * 添加数据
	 */
	@Override
	public void put(K key, V value) {
		int index = key.hashCode() % table.length; // 数组的索引

		Entry<K, V> data = new Entry<>(key, value);
		Node<K, V> newNode = new Node<>(data, null);

		if (table[index] == null) { // 空链表无节点
			table[index] = newNode;
		} else {
			Node<K, V> tmp = table[index];
			while (tmp != null && tmp.next != null) { // 尾插法
				if (tmp.data.getKey() == key || tmp.data.getKey().equals(key)) {
					tmp.data.setValue(value);
					return;
				}
				tmp.next = newNode; // 将其插入
			}
			if (tmp.data.getKey() == key || tmp.data.getKey().equals(key)) {
				tmp.data.setValue(value);
				return;
			}
			tmp.next = newNode;
		}
		this.size++; // 容量大小+1
	}

	/**
	 * 查找
	 */

	@Override
	public V get(K key) {
		int index = (key == null) ? 0 : key.hashCode() % table.length;// 数组的索引
		if (table[index] == null) {
			return null;
		} else {
			Node<K, V> tmp = table[index];
			while (tmp != null) {
				Entry<K, V> data = tmp.data;
				if (tmp.data.getKey().equals(key)) {
					return data.getValue();
				}
				tmp = tmp.next;
			}
		}
		return null;
	}

	/**
	 * 定义K与V的绑定关系(内部类)
	 * 
	 * @author DELL
	 *
	 * @param <K>
	 * @param <V>
	 */
	private static class Entry<K, V> {
		K key;
		V value;

		public Entry(K key, V value) {

			this.key = key;
			this.value = value;
		}

		public K getKey() {
			return key;
		}

		public void setKey(K key) {
			this.key = key;
		}

		public V getValue() {
			return value;
		}

		public void setValue(V value) {
			this.value = value;
		}

		@Override
		public String toString() {
			return "Entry [key=" + key + ", value=" + value + "]";
		}

	}

	/**
	 * 储存数据(内部类)
	 * 
	 * @author DELL
	 *
	 * @param <K>
	 * @param <V>
	 */
	private static class Node<K, V> {
		Entry<K, V> data;
		Node<K, V> next;

		public Node(Entry<K, V> data, Node<K, V> next) {

			this.data = data;
			this.next = next;
		}

		@Override
		public String toString() {
			return "Node [data=" + data + ", next=" + next + "]";
		}

	}

}

3)代码实现:

public class MapTest {
     public static void main(String[] args) {
    	 IMap<String, Integer> map = new MyHashMap<>();
    		map.put("1", 22);
    		map.put("2", 34);
    		map.put("3", 55);
    		map.put("4", 77);
    		map.put("9", 67);
    		map.put("99", null);
    		//System.out.println(map.get("2"));
    		//输出>>34
    		
    		System.out.println(map.get("99"));
    		//输出>>null
	}
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值