Java全栈JavaSE:23.数据结构上

Posted new nm个对象

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java全栈JavaSE:23.数据结构上相关的知识,希望对你有一定的参考价值。

1 数据结构

数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系,并对这种结构定义相应的运算,而且确保经过这些运算后所得到的新结构仍然是原来的结构类型。

数据的逻辑结构指反映数据元素之间的逻辑关系,而与他们在计算机中的存储位置无关:

  • 集合(数学中集合的概念):数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系;
  • 线性结构:数据结构中的元素存在一对一的相互关系;
  • 树形结构:数据结构中的元素存在一对多的相互关系;
  • 图形结构:数据结构中的元素存在多对多的相互关系。

数据的物理结构/存储结构:是描述数据具体在内存中的存储(如:顺序结构、链式结构、索引结构、哈希结构)等,一种数据逻辑结构可表示成一种或多种物理存储结构。


数据结构和算法是一门完整并且复杂的课程,那么我们今天只是简单的讨论常见的几种数据结构,让我们对数据结构与算法有一个初步的了解。

2 动态数组

2.1 动态数组的特点

逻辑结构:线性的

物理结构:顺序结构

申请内存:一次申请一大段连续的空间,一旦申请到了,内存就固定了。

存储特点:所有数据存储在这个连续的空间中,数组中的每一个元素都是一个具体的数据(或对象),所有数据都紧密排布,不能有间隔。

例如:整型数组

例如:对象数组

2.2 动态数组的基本操作

与数据结构相关的数据操作:

  • 插入
  • 删除
  • 修改
  • 查找
  • 遍历
public interface Container<E> extends Iterable<E>{
	void add(E e);
	void insert(int index,E value);
	void delete(E e);
	void delete(int index);
	E update(int index, E value);
	void update(E old, E value);
	boolean contains(E e);
	int indexOf(E e);
	E get(int index);
	Object[] getAll();
	int size();
}

2.3 动态数组实现

import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class MyArrayList<E> implements Container<E>{
	private Object[] all; // 初始化一个内部数组,用来储存元素
	private int total; // 集合中的元素个数
	
	public MyArrayList(){
		all = new Object[5]; // 内部数组初始化长度默认为5
	}

	@Override
	public void add(E e) {
		ensureCapacityEnough();
		all[total++] = e;
	}

	// 校验是否需要扩容
	private void ensureCapacityEnough() {
		if(total >= all.length){
			all = Arrays.copyOf(all, all.length*2); // 长度扩容为原来的两倍
		}
	}

	@Override
	public void insert(int index, E value) {
		//是否需要扩容
		ensureCapacityEnough();
		addCheckIndex(index);
		if(total-index>0) {
			System.arraycopy(all, index, all, index+1, total-index);
		}
		all[index]=value;
		total++;
	}
	
	// 校验外界传入的下标是否越界
	private void addCheckIndex(int index) {
		if(index<0 || index>total){
			throw new IndexOutOfBoundsException(index+"越界");
		}
	}

	@Override
	public void delete(E e) {
		int index = indexOf(e);
		if(index==-1){
			throw new NoSuchElementException(e+"不存在");
		}
		delete(index);
	}

	@Override
	public void delete(int index) {
		checkIndex(index);
		if(total-index-1>0) {
			System.arraycopy(all, index+1, all, index, total-index-1);
		}
		all[--total] = null;
	}

	private void checkIndex(int index) {
		if(index<0 || index>total){
			throw new IndexOutOfBoundsException(index+"越界");
		}
	}

	@Override
	public E update(int index, E value) {
		checkIndex(index);
		E oldValue = get(index);
		all[index]=value;
		return oldValue;
	}
	
	@Override
	public void update(E old, E value) {
		int index = indexOf(old);
		if(index!=-1){
			update(index, value);
		}
	}

	@Override
	public boolean contains(E e) {
		return indexOf(e) != -1;
	}

	@Override
	public int indexOf(E e) {
		int index = -1;
		if(e==null){
			// 需要查找的内容为null,则必须使用==判断
			for (int i = 0; i < total; i++) {
				if(e == all[i]){
					index = i;
					break;
				}
			}
		}else{
			// 如果查找的内容不为null,则使用equals判断。因为==会判断内存地址,不符合要求
			for (int i = 0; i < total; i++) {
				if(e.equals(all[i])){
					index = i;
					break;
				}
			}
		}
		return index;
	}

	@SuppressWarnings("unchecked")
	@Override
	public E get(int index) {
		checkIndex(index);
		return (E) all[index];
	}

	@Override
	public Object[] getAll() {
		return Arrays.copyOf(all, total);
	}

	@Override
	public int size() {
		return total;
	}

	@Override
	public Iterator<E> iterator() {
		return new Itr();
	}
	
	private class Itr implements Iterator<E>{
		private int cursor;

		@Override
		public boolean hasNext() {
			return cursor!=total;
		}

		@SuppressWarnings("unchecked")
		@Override
		public E next() {
			return (E) all[cursor++];
		}

		@Override
		public void remove() {
			MyArrayList.this.delete(--cursor);
		}
		
	}
}

