Java常用数据结构(个人笔记)

 

写在前面:

楼主刚打完ACM徐州现场赛,也算是退役了,现在准备重新补一遍Java,之前一直用的是C++,所以我会结合C++来整理Java的数据结构,同时也便于理解。

 

那么我将按照以下顺序进行讲解,感觉难度也是逐步提升

 

ArrayListVectorLinkedlist的用法

StackQueue的用法

Set  用法

Map 用法

 

下面开始我的表演

①ArrayList

ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问

其实吧,个人理解他就是个数组,只不过封装了,有各种操作。

定义:

    	ArrayList a = new ArrayList();
    	ArrayList b = new ArrayList();

这里的Integer可以换成任何其他类。

第一种定义可以不指明ArrayList的类型,那么插入的数据可以是任意类型;

第二种明确了类型,只能插入相应类型的数据。

操作:

1. add( Object obj );  加入元素到尾部

    	a.add(2);
    	a.add( new person("小明",1) );
    	
    	b.add(4);
    	b.add(5);

因为之前的a我们没指名类型,所以我们可以add任意类型的东西进去,b就只能add Integer类型的。

这个绝逼是最常用的,相当于C++里面的push_back();

至于他的返回值,是boolean,也就是C++的bool,表示是否add成功,但是返回值我们一般不用

 

然后add还可以指定位置

add( int index,Object obj);

      b.add(1, 222);	//在1位置处插入222,后面的元素index加1(如果有的话)

这个带插入位置的add就相当于C++的insert,在某个位置插入一个元素,使后面的元素后移。

但是个人建议不要用这个,这个插入效率比较低。

 

2.get( int index );  得到指定位置的元素

    	int t = (Integer)a.get(0);  //下标是从0开始的
    	person p = (person)a.get(1);	
    	
    	int t2 = b.get(0);
    	int t3 = b.get(1);

这里我们注意到a的get都要强制转换,而b不需要,因为a在定义时候就没有明确,所以这是必然的。

 

3.remove( int index ) 删除指定位置的元素,后面元素向前挪

       a.remove(0);

它的返回值也是boolean,表示是否删除成功。

同样,因为是数组实现,所以删除效率就很低。

 

4.int size();  得到ArrayList的大小

    	int t = b.size();

常用而又简单

 

5.sort( Comparator c );  进行排序,还需要定义比较器,个人觉得比较麻烦

    b.sort( new mycomparator() );
    
    //定义 mycomparator
    class mycomparator implements Comparator
    {
	    public int compare(Integer o1, Integer o2)
	    {
	    	if( o1 > o2 )	
		    	return 1;
		    return -1;
	    }
    }

 如果觉得不太理解可以去查查Java排序的相关知识

 

6.void clear();  清空

		a.clear();

就和C++的clear一样

 

下面是ArrayList用法小汇总,大家可以举一反三

import java.util.*;

public class Main 
{
	
	public static void main( String args[] )
	{
		ArrayList a = new ArrayList();	//定义ArrayList  不明确类型
		
		a.add(1);
		a.add( new Person("小明",12) );
		a.add(0, 123); 					//在0位置处插入123
		int t = (int)a.get(0);			//不加强制转化 会报错
		System.out.println(t); 			//输出t 结果是123
		
		a.remove(0);					//删除位置0处的元素,后面的向前面移动	
		
		for( int i = 0 ; i < a.size() ; i++ )	//遍历ArrayList
			System.out.println( a.get(i) );
		
		a.clear();	//清空
		if( a.isEmpty() )		//调用 isEmpty方法
			System.out.println("ArrayList已经空了");
		
	}
}
class Person
{
	String name;
	int age;
	Person( String name,int age )
	{
		this.name = name;
		this.age = age;
	}
	public String toString()
	{
		return "name "+name+"\n"+"age "+age;
	}
}

②Vector的用法

其实Vector和ArrayList简直是一模一样,至少操作是这样

如果想了解它们的区别,可以参考

