List和Set(笔记19)

List和Set

一、List接口

List集合代表一个有序的集合 ,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,通过索引来访问指定位置的集合元素。
List集合在Collection的基础上新添加的方法:
(1)void  add (int index,Object element):将元素element插入在List集合的index处。
(2)boolean  addAll(int index,Collection c):将集合c所包含的所有元素都插入在List集合的Index处。
(3)Object  get(int index):返回集合index索引处的元素。
(4)int  indexOf(Object o):返回对象o在List集合中出现的位置索引。
(5)int  lastIndexOf(Object o):返回对象o在List集合中最后一次出现的位置索引。
(6)Object  remove(int index):删除并返回index索引处的元素。
(7)Object  set(int index,Object element):将index索引处的元素替换成element对象,返回新元素。
(8)List subList(int fromIndex,int toIndex):返回从索引fromIndex(包含)到索引toIndex(不包含)处所有集合元素组成的子集合。

List集合的特有特性
List派生于 Collection 接口
1)最大的特点: 集合中的元素有序 ( 可以根据索引进行存取 )  //Set 集合中的元素无序)
2)可以存放重复的元素  //Set集合不可以
List =>
ArrayList   //底层是数组,查询快, 添加,删除慢,线程不安全
LinkedList  //底层是链表,查询慢,但是删除,增加速度快,线程不安全
Vector // 底层是数组,集合框架是jdk1.5后出现的, Vector 在jdk1.2的时候就出现了,线程安全
// --add(int index, E element)  往某个位置上添一个元素
// --addAll(int index, Collection<? extends E> c) 往某个位置上添一组元素
// -- E get(int index)  根据索引取元素
// -- int indexOf(Object o) 查询一个元素在集合中的索引
// -- listIterator() 用来遍历 
// -- E set(int index, E element)  把集合中某个位置上的元素,换成指定的值 ,返回值是指被换出来的那个元素
//  -- void remove(int position) 簃除指定位置上的元素
//  -- List<E> subList(int fromIndex, int toIndex )  取集合中的一段,和substring很象

static void demo1(){
List  list=new ArrayList();
list.add("邓晓慧");
list.add("宋歌");
list.add("岳鹏宇");
list.add(1,"李哲");  //把李哲放在了第二个位置上
System.out.println(list);  //[邓晓慧, 李哲, 宋歌, 岳鹏宇]
list.remove(3);
System.out.println(list);  //移除索引为3的元素 [邓晓慧, 李哲, 宋歌]
System.out.println(list.indexOf("宋歌")); //2 根据元素取索引
Object result=list.set(0, "师大导员");
System.out.println("被放出来的人:"+result); //邓晓慧
System.out.println(list); //[师大导员, 李哲, 宋歌]
System.out.println(list.get(2)); //宋歌
//list集合能用for遍历
for(int i=0;i<list.size();i++){
System.out.println(list.get(i)); //师大导员  李哲  宋歌
}
}

4.2 在list集合中添加自定义对象
public class Test3 {
public static void main(String[] args) {
test();
}
static void test(){
List list=new ArrayList();
Student stu1=new Student(20,"宋歌");
Student stu2=new Student(21,"邓晓慧");
Student stu3=new Student(23,"岳鹏宇");
list.add(stu1);
list.add(stu2);
list.add(stu3);
/*for(int i=0;i<list.size();i++){
((Student)list.get(i)).speak();  //给我记住要强转
}*/
System.out.println(list.contains(stu2)); //true
System.out.println(list.indexOf(stu2));  //1
}
}

class Student{
int age;
String name;
void speak(){
System.out.println("我是"+name +" 我正在说话");
}
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
}
    
//如果在List 集合中存放自定义对象, 请尽量重写对象的equals方法
static void test2(){
List list=new ArrayList();
list.add(new Student(20,"宋歌"));
list.add(new Student(22,"邓晓慧"));
list.add(new Student(23,"岳鹏宇"));
System.out.println(list.contains(new Student(22,"邓晓慧"))); // 如果不重写equals ,返回的是false
System.out.println(list.indexOf(new Student(22,"邓晓慧")));  // 如果不重写equals,返回的是 -1
}
equals的重写:
class Student{
int age;
String name;
void speak(){
System.out.println("我是"+name +" 我正在说话");
}
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public boolean equals(Object obj) {
if(this==obj){
return true;
}
if(obj instanceof Student){
Student stuTemp=(Student) obj;
if(this.age==stuTemp.age && this.name.equals(stuTemp.name)){
return true;
}
else{
return false;
}
}
else{
return false;
}
}
}