2.4 动态数组测试

import java.util.Arrays;
import java.util.Iterator;

import org.junit.Test;

public class TestMyArrayList {
	@Test
	public void test01(){
		MyArrayList<String> my = new MyArrayList<String>();
		my.add("hello");
		my.add("java");
		my.add("world");
		my.add("atguigu");
		my.add("list");
		my.add("data");
		
		System.out.println("元素个数:" + my.size());
		Object[] all = my.getAll();
		System.out.println(Arrays.toString(all));
		
		my.insert(2, "尚硅谷");
		System.out.println("元素个数:" + my.size());
		all = my.getAll();
		System.out.println(Arrays.toString(all));
	}
	
	@Test
	public void test02(){
		MyArrayList<String> my = new MyArrayList<String>();
		my.add("hello");
		my.add("java");
		my.add("world");
		my.add("atguigu");
		my.add("list");
		my.add("data");
		
		my.delete(1);
		System.out.println("元素个数:" + my.size());
		Object[] all = my.getAll();
		System.out.println(Arrays.toString(all));
		
		my.delete("atguigu");
		System.out.println("元素个数:" + my.size());
		all = my.getAll();
		System.out.println(Arrays.toString(all));
	}
	
	@Test
	public void test03(){
		MyArrayList<String> my = new MyArrayList<String>();
		my.add("hello");
		my.add("java");
		my.add("world");
		my.add("atguigu");
		my.add("list");
		my.add("data");
		
		String update = my.update(3, "尚硅谷");
		System.out.println("元素个数:" + my.size());
		System.out.println("被替换的是:" + update);
		Object[] all = my.getAll();
		System.out.println(Arrays.toString(all));
		
		my.update("java", "Java");
		System.out.println("元素个数:" + my.size());
		System.out.println("被替换的是:java");
		all = my.getAll();
		System.out.println(Arrays.toString(all));
	}
	
	@Test
	public void test04(){
		MyArrayList<String> my = new MyArrayList<String>();
		my.add("hello");
		my.add("java");
		my.add("world");
		my.add("atguigu");
		my.add("list");
		my.add("data");
		
		System.out.println(my.contains("java"));
		System.out.println(my.indexOf("java"));
		System.out.println(my.get(0));
	}
	
	@Test
	public void test05(){
		MyArrayList<String> my = new MyArrayList<String>();
		my.add("hello");
		my.add("java");
		my.add("world");
		my.add("atguigu");
		my.add("list");
		my.add("data");
		
		for (String string : my) {
			System.out.println(string);
		}
	}
	
	@Test
	public void test06(){
		MyArrayList<String> my = new MyArrayList<String>();
		my.add("hello");
		my.add("java");
		my.add("world");
		my.add("atguigu");
		my.add("list");
		my.add("data");
		
		Iterator<String> iterator = my.iterator();
		while(iterator.hasNext()) {
			String next = iterator.next();
			if(next.length()>4) {
				iterator.remove();
			}
		}
		for (String string : my) {
			System.out.println(string);
		}
	}
}

2.5 Java核心类库中的动态数组

Java的List接口的实现类中有两个动态数组的实现:Vector和ArrayList。

1、ArrayList与Vector的区别?

它们的底层物理结构都是数组,我们称为动态数组。

  • ArrayList是新版的动态数组,线程不安全,效率高,Vector是旧版的动态数组,线程安全,效率低。
  • 动态数组的扩容机制不同,ArrayList扩容为原来的1.5倍,Vector扩容增加为原来的2倍。
  • 数组的初始化容量,如果在构建ArrayList与Vector的集合对象时,没有显式指定初始化容量,那么Vector的内部数组的初始容量默认为10,而ArrayList在JDK1.6及之前的版本也是10,而JDK1.7之后的版本ArrayList初始化为长度为0的空数组,之后在添加第一个元素时,再创建长度为10的数组。
  • Vector因为版本古老,支持Enumeration 迭代器。但是该迭代器不支持快速失败。而Iterator和ListIterator迭代器支持快速失败。如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的 remove 或 add 方法之

    以上是关于Java全栈JavaSE:23.数据结构上的主要内容,如果未能解决你的问题,请参考以下文章

    Java全栈JavaSE:24.数据结构下

    Java全栈JavaSE:4.数据库之JDBC下

    Java全栈JavaSE:3.数据库之JDBC上

    Java全栈JavaSE:7.流程控制

    Java全栈JavaSE:1.数据库之MysqlL上

    Java全栈JavaSE:26.网络编程