首页 > 编程知识 正文

java数组转set集合,java集合排序

时间:2023-05-04 23:39:29 阅读:52810 作者:3673

实现序列化接口,表明支持序列化。

)支持克隆(超类克隆) )实现了Cloneable接口,该接口调用方法以指示可以进行浅复制。

继承AbstractSet抽象类,与ArrayList和链接列表一样,他们的抽象父类提供了equals (方法和hashCode )方法。 它们本身没有实现这两种方法。 (但ArrayList和链接列表的equals )实现是不同的。 请看我的ArrayList源代码分析。 (这意味着与HashSet一样从AbstractSet抽象类继承的TreeSet、LinkedHashSet等。 如果元素的数量与集合中的元素相同(即使是AbstractSet的不同子类,也是equals ) )。下面的代码是JDK的equals ) )代码。

从JDK源代码可以看出,基本上,通过调用AbstractCollection的containsAll ) )方法,而不是用我们通常认为的hashcode )方法求出的值进行比较,可以在他们中间

公共布尔型(对象) if ) o==this )返回真; if (! (集实例) )返回假;

collectionc=(collection ) o; //元素的个数必须相等。

if(c.size )!=size () )返回假; 调用了try//abstractcollection的方法。

返回容器(c;

} catch (classcastexceptionunused ) {return false;

} catch (nullpointerexceptionunused ) {return false;

}

}

只要逐一判断publicbooleancontainsall (collection c )//收藏中包含的要素即可。

for(objecte:c ) if (! 连续(e ) )返回假; 返回真;

}

实现了Set接口。

平时的规则是先把总结放在上面:

HashSet内部使用HashMap的键存储集合中的元素,并且内部HashMap的所有值

全部为空。 (向HashSet添加元素时,所有内部HashMap值都是PRESENT ),因此PRESENT直接在实例域位置初始化,不允许更改。

HashSet对外提供的所有方法都是内部通过HashMap操作完成的,要真正了解HashSet的实现,只需了解HashMap的原理即可。 我也分析了关于HashMap的事情。 传送门:

因此,如果你熟悉HashMap,学习HastSet的源代码很容易!

1 (首先,让我们看看HashSet的哪个实例域: (减少了很多,而且不是很简单吗(o )……)。

//序列化ID

staticfinallongserialversionuid=-502474406713321676 l; //基础使用了HashMap存储数据。

隐私转移hashmap图; //用于将值填充到基础数据结构的HashMap中。 因为HashSet只用key保存数据。

私有对象=新对象(;

2 )虽然是往常的规则,但是先看看构造方法吧。

构造函数的实现基本上使用HashMap

//其实只是实例化了HashMap(o )…(不知道的童鞋可以看我关于Hashmap的其他源代码分析)

公共散列()。

map=new HashMap (;

}

//还是

公共散列(collectionextendsec )。

map=newhashmap(math.max((int ) ) c.size )/. 75f (1,16 ) );

addall(c;

//调用的AbstractCollection方法。 然后,调用HashSet的add ) )方法,将集合中的//所有元素添加到集合中。 (因为)

publicbooleanaddall (collectionextendsec ) {

布尔修改=假; for(e:c ) if (添加) e ) )

修改=true; re

turnmodified;

}//底层并不支持直接在AbstractCollection类中调用add()方法,而是调用add()方法//的自身实现。

publicboolean add(E e) {throw newUnsupportedOperationException();

}

//初始化HashSet仍然是关于HashMap的知识。

public HashSet(intinitialCapacity) {

map= new HashMap<>(initialCapacity);

}

//初始化HashSet仍然是关于HashMap的知识。

public HashSet(int initialCapacity, floatloadFactor) {

map= new HashMap<>(initialCapacity, loadFactor);

}

//这次初始化底层使用了LinkedHashMap实现。

HashSet(int initialCapacity, floatloadFactor, boolean dummy) {

map= new LinkedHashMap<>(initialCapacity, loadFactor);

}

3:添加新的元素:

//底层仍然利用了HashMap键进行了元素的添加。//在HashMap的put()方法中,该方法的返回值是对应HashMap中键值对中的值,而值总是PRESENT,//该PRESENT一直都是private static final Object PRESENT = new Object();//PRESENT只是初始化了,并不能改变,所以PRESENT的值一直为null。//所以只要插入成功了,put()方法返回的值总是null。

