JAVA自学笔记17

JAVA自学笔记17

1、Map接口
1)概述
将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。可以存储键值对的元素
2)与Collection接口的不同:
①Map是双列的(成对出现),Collection是单列的
②Map的键是唯一的,值是可重复的。Collection的子体系Set是唯一的,List是可重复的
③Map集合的数据结构针对键有效,与值无关;Collection集合的数据结构是针对元素有效

2、登录注册集合版
1)图解:
这里写图片描述
2)这里写图片描述
这里写图片描述
3)代码:见视频17.04-07

3、Vector类
1)底层数据结构为数组,查询快,增删慢。线程安全,效率低
2)Vector类特有功能
①public void addElement(E obi)
添加功能

Vector v=new Vector();
v.addElement("abc");

②public E elementAt(int index)
返回指定索引处的组件
③public Enumeration element()

Enumeration en=v.elements();
while(en.hasMoreElement()){
String s=(String)en.nextElement();
System.out.println(s);//与迭代器相似
}

3、LinkedList类
1底层数据结构是链表。查询慢,增删快。线程不安全,效率高
2)特有功能:
①public void addFirst(E e)及addLast(E e)
在开头或在最后一个添加
②public E getFirst()及getLast()
返回第一个或最后一个元素
③public E removeFirst()及public E removeLast()
移除并返回第一个或最后一个元素

@例题1:去集合中字符串的重复值

ArrayList array=new ArrayList();

array.add("abc");
array.add("adc");
array.add("abc");
array.add("abc");

ArrayList newArray=new ArrayList();
Iterator it=array.iterator();
while(it.hasNext()){
String s=(String)it.next;
if(!newArray.contains(s)){
newArrray.add(s);
}
}
//遍历新集合即可

//若要求不能创建新集合
//选择排序思想
for(int x=0;x<array.size()-1;x++){
for(int y=x+1;y<array.size();y++){
if(array.get(x).equals(array.get(y))){
arr.remove(y);
y--;
}
}
}

@例题2:去除自定义对象(对象成员变量值相同的)

ArrayList array=new ArrayList();

//创建学生对象
Student s1=new Student("c");
Student s2=new Student("w");
Student s3=new Student("w");
Student s3=new Student("w");

//注意:contains()方法底层依赖的是equals()
//方法。而我们的学生类中没有equals()方法。因此使
//用的是父类的Object方法,比较的是地址值。
Iterator it=array.iterator();
while(it.hasNext()){
Student s=(Student)it.next();

if(!newArrray.contains(s)){
newArray.add(s);
}
}

@例题3:用LinkedList实现栈

//使用addFirst(),先进后出
//LinkedList link=new LinkedList();
Student s1=new Student("c");
Student s2=new Student("w");
Iterator it=link.iterator();
while(it.hasNext()){
String s=String it.next();
System.out.println(s);
}

//用集合实现
public class MyStack{
private LinkedList link;
public MyStack(){
link=new Linkedlist();
}
public void add(Object obj){}
public Object get{
return link.gerFirst();}
link.RemoveFirst();
}

4、泛型
1)是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。也被称为参数化类型
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在着隐患,不安全
2)格式:
<数据类型>//此处的数据类型只能是引用类型
3)优点:把运行时期会出现的问题提前到编译期间,避免了强制类型转换,优化了程序设计
4)泛型使用的场景: 看API,如果类,接口,抽象类后面跟有就要使用泛型,一般来说就是在集合中使用
5)应用:
①泛型类:把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
public class ObjectTool{
private T obj;
}
②泛型方法
把泛型定义在方法上
格式:public<泛型类型> 返回类型 方法名(泛型类型1 变量名1…)

③泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>

public interface Inter<T>{
public abstract void show(T t);

}
public class InterImpl<T> implements Inter<T>{
}

6)通配符

Collection<?>c1=new ArrayList<Object>();
Collection<? extends Animal>c1=new ArrayList<Cat>();
Collection<? super Animal>c1=new ArrayList<Object>();

@例题3:泛型改进字符串遍历问题

ArrayList<String> array=new ArrayList<String>();

array.add("s");
array.add("ss");
array.add("sss");

while(it.hasNext()){
String s=it.next();//不用泛型
System.out.println(s);
}

//遍历
for(int x=0;x<array.size();x++){
String s=array.get(x);
System.out.println(s);
}

@例题4:ArrayList存储自定义对象并遍历

ArrayList<Student> array=new ArrayList<Student>();

Student s1=new Student("s");
Student s2=new Student("s2");
Student s3=new Student("s3");