https://www.cnblogs.com/zhangzongle/p/5432212.html

 

③LinkedList

LinkedList的基本用法其实和ArrayList差不多,但是它的储存方式和之前的不一样,所以还是有一丢丢不同。

总的来说,LinkedList   增加和删除效率要比ArrayList要高。 毕竟是链表,改一下指针就行了

但是访问的效率并不高。

定义

    	LinkedList l = new LinkedList();
    	LinkedList ll = new LinkedList();

操作:

add( Object obj)、remove(int index)、size()、isEmpty()、sort()、clear()这些都和之前的一样,我就不讲啦

 

不同的有:

void addFirst( Object obj );   //队首插入

void addLast( Object obj );   //队尾插入,和add( Object obj )效果一样

    	l.addFirst(1);
    	l.addLast(2);

同样remove也有两种

Object removeFirst(  );

Object removeLast(  );

当然,返回值可以要,也可以不要

    	l.removeFirst();
    	l.removeLast();
    	
    	int t = (int)l.removeLast();
    	int t2 = (int)l.removeFirst();

 

下面是LinkedList的用法小汇总

import java.lang.reflect.Array;
import java.math.*;
import java.util.*;

public class Main
{
    public static void main(String[] args) 
    {
    	Person p1 = new Person("小明",12);
    	Person p2 = new Person("小红",16);
    	Person p3 = new Person("小哥哥",13);
    	
    	LinkedList ll = new LinkedList();	//定义一个LinkedList
    	ll.add(p1);
    	ll.add(p2);
    	ll.add(p3);
    	
    	ll.sort( new mycomparator() );		//进行排序
    	ll.addFirst( new Person("大哥",22) );	
    	
    	for( int i = 0 ; i < ll.size() ; i++ )
    		System.out.println( ll.get(i) );
    	
    	ll.removeFirst();
    	ll.removeLast();
    	Person temp = ll.removeFirst();		//删除第一个
    	ll.removeFirst();
    	
    	if( ll.isEmpty() )		//调用isEmpty方法
    		System.out.println("LinkedList空了");
    	else
    	{
    		Person tt = ll.get(0);	//get函数
    		ll.removeFirst();		
    	}
    	ll.clear();					//清空
    }
}
class Person
{
	String name;
	int age;
	public Person( String name,int age )
	{
		this.name = name;
		this.age = age;
	}
	public String toString()
	{
		return "name "+name+"\n"+"age "+age;
	}
}
class mycomparator implements Comparator
{
	public int compare(Person a, Person b )		//年龄从大到小排序
	{
		if( a.age < b.age )
			return 1;
		return -1;
	}
}

Stack用法

Stack意思是栈,具有先进后出的特点

与C++不同的是,Java的Stack遍历方式可以多样,因为Stack可以取到任意位置的值,而C++只能中规中矩的遍历。

可见Java的操作比C++更多

定义:

    	Stack s = new Stack();
    	Stack ss = new Stack();

操作:

push( Object obj );  插入元素到栈顶

add( Object obj );    插入元素到尾部  效果和push一样

    	Stack s = new Stack();
    	s.push(1);
    	s.add(2);

boolean empty();  判断队列是否为空

Object peek();    取栈顶元素

Object pop();     删除栈顶元素,返回的是删除的元素

int size();     返回栈的大小

结合以上几个方法,我们可以写出Stack的两种遍历方法

    	System.out.println("遍历");
    	for( int i = s.size()-1 ; i >= 0 ; i-- )	//从后往前遍历
    		System.out.println(s.get(i) );
    	
    	System.out.println("遍历");
    	while( s.empty() == false )
    	{
    		int t = s.peek();	
    		s.pop();
    		System.out.println(t);
    	}

void sort();  之前已经讲过啦,参加ArrayList的sort

void clear();   清空

 

下面是Stack用法小汇总

