04.尚学堂99-207.txt
UP 返回
1.容器
ArrayList初始容量为10
数组复制:System.arraycopy(src,srcPos,dest,destPos,length) 从src的srcPos位置向dest的destPos位置开始复制length长度的数据
LinkedList是一个双向链表
HashMap和HashTable一样的功能,前者线程不安全效率高,后者安全效率低
map的底层是数组+链表,,通过对hash值取余直接命中数组位置,通过链表处理冲突的元素。但是hashcode会存在负值,所以可以取绝对值再命中数组下标。
平时在使用hashcode时,如果需要保证一些散列问题,可以使用& Integer.MAX_VALUE 去符号,这只是为了解决负数问题,实际上会造成新的冲突
一般重写equals就会重写hashcode,这样保证了equals相同的对象hashcode一定相等,这是一个规范。如果不写或者重写成别的不合适的方式,会造成equals相同而hashcode不同
LinkedList里有一个查找方(查找之前判断下标位置,使查找变快):
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
HashSet是由HashMap实现的,直接将值作为key塞入,value是一个new的Object
集合的循环:
Iterator iter = set.iterator();while(iter.hasNext()) 或者 for(Iterator iter = set.iterator();iter.hasNext();)
通过Iterator中的游标来实现
map的循环:
Map <String,String>map = new HashMap<String,String>();
■1.最常见也是大多数情况下用的最多的,一般在键值对都需要使用
for(Map.Entry<String, String> entry : map.entrySet()){
String mapKey = entry.getKey();
String mapValue = entry.getValue();
}
■2.在for循环中遍历key或者values,一般适用于只需要map中的key或者value时使用,在性能上比使用entrySet较好
//key
for(String key : map.keySet()){
System.out.println(key);
}
//value
for(String value : map.values()){
System.out.println(value);
}
■3.通过Iterator遍历
Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while(entries.hasNext()){
Entry<String, String> entry = entries.next();
String key = entry.getKey();
String value = entry.getValue();
}
■4.通过键找值遍历,这种方式的效率比较低,因为本身从键取值是耗时的操作
for(String key : map.keySet()){
String value = map.get(key);
}
2.泛型
2.1 概念:泛型就是参数化类型,使用广泛的类型
起因:数据类型不明确
装入数据的类型都被当做Object对待,从而“丢失”自己的实际类型
获取数据时往往需要转型,效率低,容易产生错误
作用:
安全:在编译的时候检查类型安全
省心:所有的强制转换都是自动和隐式的,提高代码的重用率
使用:
泛型类需要在声明时使用泛型,泛型的字母可以任意设置,一般约定为:T Type 表示类型;K V 分别代表键值中的Key Value;E 代表Element。
在使用时需要确定泛型的类型
注意:
泛型只能使用引用类型,不能基本类型
泛型声明时字母不能使用在 静态属性|静态方法上(所以在接口中 泛型字母只能使用在方法中,不能使用在全局常量中)
泛型的方法, <> 需要写在返回类型前面。只能访问对象的信息,不能修改信息
代码:
//泛型类
public class Student<T1,T2> {
private T1 javaScore;
private T2 oracleScore;
//▶泛型声明时不能使用 静态属性|静态方法上
//private static T1 test;
public static void main(String[] args) {
//▶使用时指定类型(引用类型)
Student<String,Integer> stu = new Student<String,Integer> ();
//▶1、安全:类型检查
stu.setJavaScore("优秀");
//▶2、省心:类型转换
int it =stu.getOracleScore(); //自动拆箱
}
}
//泛型接口
public interface Comparator<T> {
void compare(T t);
}
//泛型方法
public class TestMethod {
public static void main(String[] args) {
test("a"); //T -->String
}
//泛型方法
public static <T> void test(T a){
System.out.println(a);
}
// extends <=
public static <T extends Closeable> void test(T... a){
for(T temp:a){
try {
if(null!=temp){
temp.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.2 泛型的继承:
比如父类含有泛型(属性,方法),子类继承时可以有4中情况。继承时对泛型的处理:要么同时擦除,要么子类大于等于父类的类型;不能子类擦除,父类泛型
继承以后的属性类型
在父类中,随父类而定
在子类中,随子类而定
继承以后方法重写:
方法中的泛型类型随父类而定
代码
//▶父类
public abstract class Father<T,T1> {
T name;
public abstract void test(T t);
}
/**
* 情况1
* 子类声明时指定具体类型
* 属性类型为具体类型
* 方法同理
*/
class Child1 extends Father<String,Integer>{
String t2;
@Override
public void test(String t) {
}
}
/**
* 情况2
* 子类为泛型类 ,类型在使用时确定
*/
class Child2<T1,T,T3> extends Father<T,T1>{
T1 t2;
@Override
public void test(T t) {
}
}
/**
* 情况3
* 子类为泛型类,父类不指定类型 ,泛型的擦除,使用Object替换
*/
class Child3<T1,T2> extends Father{
T1 name2;
@Override
public void test(Object t) {
}
}
/**
* 情况4
* 子类与父类同时擦除
*/
class Child4 extends Father{
String name;
@Override
public void test(Object t) {
}
}
/**
*错误情况:子类擦除,父类使用泛型(不允许)
class Child5 extends Father<T,T1>{
String name;
@Override
public void test(T t) {
}
*/
泛型接口与继承同理。重写方法随父类而定
//父接口
public interface Comparable<T> {
void compare(T t);
}
//1.声明子类指定具体类型
class Comp implements Comparable<Integer>{
@Override
public void compare(Integer t) {
// TODO Auto-generated method stub
}
}
//2.擦除
class Comp1 implements Comparable{
@Override
public void compare(Object t) {
// TODO Auto-generated method stub
}
}
//3.父类擦除,子类泛型
class Comp2<T> implements Comparable{
@Override
public void compare(Object t) {
// TODO Auto-generated method stub
}
}
//4.子类泛型>=父类泛型
class Comp3<T> implements Comparable<T>{
@Override
public void compare(T t) {
// TODO Auto-generated method stub
}
}
2.3 泛型没有多态,需要使用?来表示
通配符?表示类型不定,使用时再确定类型。只能用在声明类型|声明方法上,不能声明类或使用时使用
? extends : <= 上限 指定类型 子类或自身
? super :>=下限 指定类型 为自身或父类
代码:
public class Student<T> {
T score;
public static void main(String[] args) {
Student<?> stu = new Student<String>();
test(new Student<Integer>());
test2(new Student<Apple>());
//test3(new Student<Apple>()); //泛型没有多态
//test4(new Student<Apple>()); //<
stu = new Student<Fruit>();
//test4(stu); //使用时确定类型
test4(new Student<Object>());
test4(new Student<Fruit>());
}
public static void test(Student<?> stu){
}
public static void test3(Student<Fruit> stu){
}
// <=
public static void test2(Student<? extends Fruit> stu){
}
//>=
public static void test4(Student<? super Fruit> stu){
}
}
2.4 泛型的嵌套:
public class Bjsxt <T>{
T stu ;
//Bjsxt和Student都是一个含有泛型的类,故可以嵌套使用。取值时一层层拆分
public static void main(String[] args) {
//泛型的嵌套
Bjsxt<Student<String>> room =new Bjsxt<Student<String>>();
//从外到内拆分
room.stu = new Student<String>();
Student<String> stu = room.stu;
String score =stu.score;
System.out.println(score);
}
}
2.5 没有泛型数组。 声明可以使用,但是创建失败
//Student<String>[] arr2 = new Student<String>[10]; //错误
Student<?>[] arr2 = new Student[10];
在jdk1.7中使用泛型,声明一次类型即可,在使用|创建时不用指定类型
List<String> arrList= new ArrayList<String>();
List<String> arrList2= new ArrayList<>(); //1.7以下会报错
2.6 以下这种写法不会报错:
int score =(int)obj; //jdk1.7以后 Object -->integer -->自动拆箱 可以自动发生
但是如果是1.7以下,必须用包装类:int score=(Integer)obj;
增强for中的被循环对象,必须实现java.lang.Iterable接口,重写iterator方法。其实现方式就是根据迭代器来的
DOWN 返回