array.add(s1);
array.add(s2);
array.add(s3);

//遍历:
Iterator<Student> it=array.iterator();
while(it.hasNext()){
Student s=it.next;
System.out.println(s);
}

5、set接口
1)一个不包括重复元素的collection
2)特点:无序,存储顺序和取出顺序不一致。

Set<String> set=new HashSet<String>();
set.add("abc");
set.add("def");

for(String s:set){
System.out.println(s);
}

3)实现类HashSet
不保证set的迭代顺序,特别是它不保证该顺序恒久不变,但它有它自己的存储顺序.
底层结构式哈希表(元素时链表的数组),哈希表依赖于哈希值存储

HashSet存储字符串
HashSet <String> hs=new HashSet<String>();
hs.add("abc");
hs.add("def");

for(String s:hs){
System.out.println(s);
}

4)HashSet保证元素唯一性的解析(不懂):如果两个对象的成员变量值都相同,则为同一个对象。底层依赖的是HashCode ()和equals()方法,如果不重写,这时它们的哈希值是不会一样的,唯一性失效。

通过查看add方法的源码,得知这个方法底层依赖两个方法:hashCode()和equals(),步骤:
首先比较哈希值,如果相同,继续比较地址值或者执行equals,equals()如果为真,说明元素重复,就添加到集合中;哈希值若不同,就直接添加到集合中。

若使用的是HashSet集合。这个集合的底层是哈希表结构的。而哈希表结构的底层依赖:hashCode()和equals()方法。如果认为对象的成员变量值相同即为同一个对象的话,就应该重写这两个方法。不用手写,系统自动生成即可。右键-generate hashcode() and equals()

@例题7:HashSet存储自定义对象并遍历

HashSet<Student> hs=new HashSet<Student>();
String s=new Student("dd");
String s2=new Student("ed");//需重写上述两方法

hs.add(s1,1);
hs.add(s2,20)

for(Student s:hs){
system.out.println(s);
}

//在Student类中重写上述两方法
public int hashCode(){
//return 0;//哈希值都一样
return this.name.hashCode()+this.age.HashCode();
}
public boolean equals(Object obj){
if(this == obj){//如果比较对象是本身,则不用比较直接返回true
return true;}
}
if(!(obj instanceof Student)){//若比较对象不是同一类,则不进行比较
return false
}
Student s=(Student) obj;
return this.name.equals(s.name)&& this.name.equals(s.age);

上述代码的图解示意图:
这里写图片描述

6、LinkedHashSet:
1)元素有序唯一,由链表保证元素有序,由哈希表保证元素唯一

7、TreeSet类概述:
1)使用元素的自然顺序(无参构造时)对元素进行排序或根据创建set类时提供的Comparator比较器进行排序。这取决于使用的构造方法
2)TreeSet的数据结构是红黑树(红黑树是一种自平衡的二叉树),以此保证元素的排序和唯一性

TreeSet<Integer> ts=new TreeSet<Integer>();

ts.add(104);
ts.add(103);
ts.add(101);
ts.add(101);//自动装箱

for(Integer i:ts){
System.out.println(ts);
}

2)保证元素排序的解析
真正比较是依赖于元素的compareTo()方法,而这个方法是定义在Comparable里面的。所以,若要想重写该方法,就必须是先Comparable 接口。这个接口表示的就是自然排序。
一个类如果想实现自然排序,就必须实现自然排序接口
图解:这里写图片描述

@例题8:TreeSet存储自定义对象并练习

TreeSet<Student> ts=new TreeSet<Student>();

//创建对象省略,以s1,s2,s3代替
for(Student s:ts){
System.out.println(s);

//在原类Student中重写compareTo方法
public class Student implements Comparable<Student>{
public int compareTo(Student s){
int num=this.age-s.age;
int num2=num==0?this.name.compareTo(s.name):num;
return num2;//年龄从小到大排,要自己分析出主次条件
}}}

3)比较器排序

//通过查看api发现构造方法与自然排序有区别
public TreeSet(Comparator comparator){
TreeSet<Student> ts=new TreeSet<Student>(new MyComparator());
} 

//需自行创建Comparator类
public class MyComparator implements Comparator<Student>{
public int compare(Student s1,Student S2){
//this——s1,s--s2,重要条件为姓名长度
int num=s1.getName()-s2.getName();
int num2=num==0?s1.getName().compareTo(s2.getName()):num;///次要条件
return num2;
}
}

//使用匿名内部类可不用另外创建Comparator类
下图

这里写图片描述

原文地址:https://www.cnblogs.com/Tanqurey/p/10485328.html