publicboolean add(E e) {return map.put(e, PRESENT)==null;

}

4:删除一个元素:

//该方法底层实现了仍然使用了map的remove()方法。//map的remove()方法的返回的是被删除键对应的值。(在HashSet的底层HashMap中的所有//键值对的值都是PRESENT)

publicboolean remove(Object o) {return map.remove(o)==PRESENT;

}

5:清空方法

public voidclear() {

map.clear();

}

6:克隆方法(浅克隆)

底层仍然使用了Object的clone()方法,得到的Object对象,并把它强制转化为HashSet,然后把它的底层的HashMap也克隆一份(调用的HashMap的clone()方法),并把它赋值给newSet,最后返回newSet即可。

@SuppressWarnings("unchecked")publicObject clone() {try{

HashSet newSet = (HashSet) super.clone();

newSet.map= (HashMap) map.clone();returnnewSet;

}catch(CloneNotSupportedException e) {throw newInternalError(e);

}

}

7:是否包含某个元素

底层仍然使用了HashMap的containsKey()方法(因为HashSet只用到了HashMap的键)同样的话重复了好多遍 ……….(艹皿艹 )

publicboolean contains(Object o) {returnmap.containsKey(o);

}

8:判断是否为空

仍然调用HashMap的方法。

publicboolean isEmpty() {returnmap.isEmpty();

}

9:生成一个迭代器

仍然使用了HashMap的键的迭代器

public Iteratoriterator() {returnmap.keySet().iterator();

}

10: 统计HashSet中包含元素的个数

还是调用HashMap的实现。

public intsize() {returnmap.size();

}

11:把HashSet写入流中(也就是序列化)

在HashSet序列化实现中,仍然是把HashMap中的属性写入流中。(因为HashSet中真正存储数据的数据结构是HashMap。)

private voidwriteObject(java.io.ObjectOutputStream s)

throws java.io.IOException {//Write out any hidden serialization magic

s.defaultWriteObject();//Write out HashMap capacity and load factor//把HashMap的容量写入流中。

s.writeInt(map.capacity());//把HashMap的装载因子写入流中。

s.writeFloat(map.loadFactor());//把HashMap中键值对的个数写入流中。

s.writeInt(map.size());//按正确的顺序把集合中的所有元素写入流中。

for(E e : map.keySet())

s.writeObject(e);

}

12:从流中读取数据,组装HashSet(反序列化)

private voidreadObject(java.io.ObjectInputStream s)

throws java.io.IOException, ClassNotFoundException {//Read in any hidden serialization magic

s.defaultReadObject();//Read capacity and verify non-negative.

int capacity =s.readInt();if (capacity < 0) {throw new InvalidObjectException("Illegal capacity:" +capacity);

}//Read load factor and verify positive and non NaN.

float loadFactor =s.readFloat();if (loadFactor <= 0 ||Float.isNaN(loadFactor)) {throw new InvalidObjectException("Illegal load factor:" +loadFactor);

}//Read size and verify non-negative.

int size =s.readInt();if (size < 0) {throw new InvalidObjectException("Illegal size:" +size);

}//Set the capacity according to the size and load factor ensuring that//the HashMap is at least 25% full but clamping to maximum capacity.

capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f),

HashMap.MAXIMUM_CAPACITY);//HashMap中构建哈希桶数组是在第一个元素被添加的时候才构建,所以在构建之前检查它,//调用HashMap.tableSizeFor来计算实际分配的大小,//检查Map.Entry []类,因为它是最接近的公共类型实际创建的内容。

SharedSecrets.getJavaOISAccess()

.checkArray(s, Map.Entry[].class,HashMap.tableSizeFor(capacity));//创建HashMap。

map = (((HashSet>)this) instanceof LinkedHashSet ?

new LinkedHashMap(capacity, loadFactor) :new HashMap(capacity, loadFactor));//按写入流中的顺序再把元素依次读取出来放到map中。

for (int i=0; i

@SuppressWarnings("unchecked")

E e=(E) s.readObject();

map.put(e, PRESENT);

}

}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。