JCF与数据结构

JCF与数据结构

数组

数组是一个存放多个数据结构的容器

  • 数据是统一类型的
  • 所有数据都是线性规则排序的
  • 可通过为止索引来进行快速定位访问数据
  • 记得明确给出容器的长度

数组的初始化

动态初始化

//数组类型[] 数组名 = new 数据类型[数组长度];
public class Study02{
    
    
    public static void main(String[] args){
    
    
        int[] arrays = new int[5];	//定义并开辟了一个长度为3的数组
	    // 可以将上面代码分成两句来写
	   int[] array = null;	// 声明一个长度int[]类型的变量,变量会占用一块内存空间,它没有分配初始值。
	   array = new int[5];	//创建一个长度为5的数组,将数组的地址赋给变量arrays。
		
	   for(int i = 0; i < arrays.length; i++)
        {
    
    
            System.out.println("arrays[" + i + "] = " + arrays[i] + " ");
        }
        arrays[0] = 10;	//数组的第一个元素
        arrays[1] = 20;	//数组的第二个元素
        // 数组遍历
        for(int x : array)
        {
    
    
            System.out.println(array[x]);
        }
    }
}

静态初始化

//简化格式:
	//数据类型[] 数组名称 = {值, 值, …};
//完整格式(推荐):
	//数据类型[] 数组名称 = new 数据类型[]{值, 值, …};
	int[] arrays = {
    
    1, 2, 3, 4, 5};
	int[] arrays = new int[]{
    
    1, 2, 3, 4, 5};

注意不要访问越界

数组的遍历方法

//两种方法来遍历
for(int i=0;i<_size;++i){
    
    
    System.out.println(d[i]);
}

for(int e :d){
    
    
    System.out.println(e);
}

多维数组

  • 数组的数组
  • Java中多维数组存储是按照存储原则的
//规则数组
int a[][]=new int[2][3];
//不规则数组
int b[][];
b=new int[3][];
b[0]=new int[3];
b[1]=new int[4];
b[2]=new int[5];
//遍历
//1.根据下标和length属性来遍历
int k=0;
for(int i=0;i<a.length;i++){
    
    
    for(int j=0;j<a[i].length;j++){
    
    
        a[i][j]=++k;
    }
}
//2.根据无索引的方式进行遍历
for(int[] items:a){
    
    
    for(int item:items){
    
    
        System.out.println(item+", ");
    }
    
}


JCF

简介

  • 容器:能够存放数据的空间结构
    • 数组、多维数组,只能线性存放
    • 列表/散列集(Hashing)/树(Tree)/…
  • 容器框架:为了表示和操作容器而规定的一种标准体系结构
    • 对外的接口:容器中所能存放的抽象数据类型
    • 接口的实现:可复用的数据结构
    • 算法:对数据的一系列操作,如查找,排序
  • JCF的优点:提高数据存放的效率,减少程序员的工作量
  • 容器框架两个成功的实例:C++的STL,Java的JCF

img

主要的数据结构和实现类

  • 列表(List,ArrayList,LinkedList)
  • 集合(Set,HashSet,TreeSet,LinkedHashSet)
  • 映射(Map,HashMap,TreeMap,LinkedHashMap)
主要算法类
  • Arrays:对数组进行排序查找等

  • Collection:对Collection及其子类进行排序查找等

列表List

  • 有序的Collection
  • 允许重复的元素

主要实现:

List的主要实现 特性
ArrayList 非同步
LinkedList 非同步
Vector 同步

ArrayList

用数组的方式来实现列表,不支持同步

  • 因为为数组,所以不适合进行如插入删除等动态操作
  • 但静态操作,如访问效率非常的搞
  • 与Java的数组比起来,这个容量可以动态调整
  • 在填满容器时候就会自动扩充容器大小的50%

根据官方文档的描述,在非同步的情况下面,有先使用ArrayList!!!

LinkedList

双向链表实现的列表,不支持同步

  • 可别当做栈,队列和双向队列进行操作
  • 顺序访问的时候高效,随机访问差,动态操作很高效
  • 适用于数据经常变化的

Vector