附: 简单的模拟
public class MyArrayList {
Object [] data;
int index=0;
public MyArrayList(){
data=new Object[10];
}
public void add(Object obj){
data[index++]=obj;
}
public boolean contains(Object obj){
for (int i = 0; i < index; i++) {
if(data[i].equals(obj)){
return true;
}
}
return false;
}
public int indexOf(Object obj){
for (int i = 0; i < data.length; i++) {
if(data[i].equals(obj)){
return i;
}
}
return -1;
}
public void show(){
for (int i = 0; i <index; i++) {
System.out.println(data[i]);
}
}
}

class T{
public static void main(String[] args) {
MyArrayList m=new MyArrayList();
m.add("数据一");
m.add("数据二");
m.add("数据三");
m.add("数据四");
m.show();
System.out.println(m.indexOf("数据三"));
System.out.println(m.contains("数据五十四"));
}
}

二、Vector 和 Enumeration 接口

Vector jdk1,2 就出现了,线程安全 ,底层也是数组
static void demo1(){
Vector v=new Vector();
v.add("元素一");
v.add("元素二");
v.add("元素三");
v.add("元素四");
v.add(3, "这是一个插队的");
//使用for进行迭代
for (int i = 0; i <v.size(); i++) {
System.out.println(v.get(i));
}
//使用Collection 集合的iterator进行迭代
Iterator it= v.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//使用 Enumeration 进行迭代
Enumeration e=v.elements();
while(e.hasMoreElements()){
System.out.println( e.nextElement());
}
}

三、LinkedList 

底层是链表,增,删快,查询比ArrayList 慢
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。
除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 
元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
例子,使用   LinkedList 模拟一个队列
//队列
public class Queue {
private LinkedList list;
public Queue(){
list=new LinkedList();
}
public void put(Object obj){
list.addLast(obj);
}
public Object get(){
if(list.size()!=0){
return list.removeFirst();
}
else{
throw new RuntimeException("没有元素了!!!");
}
}
}

class T{
public static void main(String[] args) {
Queue q=new Queue();
q.put("第一");
q.put("第二");
q.put("第三");
q.put("第四");
System.out.println(q.get());
System.out.println(q.get());
System.out.println(q.get());
System.out.println(q.get());
System.out.println(q.get());  //NoSuchElementException
//输出 第一  第二  第三 第四
}
}

四、Set 集合

1) Set 也是来自Collection 所以它的功能和 Collection 是一致的
2) Set 集合是无序的 
3) Set 集合中不能存入重复元素,最多只能有一个NULL 
4) Set 底层是Map
子类 
  - HashSet 
  - TreeSet 
static void setDemo(){
Set set=new HashSet();
set.add("桃");
set.add("桃");
set.add("杏");
set.add("杏");
set.add("杏");
set.add("李子");
set.add("花");
set.add("树");
set.add(null);
System.out.println(set);  //[null, 桃, 杏, 李子, 树, 花]
}

//例子  如何给一个ArrayList中的元素去重 可以使用Set集合的特性
Collection c=new ArrayList();
c.add("aaa"); 
c.add("aaa"); 
c.add("bbb"); 
c.add("aaa"); 
c.add("ccc"); 
c.add("aaa"); 
c.add("ddd"); 
c.add("aaa"); 
Set set=new HashSet(c); //[aaa, ddd, ccc, bbb]
System.out.println(set);

五、Set 集合的相等判断

对于List集合,进行相等判断,它只需要判断对象的equals方法的返回值
对于Set 集合,进行相等判断的时候,它先判  对象的 hashCode() 方法的返回值是不是相同,
如果相同了,再用 equals() 方法判断, 只有两者完全相同,它才认为两个对象是相等的
  
//例子
public class Test2 {
public static void main(String[] args) {
Set set=new HashSet();
set.add(new Student("赵明明",20));
set.add(new Student("姜博文",22));
set.add(new Student("张悦",20));  //add方法有返回值,成功了,返回true,如果已经有这个元素了,添不成功,则返回false
set.add(new Student("张悦",20));
set.add(new Student("张悦",20));
set.add(new Student("张悦",20));
set.add(new Student("李雪",20));
Iterator it =set.iterator();
while(it.hasNext()){
((Student)it.next()).speak();;
}
}
}

class Student extends Object{
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//重写hashCode
public int hashCode() {
return  this.name.hashCode() +age;
}
public boolean equals(Object obj) {
if(this==obj){
return true;
}
if(obj instanceof Student){
Student temp=(Student)obj;
if(this.age==temp.age&&this.name.equals(temp.name)){
return true;
}else{
return false;
}
}else{
return false;
}
}
public void speak(){
System.out.println("我是学生:"+this.name +" 我的年龄是:"+this.age);
}
}