public class Main
{
    public static void main(String[] args) 
    {
    	Stack s = new Stack();
    	s.push(1);
    	s.add(2);		//add和push效果一样
    	
    	s.push(3);
    	
    	System.out.println( "位置为 1的地方是 "+ s.elementAt(1) );	//调用elementAt方法
    	
    	System.out.println("从前向后遍历");
    	for( Integer i:s )			//从前向后遍历  用到了foreach循环
    		System.out.println(i);
    	
    	System.out.println("从后向前遍历");
    	for( int i = s.size()-1 ; i >= 0 ; i-- )	//从后往前遍历
    		System.out.println(s.get(i) );
    	
    	System.out.println("类似C++Stack的遍历");
    	while( s.empty() == false )
    	{
    		int t = s.peek();	
    		s.pop();
    		System.out.println(t);
    	}
    	s.clear();	//清空栈
    	
    }
}

Queue用法

Queue就是队列,具有先进先出的特点

在Java中,没有Queue这个类,而是用到了LinkedList,所以我们定义的时候有点特殊

 

定义:

    	Queue q = new LinkedList();
    	Queue qq = new LinkedList();

操作:

boolean add( Object obj );  向队列中插入一个元素

boolean offer( Object obj );  向队列中插入一个元素

可以看出两个方法的功能一样,但是推荐使用第二个,在网上看的说add操作失败时会抛出异常,有点不是很明白

如果有问题的可以自己去百度一下吧

 

Object peek();     返回队首元素

Object poll();   删除并返回队首元素

当然因为是LinkedList实现的,所以LinkedList有的操作它都有,那么我就偷一下懒,不写啦

 

下面是Queue用法小汇总

public class Main
{
    public static void main(String[] args) 
    {
    	Queue q = new LinkedList();		//定义一个Sting类的Queue
    	
    	q.add("1");		//向队首加入元素
    	q.offer("1");   //功能与上一个一样,但是推荐使用第二个
    	q.offer("2");	
    	q.offer("3");
    	
    	q.poll();		//删除队首元素
    	
    	String t = q.peek();	//取队首元素
    	
    	System.out.println("foreach 遍历队列");
    	for( String s:q )
    		System.out.println(s);
    	
    	System.out.println("类似C++的队列遍历");
    	while( q.isEmpty() == false )
    	{
    		String s = q.peek();
    		q.poll();
    		System.out.println(s);
    	}
    	q.clear();
    }
}

 

⑥Set用法

Set表示集合,不能允许元素重复

Set又包括HashSet和TreeSet,第一个不自动排序,第二个自动排序

C++中STL有MultiSet(允许元素重复),而Java中自带的没有,似乎要自己去下载。

另外,Set是一个借口,不能实例化一个Set对象

Set继承Collection借口,所以有Collection的常见操作

定义:

    	Set s1 = new HashSet();
    	Set s2 = new TreeSet();
    	//或者
    	HashSet s3 = new HashSet();
    	TreeSet s4 = new TreeSet();

 

操作:

这里我偷一下懒,直接放张图片,嘻嘻

Java常用数据结构(个人笔记)_第1张图片

 

下面是Set用法小汇总

public class Main
{
    public static void main(String[] args) 
    {
    	Set s1 = new HashSet();
    	Set s2 = new TreeSet();
    	
    	s1.add("ABC");
    	s1.add("ABC");
    	s1.add("AAA");
    	
    	s2.add("AB");
    	s2.add("BB");
    	s2.add("CC");
    	
    	System.out.println("遍历HashSet");
    	Iterator it = s1.iterator();	
    	while( it.hasNext() )
    	{
    		String t = it.next();
    		System.out.println(t);
    	}
    	
    	s1.remove("ABC");		//删除ABC
    	if( s1.contains("ABC")  )		//调用contains方法,判断Set是否包含某个元素
    		System.out.println("ABC 还在");
    	
    	if( s1.isEmpty() )		//使用 isEmpty方法
    		System.out.println("s1空了");
    	
    	System.out.println("遍历TreeSet");
    	Iterator it2 = s2.iterator();		//TreeSet结果会自动排序
    	while( it2.hasNext() )
    	{
    		String t = it2.next();
    		System.out.println(t);
    	}
    	s1.clear();			//清空
    	s2.clear();
    }
}

 

