Java数据结构与排序

一、引子:想要给ArrayList排序却发现没有排序方法?你有两种选择:

          1、换用TreeSet;

        2、使用Collection.sort(List<T> list) / Collection.sort(List<T> list, Comparator<? super T> c)方法。

二、展开分析Java的几种主要数据结构及其排序方法:

LinkedList 高效操作元素
TreeSet  不重复,有序
HashSet 不重复,快速查找
HashMap  NVP(key不能重复),按Hash算法来存储,取出与存入顺序常常不一致
LinkedHashMap  NVP(key不能重复),可记住元素插入的顺序,取出与存入顺序一致

PS:  HashSet<T>.addAll(ArrayList<T>) 可以这样将所有的元素加进去

三、类型参数与泛型

  在API中常常看见的

public class ArrayList<E> extends AbstractList<E> {...}

这里的E会被实际传入的真正类型所取代,这个真正类型也称为类型参数。类ArrayList<E>被称为泛型的类

同样的,泛型的方法代表着方法声明用到类型参数。有两种运用方式:

(1)在使用了该类型参数的类中使用

1  public class ArrayList<E> extends AbstractList<E>{
2         public boolean add( E o){
3         ......
4         }
5 }

(2)在未使用该类型参数的类中使用,但不能将任何东西加入到集合中,只能读及调用方法:

(在返回类型前加上声明)

1  public <T extends Animal> void takeThing(ArrayList<T> list){
2         .....
3 }

或者使用?

1 public void takeThing(ArrayList<? extends Animal> animals){
2        .....
3 }

需要注意:这和以下代码代表的意思是不一样的:

1  public void takeThing(ArrayList<Animal> list){
2         .....
3 }

前者是表示类型参数只要是Animal或其子类就可以而后者只能是Animal

如果说对后者有了不正确的操作,比如加入了Animal的子类,也只会在运行期间才会被发现。

在泛型中,extend代表extend或implement

四、使用Collections.sort(List<T> list)方法

(一)对存放String的ArrayList排序

1 ArrayList<String> songList = new ArrayList<String>();
2 Collections.sort(songList);

(二)对存放对象的ArrayList排序

(1)对象需要实现Comparable<E>接口(重写compareTo方法,在里面写上比较逻辑),例:

1 public int compareTo( Song s ){
2        return title.compareTo( s.getTitle() );
3 }

(2)步骤与对String排序相同。

五、使用Collections.sort(List<T> list, Comparator<? super T> c)方法

该方法是使用自制的Comparator来帮助排序,以实现更加灵活的排序。

代码:

1  //内部类
2 class ArtistCompare implements Comparator<Song>{
3       public int compare(Song one, Song two){
4              return one.getArtist() . compareTo( two. getArtist());
5       }
6 }
7 ArtistCompare artistCompare = new ArtsitCompare();
8 Collections.sort(songList, artistCompare);

六、想一想,拿着两个对象,有那么多可以比较的方面,你比那个?所以:你以为对象的比较那么简单?

     hashCode()的默认行为是对堆上的对象产生独特的值。

equals()的默认行为是执行==的比较。也就是对象字节组合间的比较。

所以如果你没有重写过以上两个方法,两个对象无论如何都会被认为是不同的。

下面:引用的相等性和对象的相等性

1、引用的相等性:引用的是同一个对象,则引用是相等的。

调用hashCode()可以得到相同的结果,hashCode()会根据对象在内存上的位置返回一个专属的序号,该序号是不重复的。

可以用==来判断引用变量是否相等(对象的字节组合);

2、对象的相等性:如果你想把两个不同的对象视为相等的,必须覆盖从Object继承下来的hashCode()方法与equals()方法。使前者相等,后者返回true(之前提过原因)                但两个对象如果有相同的hashCode也不一定是相等的(存在杂凑算法的碰撞值)。

    覆盖的例子:以一首歌的标题来比较歌曲是否是相同:

 1 class Song implements Comparable<Song>{
 2       private String title;
 3       public boolean equals(Object o){
 4             Song s = (Song) o;
 5             return getTitle().equals(s.getTitle);
 6       }
 7       public int hashCode(){
 8             return getTitle().hashCode();
 9       }
10       public String getTitle(){
11             return this.title;
12       }
13 }

七、在介绍了上面对象之间如何比较后,还记得开头提到可以提到ArrayList的Treeset么?

  TreeSet的元素必须是(实现了)Comparable 或者 使用重载、取用了Comparator参数的构造函数

第二种举例:

  

1 TreeSet<Book> tree = new TreeSet<Book>(bCompare);  //bCompare是实现了Comparator接口类的一个对象

八、Map键值对的取得方式

1、传统方法1(转成set后取得)

2、传统方法2(转成set后取得)

   3、增强for循环(推荐, jdk1.5以后可使用)

不用iterater,直接迭代以上两种方法取得的set即可。

时间: 2024-08-01 22:47:48

Java数据结构与排序的相关文章

