一、java集合类框架图
二、集合的特点
三、集合的排序
方法一、集合元素实现Comparable泛型接口,重写comparable方法
现有一个歌曲表单.txt,需要对其进行排序
双截棍/周杰伦 五环之歌/岳云鹏 Black/Pink Floyd/Numb Comfortable/Van Halen Breath/Kiss
1、先创建歌名实体类,
public class Song implements Comparable<Song>{
String title;
String artist;
public Song(String title, String artist) {
this.title = title;
this.artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return title;
}
/**
* 比较歌曲名
* @param song
* @return
*/
@Override
public int compareTo(Song song) {
return title.compareTo(song.getTitle());
}
}
2、测试
我们将需要排序的集合和自定义的排序类传入Collections的sort()方法里
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
public class Jukebox3
{
ArrayList<Song> songList = new ArrayList<>();
public static void main(String[] args)
{
new Jukebox3().go();
}
public void go()
{
getSong();
System.out.println(songList);
Collections.sort(this.songList); //调用Collections的sort()方法对集合进行排序
System.out.println(this.songList);
}
public void getSong()
{
File file = new File("E:\\java_project\\test\\src\\歌曲表单.txt");
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
addSong(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void addSong(String line) {
String[] tokes = line.split("/");
Song song = new Song(tokes[0],tokes[1]);
songList.add(song);
}
}
测试结果:可以看出按照字母顺序进行了排序
[双截棍, 五环之歌, Black, Floyd, Comfortable, Breath]
[Black, Breath, Comfortable, Floyd, 五环之歌, 双截棍]
方法二、自定义comparator
这一次我们不需要实现Comparable泛型接口,重写comparable方法。而是自定义一个comparator
1、创建歌曲类
public class Song {
String title;
String artist;
public Song(String title, String artist) {
this.title = title;
this.artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return title;
}
}
2、创建自定义排序类
import java.util.Comparator;
public class TitleCompare implements Comparator<Song> {
@Override
public int compare(Song o1, Song o2) {
return o1.getTitle().compareTo(o2.getTitle());
}
}
3、测试,我们将需要排序的集合和自定义的排序类传入Collections的sort()方法里
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
public class Jukebox3
{
ArrayList<Song> songList = new ArrayList<>();
public static void main(String[] args)
{
new Jukebox3().go();
}
public void go()
{
getSong();
System.out.println(songList);
//创建自定义排序
TitleCompare titleCompare = new TitleCompare();
Collections.sort(songList,titleCompare);
System.out.println(songList);
}
public void getSong()
{
File file = new File("E:\\java_project\\test\\src\\歌曲表单.txt");
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
addSong(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void addSong(String line) {
String[] tokes = line.split("/");
Song song = new Song(tokes[0],tokes[1]);
songList.add(song);
}
}
测试结果:同样能完成排序
[双截棍, 五环之歌, Black, Floyd, Comfortable, Breath]
[Black, Breath, Comfortable, Floyd, 五环之歌, 双截棍]
四、集合的去重
集合去重的精髓在于首先判断集合中两个对象是否相等,如果相等才能去重
问题:对象怎样才算相等?
1、引用相等
引用到堆上同一个对象的两个引用是相等的,这就是引用的相等性。
如果想要知道两个引用是否相等,可以使用==来比较变量上的字节组合,如果引用到相同的对象,字节组合也会一样:
if (foo == bar){ // 两个引用都指向同一个对象 }
2、对象相等
堆上的两个不同对象在意义上是相同的,这就是对象的相等性。
两个对象相等的条件是它们的hashCode相等,而且调用以另一个对象为参数的equals时返回true:
if (foo.equals(bar) && foo.hashCode() == bar.hashCode()) { // 两个引用指向同一个对象或者两个对象是相等的 }
我们知道所有的类都继承自Object类,而Object类默认的equals方法是使用==进行比较:
public boolean equals(Object obj) { return (this == obj); }
Object类的hashCode函数:
public native int hashCode();
是一个native函数,而且返回值类型是整形;实际上,该native方法将对象在内存中的地址作为哈希码返回,可以保证不同对象的返回值不同。
因此,要比较两个对象的相等性,首先需要重写equals和hashCode方法。
下面我们重写上面的例子,首先加入有重复的歌曲名单
双截棍/周杰伦 五环之歌/岳云鹏 Black/Pink Floyd/Numb Comfortable/Van Halen Breath/Kiss Breath/Kiss Breath/Kiss
1、重写equals和hashCode方法
我们根据歌曲名判断对象的相同,由于歌曲名是String类型的,实际上String类型重写了Object的equals和hasCode方法,它是根据字符串内容比较相等。
public class Song {
String title;
String artist;
public Song(String title, String artist) {
this.title = title;
this.artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return title;
}
public boolean equals(Object song)
{
Song s = (Song) song;
return getTitle().equals(s.getTitle());
}
public int hashCode()
{
return title.hashCode();
}
}
2、使用Set进行去重
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
public class Jukebox3
{
ArrayList<Song> songList = new ArrayList<>();
public static void main(String[] args)
{
new Jukebox3().go();
}
public void go()
{
getSong();
System.out.println(songList);
//创建自定义排序
TitleCompare titleCompare = new TitleCompare();
Collections.sort(songList,titleCompare);
System.out.println(songList);
HashSet<Song> songSet = new HashSet<>();
songSet.addAll(songList);
System.out.println(songSet);
}
public void getSong()
{
File file = new File("E:\\java_project\\test\\src\\歌曲表单.txt");
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
addSong(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void addSong(String line) {
String[] tokes = line.split("/");
Song song = new Song(tokes[0],tokes[1]);
songList.add(song);
}
}
测试结果:我们可以看到加入HashSet的元素被去重了
[双截棍, 五环之歌, Black, Floyd, Comfortable, Breath, Breath, Breath]
[Black, Breath, Breath, Breath, Comfortable, Floyd, 五环之歌, 双截棍]
[Breath, 五环之歌, Floyd, 双截棍, Black, Comfortable]