Map用法

个人感觉Map是常用的数据结构里面最难的。

首先我们要知道map储存数据的方式,map储存数据的形式是一个key和一个value对应,即Map map = new HashMap(); 其储存的数据类型可以是任意的。

定义:

    	Map m = new HashMap();	//String 到 int的映射

操作:

put( Object Key,Object Value );    插入一组值

remove( Object Key );       删除键值为Key的那一组

get( Object Key );          得到键值为Key的那一组的Value

entrySet();             得到Pair集合(个人是这样理解的,pair就是一组)

keySet();        得到Key集合

values();       得到values集合

 

要想搞清楚Map,就要先搞清楚Key,Value和Entry的区别,

例如 Map m = new HashMap();

中,String就是Key,Integer就是Value,而 是一组Entry

所有组Entry构成了EntrySet

所有Key构成KeySet,同样所有Value构成ValueSet

 

下面是Map用法小汇总:

主要理解遍历啊

public class Main
{
    public static void main(String[] args) 
    {
    	Map m = new HashMap();	//String 到 int的映射
    	m.put("小明", 12);
    	m.put("小红", 11);	//向Map中插入一组值
    	m.put("小呆", 20);
    	
    	m.remove("小呆");		//删除Key为小呆的一组值
    	Integer t = m.get("小明");	//得到key为小明所在的值
    	System.out.println(t);		//得到结果为12
    	
    	//下面是Map的4种遍历方法
    	
    	System.out.println("Map遍历方法1:KeySet遍历");  //通过Key找Value,可想效率不是很高
    	for( String key: m.keySet() )
    		System.out.println(" Key:"+key+"  "+"value:"+m.get(key) );
    	
    	System.out.println("Map遍历方法2:ValueSet遍历"); //只遍历Map的value,不能遍历Key,所以有缺陷,但是比较快
    	for( Integer i:m.values() )
    		System.out.println("value "+i);
    	
    	System.out.println("Map遍历方法3: EntrySet遍历");		//遍历Map的每一组,推荐使用这种方法
    	for( Map.Entry entry : m.entrySet() )
    		System.out.println(" Key "+entry.getKey()+ "  "+"value: "+entry.getValue() );
    	
    	System.out.println("Map遍历方法4: EntrySet+Iterator遍历");	//比较复杂
    	Iterator< Map.Entry > it =  m.entrySet().iterator();
    	while( it.hasNext() )
    	{
    		Map.Entry entry = it.next();
    		System.out.println(" Key "+entry.getKey()+ "  "+"value: "+entry.getValue() );//这一步和上一种遍历一样	
    	}
    	
    }
}

 

另外Map还有一个HashTable,但是两者的差别是非常小的,而且HashTable已经快被淘汰

感兴趣的可以参考下面链接

http://www.importnew.com/24822.html

 

 

总结:

虽然我将的顺序是这样,但是分类的顺序却有些不一样

List接口是被四个类实现了

分别是ArrayList、LinkedList、Vector、Stack

Map接口是两个

HashMap、HashTable

Set接口是两个

HashSet、TreeSet

Queue接口是一个

 

所以我想说的是,编程时应该养成使用接口定义的好习惯,

即如果定义ArrayList ,用  List a = new ArrayList();   而不是 ArrayList a = new ArrayList();

如果定义LinkedList   ,用 List ll = new LinkedList();   而不是 LinkedList ll = new LinkedList();

 

至于为什么,

一句话,更灵活一些。

 

----------------------------------------------------------------------------------------------------------------------------------------------------

以上就是Java的常用数据结构啊,楼主知识短浅,还望多多指正。

第一次编辑,以后还会再回来看的。

---------------------2018/11/1

 

 

你可能感兴趣的:(Java学习)