简体   繁体   中英

how to make an element in a Set to be always the 1st element

I have a tree Set which has so many elements in it. I have them in alphabetical order. Can I actually make it to have an element always the 1st element without disturbing the sorted order?

Eg: I want "partnumber" element to be always the 1st element in the set. Can it be done? Thanks in advance !!

Just create a new Collection where you add the desired element first, then add the rest of the elements the way you want/need. For example, you say you have a TreeSet<String> which has all your data sorted, then you can use, for example, a List and store all the data how you want/need. Here's a kickoff example:

TreeSet<String> myTreeSet = ...
//...
//fill the data in treeSet...
//...
List<String> realData = new ArrayList<String>();
realData.add("partnumber");
realData.addAll(myTreeSet);

In case you go with the Comparator<String> implementation (or the class you use), just make sure that "partnumber" always is the lesser value, otherwise do the real comparison:

class MyPartNumberStringComparator implements Comparator<String>() {
    static final String PART_NUMBER = "partNumber";
    @Override
    public int compare(String s1, String s2) {
        if (PART_NUMBER.equals(s1) && s1.equals(s2)) {
            return 0;
        }
        return (PART_NUMBER.equals(s1)) ? -1 :
            (PART_NUMBER.equals(s2)) ? 1 :
            s1.compareTo(s2);
    }
}

This should allow you to add a head element to any Set .

public class HeadSet<T> extends AbstractSet<T> implements Set<T> {
    // The extra item to add at the head.
    final T head;
    // The rest of the items.
    final Set<T> body;

    public HeadSet(T head, Set<T> body) {
        this.head = head;
        this.body = body;
    }

    @Override
    public Iterator<T> iterator() {
        // Iterator starts with the head element and then delegates to the body iterator.
        return new Iterator<T>() {
            private T next = head;
            private Iterator<T> i = body.iterator();

            @Override
            public boolean hasNext() {
                if (next == null && i.hasNext()) {
                    next = i.next();
                }
                return next != null;
            }

            @Override
            public T next() {
                if (hasNext()) {
                    T n = next;
                    next = null;
                    return n;
                } else {
                    throw new NoSuchElementException();
                }
            }

        };
    }

    @Override
    public int size() {
        // Size is one more than the size of the body.
        return 1 + body.size();
    }
}

public void test() {
    Set<String> bodySet = new TreeSet<>(Arrays.asList("One", "Two"));
    Set<String> mySet = new HeadSet("Choose part number ...", bodySet);
    System.out.println(mySet);
}

You can either use a LinkedHashSet and insert each item in exactly the same order that you want them back, or you can provide a custom Comparator to your TreeSet to sort "normally" (whatever that means for your implementation) but to consider part number as occurring before anything else.

If the objects you are putting into your TreeSet implement Comparable , then you can override the compareTo method to add the special handling for part number.

To implement a Comparator , it would look something like this:

import java.util.Comparator;


public class MyComparator implements Comparator<MyDomainClass> {

    @Override
    public int compare(MyDomainClass o1, MyDomainClass o2) {
        // compare the objects here and return a negative integer, zero,
        // or a positive integer as the first argument is less than, equal
        // to, or greater than the second
        return 0;  // stub
    }

}

And then when you create your TreeSet , you could pass the custom Comparator in as an argument to the contructor:

TreeSet<MyDomainClass> ts = new TreeSet<MyDomainClass> (new MyComparator());

The way I have solved this before was to have two collections one a List and the other a Sorted Set. When I have to display data I iterate over both these collections in order.

A common use case would be populating the list of countries in a dropdown. You want 'None' and 'United States' as the top two items but the rest of the countries you want sorted.

You can make your own comparator, it will look something like this:

public class comparatorSet implements Comparator<Element type>{

 public int compare(Type e1, Type e2){
  Integer res=0;
  if(e1.equals(firstelement)){
  res=-1;
  }
  else if(e2.equals(firstelement)){
  res=1;
  }
  else{
  res=e1.compareTo(e2);
  }
 return res;
 }
}

i don't know if you absolutely need to use a Set, if you use a Max Heap, it will always keep the maximum value at the top, no matter if you insert or remove anything. all you need is an arraylist. Use the comparator like the others have said and you'll be fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM