创建Java对象的唯一列表
我有一个ArrayList,其中填充了具有属性名称和时间的对象。我想删除基于名称的副本,只保留最新时间的记录。因此,我在对象中为name重写了创建Java对象的唯一列表,java,list,collections,unique,Java,List,Collections,Unique,我有一个ArrayList,其中填充了具有属性名称和时间的对象。我想删除基于名称的副本,只保留最新时间的记录。因此,我在对象中为name重写了equals和hashcode,并使用了如下代码 private List<ChangedRecentlyTO> groupRecords(List<ChangedRecentlyTO> toList) { changedRecentlyList.clear(); //static list for(ChangedR
equals
和hashcode
,并使用了如下代码
private List<ChangedRecentlyTO> groupRecords(List<ChangedRecentlyTO> toList) {
changedRecentlyList.clear(); //static list
for(ChangedRecentlyTO to : toList) {
if(!changedRecentlyList.contains(to)) {
changedRecentlyList.add(to);
} else {
if(changedRecentlyList.get(changedRecentlyList.lastIndexOf(to)).getTimeChanged().before(to.getTimeChanged())) {
changedRecentlyList.remove(to);
changedRecentlyList.add(to);
}
}
}
return changedRecentlyList;
}
私有列表组记录(列表列表){
changedRecentlyList.clear();//静态列表
for(最近更改为:toList){
如果(!changedRecentlyList.contains(to)){
changedRecentlyList.add(到);
}否则{
if(changedRecentlyList.get(changedRecentlyList.lastIndexOf(to)).getTimeChanged().before(to.getTimeChanged())){
changedRecentlyList.remove(to);
changedRecentlyList.add(到);
}
}
}
返回changedRecentlyList;
}
但我想知道,有没有更好的解决方案?我在考虑使用Set,但我不知道该如何设置时间标准 为什么不使用a和更高版本:
new ArrayList(set);
扩展
HashMap
并重写put
方法,使其仅在新对象比现有对象更新时放置
或者,您可以创建自己的专用容器,该容器将由HashMap
支持,就像Stack
的一些实现由LinkedList
支持一样
这是一个模拟代码:
import java.util.HashMap;
import java.util.Map;
public class TimeMap<K, V> {
private Map<K, V> timeMap;
public TimeMap() {
this.timeMap = new HashMap<K, V>();
}
public void put(K key, V value) {
if (isNewer(key, value)) {
this.timeMap.put(key, value);
}
}
}
import java.util.HashMap;
导入java.util.Map;
公共类时间图{
私有地图时间地图;
公共时间地图(){
this.timeMap=newhashmap();
}
公开作废认沽权(K键,V值){
if(较新的(键、值)){
this.timeMap.put(键,值);
}
}
}
我的建议是,通过实现接口使类具有可比性。然后在comparetTo()
中,根据名称和时间比较它们,如果对象时间是最近返回的,则返回1,否则返回0(如果相等)或-1。一旦获得此功能,您可以扩展类并覆盖put
方法,如
o1.compareTo(o2) > 0 then simply overwrite the object with latest one.
向@Lopina代码添加逻辑,如
public class MyHashMap extends HashMap<String, MyClass>{
private Map<String, MyClass> timeMap;
public MyHashMap() {
this.timeMap = new HashMap<String, MyClass>();
}
public MyClass put(String key, MyClass value) {
MyClass obj;
if (isNewer(key, value)) {
System.out.println("count");
obj=this.timeMap.put(key, value);
}else{
obj=value;
}
return obj;
}
private boolean isNewer(String key, MyClass value) {
if(this.timeMap.get(key)==null ||( key.equals(value.getName()))&& (this.timeMap.get(key).compareTo(value))<0)
return true;
else
return false;
}
@Override
public int size() {
return this.timeMap.size();
}
@Override
public MyClass get(Object key) {
return this.timeMap.get(key);
}
}
您可以让您的类实现Comparable
接口,并对您感兴趣的时间戳进行比较检查。如果您随后对其进行排序(例如,将所有元素放在树集合中
),然后逐个取出,前提是这些元素不存在。大概是这样的:
public void removeDuplicates(List<MyObject> list){
SortedSet<MyObject> sortedSet = new TreeSet<MyObject>();
sortedSet.addAll(list);
//Now clear the list, and start adding them again
list.clear();
for(MyObject obj : sortedSet){
if(!list.contains(obj) {
list.add(obj);
}
}
return list;
}
public void removedeplicates(列表){
SortedSet SortedSet=新树集();
sortedSet.addAll(列表);
//现在清除列表,然后再次开始添加它们
list.clear();
用于(MyObject对象:sortedSet){
如果(!list.contains)(obj){
列表。添加(obj);
}
}
退货清单;
}
但是,只有当两个具有不同时间戳的对象不相等时,这才有效!(在equals()
这个词的意义上,你必须告诉我两种方法,一种方法需要了解集合的工作方式,另一种方法对于那些对Java集合了解较少的人来说更容易理解:
如果你想让它变得简单,你可以简单地阅读集合的Javadoc的细节,它清楚地表明,如果一个元素已经在里面,它将不会被再次添加
- 您只使用名称来实现equals和hashcode
- 您可以按时间对项目进行排序,然后将其添加到集合中
这样,第一次添加要设置的项时,您将添加具有最新时间的元素。添加其他元素时,它们将被忽略,因为它们已被包含
如果其他人不完全了解java.util.Set的约定的行为,您可能希望扩展Set以使您的意图更清楚。但是,由于不应该访问集合来“在删除后获取元素”,因此您需要使用HashMap来备份集合:
interface TimeChangeable {
long getTimeChanged();
}
public class TimeChangeableSet<E extends TimeCheangeable> implements Set<E> {
private final HashMap<Integer,E> hashMap = new HashMap<Integer,E>();
@Override
public boolean add(E e) {
E existingValue = hashMap.remove(e.hashCode());
if(existingValue==null){
hashMap.put(e.hashCode(),e);
return true;
}
else{
E toAdd = e.getTimeChanged() > existingValue.getTimeChanged() ? e : existingValue;
boolean newAdded = e.getTimeChanged() > existingValue.getTimeChanged() ? true : false;
hashMap.put(e.hashCode(),e);
return newAdded;
}
}
@Override
public int size() {
return hashMap.size();
}
@Override
public boolean isEmpty() {
return hashMap.isEmpty();
}
@Override
public boolean contains(Object o) {
return hashMap.containsKey(o.hashCode());
}
@Override
public Iterator<E> iterator() {
return hashMap.values().iterator();
}
@Override
public Object[] toArray() {
return hashMap.values().toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return hashMap.values().toArray(a);
}
@Override
public boolean remove(Object o) {
return removeAndGet(o)!=null ? true : false;
}
public E removeAndGet (Object o) {
return hashMap.remove(o.hashCode());
}
@Override
public boolean containsAll(Collection<?> c) {
boolean containsAll = true;
for(Object object:c){
E objectInMap = removeAndGet(object);
if(objectInMap==null || !objectInMap.equals(object))
containsAll=false;
}
return containsAll;
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean addAll=true;
for(E e:c){
if(!add(e)) addAll=false;
}
return addAll;
}
@Override
public boolean retainAll(Collection<?> c) {
boolean setChanged=false;
for(E e: hashMap.values()){
if(!c.contains(e)){
hashMap.remove(e.hashCode());
setChanged=true;
}
}
return setChanged;
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException("Please do not use type-unsafe methods in 2012");
}
@Override
public void clear() {
hashMap.clear();
}
}
接口时间可变{
long getTimeChanged();
}
公共类TimeChangeableSet实现了{
private final HashMap HashMap=new HashMap();
@凌驾
公共布尔加法(E){
E existingValue=hashMap.remove(E.hashCode());
if(existingValue==null){
put(e.hashCode(),e);
返回true;
}
否则{
E toAdd=E.getTimeChanged()>existingValue.getTimeChanged()?E:existingValue;
boolean newAdded=e.getTimeChanged()>existingValue.getTimeChanged()?true:false;
put(e.hashCode(),e);
返回新添加的;
}
}
@凌驾
公共整数大小(){
返回hashMap.size();
}
@凌驾
公共布尔值为空(){
返回hashMap.isEmpty();
}
@凌驾
公共布尔包含(对象o){
返回hashMap.containsKey(o.hashCode());
}
@凌驾
公共迭代器迭代器(){
返回hashMap.values().iterator();
}
@凌驾
公共对象[]toArray(){
返回hashMap.values().toArray();
}
@凌驾
公共T[]toArray(T[]a){
将hashMap.values()返回数组(a);
}
@凌驾
公共布尔删除(对象o){
return removeAndGet(o)!=null?true:false;
}
公共E removeAndGet(对象o){
返回hashMap.remove(o.hashCode());
}
@凌驾
公共布尔容器(集合c){
布尔containsAll=true;
用于(对象:c){
E objectInMap=removeAndGet(对象);
如果(objectInMap==null | |!objectInMap.equals(object))
containsAll=false;
}
返回容器sall;
}
@凌驾
公共布尔addAll(集合c){
布尔setChanged=false;
对于(E:hashMap.values()){
如果(!c.包含(e)){
remove(例如hashCode());
setChanged=true;
}
}
返回设置已更改;
}
@凌驾
公共布尔removeAll(集合c){
通过
interface TimeChangeable {
long getTimeChanged();
}
public class TimeChangeableSet<E extends TimeCheangeable> implements Set<E> {
private final HashMap<Integer,E> hashMap = new HashMap<Integer,E>();
@Override
public boolean add(E e) {
E existingValue = hashMap.remove(e.hashCode());
if(existingValue==null){
hashMap.put(e.hashCode(),e);
return true;
}
else{
E toAdd = e.getTimeChanged() > existingValue.getTimeChanged() ? e : existingValue;
boolean newAdded = e.getTimeChanged() > existingValue.getTimeChanged() ? true : false;
hashMap.put(e.hashCode(),e);
return newAdded;
}
}
@Override
public int size() {
return hashMap.size();
}
@Override
public boolean isEmpty() {
return hashMap.isEmpty();
}
@Override
public boolean contains(Object o) {
return hashMap.containsKey(o.hashCode());
}
@Override
public Iterator<E> iterator() {
return hashMap.values().iterator();
}
@Override
public Object[] toArray() {
return hashMap.values().toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return hashMap.values().toArray(a);
}
@Override
public boolean remove(Object o) {
return removeAndGet(o)!=null ? true : false;
}
public E removeAndGet (Object o) {
return hashMap.remove(o.hashCode());
}
@Override
public boolean containsAll(Collection<?> c) {
boolean containsAll = true;
for(Object object:c){
E objectInMap = removeAndGet(object);
if(objectInMap==null || !objectInMap.equals(object))
containsAll=false;
}
return containsAll;
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean addAll=true;
for(E e:c){
if(!add(e)) addAll=false;
}
return addAll;
}
@Override
public boolean retainAll(Collection<?> c) {
boolean setChanged=false;
for(E e: hashMap.values()){
if(!c.contains(e)){
hashMap.remove(e.hashCode());
setChanged=true;
}
}
return setChanged;
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException("Please do not use type-unsafe methods in 2012");
}
@Override
public void clear() {
hashMap.clear();
}
}
private List<ChangedRecentlyTO> groupRecords(List<ChangedRecentlyTO> toList) {
Map<String, ChangedRecentlyTO> uniqueMap = new HashMap<String, ChangedRecentlyTO>();
for(ChangedRecentlyTO to : toList) {
if (uniqueMap.containsKey(to.getName())) {
if (uniqueMap.get(to.getName()).getTimeChanged().before(to.getTimeChanged())) {
uniqueMap.put(to.getName(), to);
}
} else {
uniqueMap.put(to.getName(), to);
}
}
return (List<ChangedRecentlyTO>) uniqueMap.values();
}
public class UniqueList<T> extends ArrayList<T> implements Set<T>
{
HashMap<T,Integer> hash; // T -> int
public UniqueList()
{
hash = new HashMap<>();
}
/*
* O(n)
* */
@Override
public void add(int location, T object)
{
super.add(location, object);
for( int i = location ; i < size() ; i++ )
{
hash.put(get(i),i);
}
}
/*
* O(1) amortized.
* */
@Override
public boolean add(T object) {
if( hash.containsKey(object) ) return false;
hash.put(object, size());
super.add(object);
return true;
}
/*
* O(MAX(collection.size(),n)) because of the hash-value-shift afterwards.
* */
@Override
public boolean addAll(int location, Collection<? extends T> collection) {
boolean bChanged = false;
for( T t : collection)
{
if( ! hash.containsKey( t ) )
{
hash.put(t, size());
super.add(t);
bChanged = true;
}
}
for( int i = location + collection.size() ; i < size() ; i ++ )
{
hash.put( get(i) , i );
}
return bChanged;
}
/*
* O(collection.size())
* */
@Override
public boolean addAll(Collection<? extends T> collection) {
boolean bChanged = false;
for( T t : collection)
{
if( ! hash.containsKey( t ) )
{
hash.put( t , size() );
super.add(t);
bChanged = true;
}
}
return bChanged;
}
/*
* O(n)
* */
@Override
public void clear() {
hash.clear();
super.clear();
}
/*
* O(1)
* */
@Override
public boolean contains(Object object) {
return hash.containsKey(object);
}
/*
* O(collection.size())
* */
@Override
public boolean containsAll(Collection<?> collection) {
boolean bContainsAll = true;
for( Object c : collection ) bContainsAll &= hash.containsKey(c);
return bContainsAll;
}
/*
* O(1)
* */
@Override
public int indexOf(Object object) {
//noinspection SuspiciousMethodCalls
Integer index = hash.get(object);
return index!=null?index:-1;
}
/*
* O(1)
* */
@Override
public int lastIndexOf(Object object)
{
return hash.get(object);
}
/*
* O(n) because of the ArrayList.remove and hash adjustment
* */
@Override
public T remove(int location) {
T t = super.remove(location);
hash.remove( t );
for( int i = size() - 1 ; i >= location ; i -- )
{
hash.put( get(i) , i );
}
return t;
}
/*
* O(n) because of the ArrayList.remove and hash adjustment
* */
@Override
public boolean remove(Object object) {
Integer i = hash.get( object );
if( i == null ) return false;
remove( i.intValue() );
return true;
}
/*
* O( MAX( collection.size() , ArrayList.removeAll(collection) ) )
* */
@Override
public boolean removeAll(@NonNull Collection<?> collection) {
for( Object c : collection )
{
hash.remove( c );
}
return super.removeAll( collection );
}
}