与ArrayList的实现类似,都是数组实现的,但是Vector是同步的!

  • Vector同步,因此非常适合在多线程当中使用(多线程简介
  • 以前Vector是Java最早的数据类型,不是JCF当中的,由于性能太差了,在JDK1.2的时候对他进行了重写

code

package MyTest01;

import java.util.ArrayList;
import java.util.List;

public class ListTest01 {
    
    

    public static void main(String[] args) {
    
    

            //list中添加,获取,删除元素
            List<String> person=new ArrayList<>();
            person.add("jackie");   //索引为0  //.add(e)
            person.add("peter");    //索引为1
            person.add("annie");    //索引为2
            person.add("martin");   //索引为3
            person.add("marry");    //索引为4

            person.remove(3);   //.remove(index)
            person.remove("marry");     //.remove(Object o)

            String per="";
            per=person.get(1);
            System.out.println(per);    .get(index)

            for (int i = 0; i < person.size(); i++) {
    
    
                System.out.println(person.get(i));  //.get(index)
            }



            //list总是否包含某个元素
            List<String> fruits=new ArrayList<>();
            fruits.add("苹果");
            fruits.add("香蕉");
            fruits.add("桃子");
            //for循环遍历list
            for (int i = 0; i < fruits.size(); i++) {
    
    
                System.out.println(fruits.get(i));
            }
            String appleString="苹果";
            //true or false
            System.out.println("fruits中是否包含苹果:"+fruits.contains(appleString));

            if (fruits.contains(appleString)) {
    
    
                System.out.println("我喜欢吃苹果");
            }else {
    
    
                System.out.println("我不开心");
            }

            //list中根据索引将元素数值改变(替换)
            String a="白龙马", b="沙和尚", c="八戒", d="唐僧", e="悟空";
            List<String> people=new ArrayList<>();
            people.add(a);
            people.add(b);
            people.add(c);
            people.set(0, d);   //.set(index, element)      //将d唐僧放到list中索引为0的位置,替换a白龙马
            people.add(1, e);   //.add(index, element);     //将e悟空放到list中索引为1的位置,原来位置的b沙和尚后移一位

            //增强for循环遍历list
            for(String str:people){
    
    
                System.out.println(str);
            }

            //list中查看(判断)元素的索引
            List<String> names=new ArrayList<>();
            names.add("刘备");    //索引为0
            names.add("关羽");    //索引为1
            names.add("张飞");    //索引为2
            names.add("刘备");    //索引为3
            names.add("张飞");    //索引为4
            System.out.println(names.indexOf("刘备"));
            System.out.println(names.lastIndexOf("刘备"));
            System.out.println(names.indexOf("张飞"));
            System.out.println(names.lastIndexOf("张飞"));

            //根据元素索引位置进行的判断
            if (names.indexOf("刘备")==0) {
    
    
                System.out.println("刘备在这里");
            }else if (names.lastIndexOf("刘备")==3) {
    
    
                System.out.println("刘备在那里");
            }else {
    
    
                System.out.println("刘备到底在哪里?");
            }

            //利用list中索引位置重新生成一个新的list(截取集合)
            List<String> phone=new ArrayList<>();
            phone.add("三星");    //索引为0
            phone.add("苹果");    //索引为1
            phone.add("锤子");    //索引为2
            phone.add("华为");    //索引为3
            phone.add("小米");    //索引为4
            //原list进行遍历
            for(String pho:phone){
    
    
                System.out.println(pho);
            }
            //生成新list
            phone=phone.subList(1, 4);  //.subList(fromIndex, toIndex)      //利用索引1-4的对象重新生成一个list,但是不包含索引为4的元素,4-1=3
            for (int i = 0; i < phone.size(); i++) {
    
     // phone.size() 该方法得到list中的元素数的和
                System.out.println("新的list包含的元素是"+phone.get(i));
            }

            //对比两个list中的所有元素
            //两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象
            if (person.equals(fruits)) {
    
    
                System.out.println("两个list中的所有元素相同");
            }else {
    
    
                System.out.println("两个list中的所有元素不一样");
            }

            if (person.hashCode()==fruits.hashCode()) {
    
    
                System.out.println("我们相同");
            }else {
    
    
                System.out.println("我们不一样");
            }


            //判断list是否为空
            //空则返回true,非空则返回false
            if (person.isEmpty()) {
    
    
                System.out.println("空的");
            }else {
    
    
                System.out.println("不是空的");
            }

            //返回Iterator集合对象
            System.out.println("返回Iterator集合对象:"+person.iterator());

            //将集合转换为字符串
            String liString="";
            liString=person.toString();
            System.out.println("将集合转换为字符串:"+liString);

            //将集合转换为数组,默认类型
            System.out.println("将集合转换为数组:"+person.toArray());

            将集合转换为指定类型(友好的处理)
            //1.默认类型
            List<Object> listsStrings=new ArrayList<>();
            for (int i = 0; i < person.size(); i++) {
    
    
                listsStrings.add(person.get(i));
            }
            //2.指定类型
            List<StringBuffer> lst=new ArrayList<>();
            for(String string:person){
    
    
                lst.add(StringBuffer(string));
            }
    }
    private static StringBuffer StringBuffer(String string) {
    
    
        return null;
    }

    }

集合Set

性质:

  • 确定性
  • 互异性
  • 无序性

Java当中的Set接口:

Set接口 特点
HashSet 基于散列函数的集合,无序,不支持同步
TreeSet 基于树结构的集合,可以排序,不支持同步
LinkedHashSet 基于散列函数和双向列表的集合,可排序,不支持同步

HashSet

基于HashMap实现的,可以容纳null的元素,不支持同步

  • 想要同步 Set s=Collections.synchronizedSet(new HashSet(...));
  • add 添加一个元素
  • clear 清除整个HashSet
  • contains 判断是否包含一个元素
  • remove 删除一个元素
  • size 大小
  • retainAll计算两个集合的交集

LinkedHashSet

继承HashSet,基于HashMap实现的,可以容纳 null元素

  • 方法和HashSet基本一致
  • 通过一个双向链表来维护插入操作

TreeSet

基于TreeMap实现的,不可以容纳null元素

  • add
  • clear
  • contains 判断是否包含一个元素
  • remove,size
  • compareTo 方法或者指定Comparator排序

上述的三个接口的元素只能是对象!!!

判断元素的重复

HashSet和LinkedHashSet:

  • 判断两个元素hashCode返回值是否相同
  • 若两者hashCode相同,判定equals方法,不同则返回false

TreeSet:

  • 需要元素实现Comparable接口
  • 比较两个元素的compareTo方法
public class Dog implements Comparable{
    
    
    private int size;
    public Dog(int s){
    
    size=s;}
    //get,set function
    public int compareTo(Object o){
    
    
        return size-((Dog)o).getSize();
    }
}

映射Map

  • Map映射
    • 数学定义:两个集合之间元素的相应关系
    • 一个输入对应到一个输出
    • {1,zhangsan},{Key,Value} K-V对
  • Java中的Map
    • Hashtable(同步,慢数据量小)
    • HashMap(不支持同步,快,数据量大)
    • Properties(同步,文件形式,数据量小)

HashTable

  • KV对,都不允许为null
  • 同步,多线程安全
  • 无序的
  • 适合数据量小
  • 主要方法:
    • clear,contains/containsValue,containKey,get,put,remove,size

HashMap

  • KV对,都允许可以是null
  • 不同步,多线程安全
  • 无序的
  • 主要方法:
    • clear,containsValue,containKey,get,put,remove,size

LinkedHashMap

  • 基于双向链表的维持插入顺序

TreeMap

  • 基于红黑树的Map,可以根据key的自然排序或者compareTo方法进行排序输出

Properties

  • 继承HashTable
  • KV对保存在文件当中
  • 适合数据量少的配置文件
  • 继承自HashTable的方法
  • 文件加载load方法,写入文件 store方法
  • 获取属性setProperty,设置属性setPropert

Summary

  • HashMap是最常用的映射结构
  • 如需排序才会考虑LinkedHashMap和TreeMap
  • 存储文件才会用Properties类

遍历方法

类型 遍历方法
HashTable Entry迭代器,KeySet迭代器,KeyEnumeration迭代器
HashMap,LinkedHashMap Entry迭代器,KeySet迭代器
TreeMap 同上
Properties
import java.util.*;

/**
 * Authored by Gary on 2020/10/21.
 **/

public class MapTest {
    
    
    public static void main(String[] args) {
    
    
        Hashtable<Integer, String> hashtable = new Hashtable<>();
        hashtable.put(1000,"aa");
        hashtable.put(2,"bbb");
        hashtable.put(30000, "ccc");
        System.out.println(hashtable.contains("ccc"));
        traverByKeyEnumeration(hashtable);

        HashMap<Integer, String> hashMap = new HashMap<>();
        for (int i=0;i<100000;i++){
    
    
            hashMap.put(i,"dddd");
        }
        traverseByEntry(hashMap);
        traverByKeySet(hashMap);
    }

    private static void traverseByEntry(HashMap<Integer, String> hashMap) {
    
    
        long startTime=System.nanoTime();
        System.out.println("====Entry迭代器迭代============");
        Integer key;
        String value;
        Iterator<Map.Entry<Integer, String>> iter=hashMap.entrySet().iterator();
        while (iter.hasNext()){
    
    
            Map.Entry<Integer,String> entry=iter.next();
            key=entry.getKey();
            value=entry.getValue();
        }
        long endTime=System.nanoTime();
        long duration=endTime-startTime;
        System.out.println("Entry: duration"+ duration+ "ns");
    }

    private static void traverByKeySet(HashMap<Integer, String> hashMap) {
    
    
        long startTime=System.nanoTime();
        System.out.println("====KeySet迭代器迭代============");
        Integer key;
        String value;
        Iterator<Integer>iter=hashMap.keySet().iterator();
        while(iter.hasNext()){
    
    
            key=iter.next();
            value=hashMap.get(key);
        }
        long endTime=System.nanoTime();
        long duration=endTime-startTime;
        System.out.println("Entry: duration"+ duration+ "ns");
    }

    private static void traverByKeyEnumeration(Hashtable<Integer, String> hashtable) {
    
    
        System.out.println("===KeyEnumeration迭代器遍历");
        Integer key;
        String value;
        Enumeration<Integer>keys=hashtable.keys();
        while(keys.hasMoreElements()){
    
    
            key=keys.nextElement();
            value=hashtable.get(key);
        }
    }

}

true ===KeyEnumeration迭代器遍历 ====Entry迭代器迭代============ Entry: duration32959300ns ====KeySet迭代器迭代============ Entry: duration20722900ns

import java.beans.PropertyDescriptor;
import java.io.*;
import java.util.Enumeration;
import java.util.Properties;

/**
 * Authored by Gary on 2020/10/21.
 **/

public class PropertiesTest {
    
    
    
    public static String getValueByKey(String filePath,String key){
    
    
        Properties pps=new Properties();
        try{
    
    
            InputStream in=new BufferedInputStream(new FileInputStream(filePath));
            pps.load(in);//加载所有的kv对
            String value=pps.getProperty(key);
            return value;
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return null;
        }
    }
    //获取Properties的全部信息
    public static void getAllProperties(String filePath)throws IOException{
    
    
        Properties pps=new Properties();
        InputStream in=new BufferedInputStream(new FileInputStream(filePath));
        pps.load(in);
        Enumeration en=pps.propertyNames();//等到配置文件的名字
        while(en.hasMoreElements()){
    
    
            String strKey=(String)en.nextElement();
            String strValue = pps.getProperty(strKey);
        }
    }
    //写入Properties信息
    public static void writeProperties(String filePath,String pKay,String pValue)throws IOException{
    
    
        File file=new File(filePath);
        if(!file.exists()){
    
    
            file.createNewFile();
        }
        Properties pps=new Properties();
        InputStream in=new FileInputStream(filePath);
        //从输入流当中读取kv对
        pps.load(in);
        OutputStream out=new FileOutputStream(filePath);
        pps.setProperty(pKay, pValue);
        //写入输出流当中
        pps.store(out,"Update"+pKay+"name" );
        out.close();
    }
}

工具类

JCF中的工具类

  • 不存储数据,而是在数据容器上面,实现高效的操作
    • 排序
    • 搜索
  • Arrays类
  • Collections类

Arrays:处理对象是数组

  • 排序 sort/parallelSort
  • 查找 binarySearch
  • 批量拷贝 copyOf
  • 批量赋值 fill
  • 等价行比较 equals
code
import java.util.Arrays;
import java.util.Random;

/**
 * Authored by Gary on 2020/10/21.
 **/

public class ArraysTest {
    
    
    public static void main(String[] args) {
    
    
        testSort();
        testSearch();
        testCopy();
        testFill();
        testEquality();

    }

    private static void testCopy() {
    
    
        System.out.println("测试复制:");
        Random r=new Random();
        int []a=new int[10];
        for(int i=0;i<a.length;++i){
    
    
            a[i]=r.nextInt();
        }
        int []b=Arrays.copyOf(a,5);
        for(int i=0;i<b.length;++i){
    
    
            System.out.println(b[i]);
        }
    }

    private static void testSort() {
    
    
        Random r=new Random();
        int []a=new int[10];
        for(int i=0;i<a.length;++i){
    
    
            a[i]=r.nextInt();
        }
        System.out.println("排序前:");
        for (int i=0;i<a.length;++i)
            System.out.println(a[i]+",");
        System.out.println();
        System.out.println("排序后:");
        Arrays.sort(a);
        for(int i=0;i<a.length;++i){
    
    
            System.out.println(a[i]+",");
        }
        System.out.println();
    }

    private static void testSearch() {
    
    
        Random r=new Random();
        int []a =new int[10];
        for(int i=0;i<a.length;++i){
    
    
            a[i]=r.nextInt();
        }
        a[a.length-1]=10000;
        System.out.println("测试查找:");
        System.out.println("10000的位置是:"+Arrays.binarySearch(a, 10000));
    }

    private static void testFill() {
    
    
        System.out.println("测试填充");
        int []a=new int[10];
        Arrays.fill(a, 100);
        Arrays.fill(a, 2,8,200);//下标2-8,value:200
        System.out.println(a[8]);
    }

    private static void testEquality() {
    
    
        System.out.println("测试相等:");
        int []a=new int[10];
        Arrays.fill(a,100);
        int []b=new int [10];
        Arrays.fill(b, 100);
        System.out.println(Arrays.equals(a, b));

    }
}

`排序前:
114850936,
1061178683,
-2007848625,
-146148069,
-2010721281,
-1785763393,
1162440788,
1055691072,
-859380460,
1051727304,

排序后:
-2010721281,
-2007848625,
-1785763393,
-859380460,
-146148069,
114850936,
1051727304,
1055691072,
1061178683,
1162440788,

测试查找:
10000的位置是:9
测试复制:
1935907383
-756117661
43141791
1341785256
-681803678
测试填充
100
测试相等:
true`

Collections

处理对象是Collection及其子类

  • 排序 对List排序 sort
  • 搜索 对List搜索
  • 批量赋值 List-fill
  • 最大最小元素 max min
  • 反序 :将List反序排列 reverse

对象的比较

  • 对象实现Comparable接口
    • 重写compareTo方法
  • 新建 Comparator(适用于对象类不可更改的情况)
    • 重写compare方法
import java.util.*;
//以下是学生类Student定义,有点类似C语言的结构体啊!^_^
class Student {
    
    
	public int s_no;
	public String s_name;
	public int s_class;
}
 
public class compareTest {
    
    
	public static void main(String[] args) {
    
    
		//存放学生类的动态数组的初始化
		ArrayList<Student> studentArr = new ArrayList<Student>();
		Student s1 = new Student();
		s1.s_no = 3;
		s1.s_name = "a";
		s1.s_class = 102;
		studentArr.add(s1);
		Student s2 = new Student();
		s2.s_no = 2;
		s2.s_name = "b";
		s2.s_class = 101;
		studentArr.add(s2);
		Student s3 = new Student();
		s3.s_no = 1;
		s3.s_name = "c";
		s3.s_class = 103;
		studentArr.add(s3);
		//初始化之后先打印以下这个动态数组
		System.out.println("排序前:");
		for (int i = 0; i < studentArr.size(); i++) {
    
    
			System.out
					.println("我是" + studentArr.get(i).s_class + "班的"
							+ studentArr.get(i).s_name + "学号是"
							+ studentArr.get(i).s_no);
		}
		//对于Comparator接口的重写
		//这个接口就一个抽象函数,给出的参数与返回值都是定死的。
		Collections.sort(studentArr, new Comparator<Object>() {
    
    
			public int compare(Object o1, Object o2) {
    
    
				//你首先设置你要比较的东西
				//具体是把参数中的Object强制转换成你要比较的东西,这里是两个Student类
				//这里的s1,s2与上面的s1,s2一点关系都没有,只是抽象的前者与后者的关系
				Student s1 = (Student) o1;
				Student s2 = (Student) o2;
				//如果前者的学号大于后者的学号,就是前者大于后者,返回1系统就会识别是前者大于后者
				if (s1.s_no > s2.s_no) {
    
    
					return 1;
				}
				//小于同理
				if (s1.s_no < s2.s_no) {
    
    
					return -1;
				}
				//如果返回0则认为前者与后者相等
				return 0;
			}
		});
		//比较完毕再输出以学号排序之后的结果
		System.out.println("按学号排序后:");
		for (int i = 0; i < studentArr.size(); i++) {
    
    
			System.out
					.println("我是" + studentArr.get(i).s_class + "班的"
							+ studentArr.get(i).s_name + "学号是"
							+ studentArr.get(i).s_no);
		}
		//以下是以班级排序的过程
		Collections.sort(studentArr, new Comparator<Object>() {
    
    
			public int compare(Object o1, Object o2) {
    
    
				Student s1 = (Student) o1;
				Student s2 = (Student) o2;
				if (s1.s_class > s2.s_class) {
    
    
					return 1;
				}
				if (s1.s_class < s2.s_class) {
    
    
					return -1;
				}
				return 0;
			}
		});
		System.out.println("按班级排序后:");
		for (int i = 0; i < studentArr.size(); i++) {
    
    
			System.out
					.println("我是" + studentArr.get(i).s_class + "班的"
							+ studentArr.get(i).s_name + "学号是"
							+ studentArr.get(i).s_no);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Garyboyboy/article/details/109203678
JCF
今日推荐