Java数据结构 遍历 排序 查找 算法实现

1. 遍历算法(遍历二叉树6种方法) 1.1. 概述 遍历算法针对二叉树而言的,主要有先序.中序.后序三种遍历顺序,三种顺序又分别有递归和常规算法,二叉树遍历的主要思想是:遍历左子树,遍历右子树,访问根节点,由这三者的遍历顺序来确定是先序.中序还是后序.下面只要求掌握递归遍历算法,常规遍历算法见附录一. 1.2. 先序遍历算法 遍历顺序:访问根节点,遍历左子树,遍历右子树.代码如下: void preOrder(BinaryTreeNode bt) { if (bt == null)// 如果当

Java数据结构之排序

1.冒泡排序:时间复杂度为O(n2) 假设是由小到大排序:相邻两个数之间进行比较,较大的数在后面.一次比较过后最大的数排在最后面 如:40.8.15.18.12一次排序后为:8.15.18.12.40依次排好直到由小到大拍好 for(int i = 0;i < n-i; i++){ for(int j = 0;j < n-1-i;j++){ //最后几位已经排好的就不需要再排序了 if(a[j] > a[j+1]){ k= a[j]; a[j] = a[j+1]; a[j+1] = k;

Java数据结构(排序篇)

冒泡排序:是经过n-1趟子排序完毕的,第i趟子排序从第1个数至第n-i个数,若第i个数比后一个数大(则升序,小则降序)则交换两数.大泡在上,小泡在下. 选择排序:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到所有待排序的数据元素排完. 选择排序是不稳定的排序方法. 插入排序:有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法--插入排序法,插入排序的基本操作就是将一个数据

Java数据结构之排序---冒泡排序

冒泡排序的基本思想: 通过对待排序序列从前到后(从下标小的元素开始),依次比较相邻位置的元素的值,若发现与给定的次序冲突,则交换位置(假设数值大的数放在序列的后面),使数值较大的元素逐渐从前移动到后部,就像冒泡一样. 对于冒泡排序,我们可以对它进行一定的优化: 在排序的过程中,每个元素都不断的接近自己的位置,当在一次排序中,我们发现,使用冒泡排序之后,该序列的任何两个个元素都没有进行交换,这个时候说明该序列已经有序,我们就不需要继续进行排序算法了,此时我们推出该排序算法.如果要执行这个优化,我们

Java数据结构之排序---选择排序

简单选择排序的介绍: 从给定的序列中,按照指定的规则选出某一个元素,再根据规定交换位置后达到有序的目的. 简单选择排序的基本思想: 假定我们的数组为int [] arr = new int[n],第一次我们从arr[0]~arr[n-1]中选择出最小的值与arr[0]交换.第二次我们从arr[1]~arr[n-1]中选择出最小的值与arr[1]交换.第三次我们从arr[2]~arr[n-1]中选择出最小的值与arr[2]交换,...,第i次我们从arr[i-1]~arr[n-1]中选择出最小的值

Java数据结构之排序---希尔排序

希尔排序的基本介绍: 希尔排序同之前的插入排序一样,它也是一种插入排序,只不过它是简单插入排序之后的一个优化的排序算法,希尔排序也被称为缩小增量排序. 希尔排序的基本思想: 希尔排序是把数组中给定的元素按照下标的一定增量进行分组,在分组之后,对每组使用直接插入排序算法:随着增量的减少,每组包含的元素越来越多,当增量减少到1的时候,整个数组正好被分成一组,此时该算法终止.通常我们判断增量是通过:第一次的增量=数组的长度/2(取整),第二次的增量=第一次的增量/2(取整)...一直到增量为1结束.

Java数据结构和算法之数组与简单排序

一.数组于简单排序 数组 数组(array)是相同类型变量的集合,可以使用共同的名字引用它.数组可被定义为任何类型,可以是一维或多维.数组中的一个特别要素是通过下标来访问它.数组提供了一种将有联系的信息分组的便利方法. 一维数组 一维数组(one‐dimensional array )实质上是相同类型变量列表.要创建一个数组,你必须首先定义数组变量所需的类型.通用的一维数组的声明格式是: type var‐name[ ]; 获得一个数组需要2步: 第一步,你必须定义变量所需的类型. 第二步,你必

Java中的数据结构及排序算法

(明天补充) 主要是3种接口:List Set Map List:ArrayList,LinkedList:顺序表ArrayList,链表LinkedList,堆栈和队列可以使用LinkedList模拟 Set:HashSet没有重复记录的集合 Map:HashMap就是哈希表 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap 数据结构参考链接

Java数据结构与算法之排序

排序从大体上来讲,做了两件事情: 1.比较两个数据项: 2.交换两个数据项,或复制其中一项 一.冒泡排序 大O表示法:交换次数和比较次数都为O(N*N). 算法原理: 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 3.针对所有的元素重复以上的步骤,除了最后一个. 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较. /** * 冒泡排序 demo * */