六、TreeSet 

底层是二叉排序树 
5.1 TreeSet的自动排序
static void demo1(){
TreeSet s=new TreeSet();
s.add(5);  //自动装箱
s.add(1);
s.add(2);
s.add(7);  //TreeSet 也是Set ,所以它也去重复
s.add(7);
s.add(7);
s.add(4);
s.add(3);
s.add(9);
s.add(8);
Iterator it=s.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//可以看到,默认是按自然顺序排序,如果是数字,就按大小长顺,如果是字母,就按字母顺升序
}

5.2 TreeSet 通过实现 Comparable 接口进行排序  
// TreeSet 这个家伙,去不去重,不用hashCode,也不用equals,它就看 compareTo 返回结果是不是0
//例子 使用  TreeSet 对自定义对象进行排序
public class Test2 {
public static void main(String[] args) {
  TreeSet ts=new TreeSet();
  ts.add(new Student("张悦", 20));  //如果Student 不实现  Comparable,将出现 : Student cannot be cast to java.lang.Comparable
  ts.add(new Student("姜博文", 22));
  ts.add(new Student("周应利", 10));
  ts.add(new Student("周应利", 10));
  ts.add(new Student("周应利", 10));
  ts.add(new Student("赵庆", 30));
  ts.add(new Student("赵明明", 25));
  Iterator it=ts.iterator();
  while(it.hasNext()){
  System.out.println(it.next());
  }
}
}

//将来是每个本类对象,都知道这个比较规则
class Student extends Object implements Comparable{
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
//如果返回值大于0,则代表比人家大,如果小于0,则代表比人家小,如果是0,代表和人家相等
public int compareTo(Object o) {
Student temp=(Student)o;
if(this.age>temp.age){
return 10;
}else if(this.age==temp.age){
return 10;  //注意,如果这里返回0,则会产生对重复数据去重的结果
}else{
return -10;
}
}
}

5.3 TreeSet 通过自定义比较器排序
//使用自定义比较器进行比较 ,所谓的自定义比较器,就是一个实现了 Comparator 接口的类
class MyComparator implements Comparator{
public int compare(Object o1, Object o2) {
Student stu1=(Student)o1;
Student stu2=(Student)o2;
if( stu1.age>stu2.age){
return 1;
}else if(stu1.age==stu2.age){
return 0;
}else{
return -1;
}
}
}

public class Test2 {
public static void main(String[] args) {
  TreeSet ts=new TreeSet(new MyComparator() );
  ts.add(new Student("张悦", 20));  //出现 : Student cannot be cast to java.lang.Comparable
  ts.add(new Student("姜博文", 22));
  ts.add(new Student("周应利", 10));
  ts.add(new Student("周应利", 10));
  ts.add(new Student("周应利", 10));
  Iterator it=ts.iterator();
  while(it.hasNext()){
  System.out.println(it.next());
  }
}
}

//例子 往treeSet中放字符串,按长度进行排序
class StrLenComparator implements Comparator{
public int compare(Object o1, Object o2) {
String s1=(String)o1;
String s2=(String)o2;
if(s1.length()<s2.length()){
return 1;
}else if(s1.length()==s2.length()){
return  1; //不返回0的原因是不想去重
}else{
return -1;
}
}
}

public class Test4 {
public static void main(String[] args) {
TreeSet  ts=new TreeSet(new StrLenComparator());
ts.add("aaaaaaaa");
ts.add("abbaa");
ts.add("ee");
ts.add("axxaa");
ts.add("aaffffffffa");
ts.add("a");
ts.add("aaa");
Iterator it=ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
  
//例子,使用 //匿名的内置类
public static void main(String[] args) {
new Object(){
int a;
String b;
void eat(){
System.out.println("吃饭");
}
};   
}
  
//把上例改为使用匿名的内置类实现
public class Test4 {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new Comparator() {
public int compare(Object o1, Object o2) {  //使用了匿名的内置类
String s1=(String)o1;
String s2=(String)o2;
if(s1.length()<s2.length()){
return 1;
}else if(s1.length()==s2.length()){
return  1; //不返回0的原因是不想去重
}else{
return -1;
}
}
}); 
ts.add("aaaaaaaa");
ts.add("abbaa");
ts.add("ee");
ts.add("axxaa");
ts.add("aaffffffffa");
ts.add("a");
ts.add("aaa");
Iterator it = ts.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

总结: 比较相关的问题 
List =>只看equals 
HashSet => 先看hashCode,再 equals
TreeSet => 只看 compareTo() 或 compare() 方法的结果

猜你喜欢

转载自blog.csdn.net/weixin_41205479/article/details/80221326