What's the best way to convert an Object array to a Vector?
JDE < 1.5
public Vector getListElements()
{
Vector myVector = this.elements;
return myVector;
}
this.elements is an Object[]
Thanks,
rAyt
I should clarify my question
My target platform is a blackberry.
Collections aren't supported. Array.asList() isn't, either :/
Full Class
package CustomElements;
import net.rim.device.api.ui.component .*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.util.*;
import java.util.*;
public class ContactsList extends SortedReadableList implements KeywordProvider
{
// Constructor
public ContactsList(Vector contacts)
{
super(new ContactsListComparatorByFirstName());
loadFrom(contacts.elements());
}
// Add Element to ContactsSortedReadableList
void addElement(Object element)
{
doAdd(element);
}
public Vector getListElements()
{
return new Vector(Collection
Vector test = this.getElements();
}
// getKeywords
public String[] getKeywords(Object element)
{
return StringUtilities.stringToWords(((Contact)element).get_contactFirstName());
// return StringUtilities.stringToWords(element.toString());
}
// Comparator sorting Contact objects by name
final static class ContactsListComparatorByFirstName implements Comparator
{
public int compare(Object o1, Object o2)
{
// Sticky Entries Implementation
if(((ContactsListObject)o2).getSticky())
{
return 1;
} else
if (((ContactsListObject)o1).getSticky())
{
return -1;
} else
{
if(((ContactsListObject)o1).get_contactFirstName().compareTo(((ContactsListObject)o2).get_contactFirstName()) <0)
{
return -1;
}
if(((ContactsListObject)o1).get_contactFirstName().compareTo(((ContactsListObject)o2).get_contactFirstName()) >0)
{
return 1;
}
else
{
return 0;
}
}
}
}
}
return new Vector(Arrays.asList(elements));
Now, it may look as if you are copying the data twice, but you aren't. You do get one small temporary object (a List from asList), but this provides a view of the array. Instead of copying it, read and write operations go through to the original array.
It is possible to extends Vector and poke its protected fields. This would give a relatively simple way of having the Vector become a view of the array, as Arrays.asList does. Alternatively, just copying data into the fields. For Java ME, this is about as good as it gets without writing the obvious loop. Untested code:
return new Vector(0) {{
this.elementData = (Object[])elements.clone();
this.elementCount = this.elementData.length;
}};
Of course, you are probably better off with a List than a Vector. 1.4 has completed its End of Service Life period. Even 1.5 has completed most of its EOSL period.
In J2ME, you're stuck iterating over the array and add the elements one by one.
Vector v = new Vector();
for (int i = 0; i < this.elements.length; i++) {
v.add(this.elements[i]);
}
A simplified comparator which does basically the same thing.
final static class ContactsListComparatorByFirstName implements Comparator {
public int compare(Object o1, Object o2) {
// Sticky Entries Implementation
ContactsListObject clo2 = (ContactsListObject) o2;
ContactsListObject clo1 = (ContactsListObject) o1;
if (clo2.getSticky()) return 1;
if (clo1.getSticky()) return -1;
return clo1.get_contactFirstName().compareTo(clo2.get_contactFirstName());
}
}
Using generics and ?: it would be just
static final class ContactsListComparatorByFirstName implements Comparator<ContactsListObject> {
public int compare(ContactsListObject clo1, ContactsListObject clo2) {
return clo2.getSticky() ? 1 : // Sticky Entries Implementation
clo1.getSticky() ? -1 :
clo1.get_contactFirstName().compareTo(clo2.get_contactFirstName());
}
}
But to answer your question... (oh I see Tom has what I would put already)
imho your only viable option is:
public Vector getListElements()
Vector vector = new Vector(this.elements.length);
for (int i = 0; i < this.elements.length; i++) {
vector.add(this.elements[i]);
}
return vector;
}
Copy the array elements to the Vector, or
Use Arrays.asList(...) to return a List, which isn't exactly a Vector, but you should be coding the List interface anyway.
A reasonably concise way to do it is something like:
Object[] xx = { 1, "cat", new Point(100,200) };
Vector vv = new Vector(Arrays.asList(xx));
System.out.println("vv=="+vv.toString());
But y'all knew that already, I guess.
Related
So I have been reviewing my data structures and came across an interesting thought regarding Java generics and the Object class. I have implemented and run a "generic bag" in two different ways (Notice below: IObjectBag.java, ObjectBag.java, IGenericBag.java, and GenericBag.java) and have used them both (Notice: Below main.java and Output). I have removed some of the unnecessary code as per stack overflow rules but if you want the full implementation, let me know.
Also, I have researched the topic in many websites, books and courses in addition to looking at the source code for the ArrayList class here and I understand that my GenericBag is a better option than my ObjectBag but not well enough to explain it in a practical way during an interview. And I am confused that my GenericBag uses more casting operations than my ObjectBag in its implementation (see Remove and PrintBag).
So, other than the syntactic sugar, why is my GenericBag better? Please use my classes as examples.
Are there any important differences in runtime/overhead/space/time I am not noticing?
How would you answer this question or expect it to be answered in an interview?
Bonus questions: If you want, please answer the bonus questions in the Main and GenericBag comments (I think I can answer them myself though, just want to hear your opinion).
IObjectBag interface:
public interface IObjectBag {
void add(Object item);
Object remove(Object item) throws NoSuchElementException;
boolean isEmpty();
int find(Object item);
Object get(int index);
int numItems();
}
ObjectBag class:
public class ObjectBag implements IObjectBag {
private Object [] items; // the java class attribute that will hold out "ints"
private int numItems;
public static void printBag(IObjectBag bag) {
for(int i = 0; i < bag.numItems(); i++) {
System.out.println(bag.get(i));
}
}
public ObjectBag(int size) {
this.items = new Object[size]; // fills array with null values
this.numItems = 0;
}
public void add(Object item){
// adds item to end of bag
}
public Object remove(Object item) {
int index = this.find(item);
if(index == -1) throw new NoSuchElementException("oops nothing found");
Object out = this.items[index];
this.items[index] = null;
this.numItems -= 1;
if(index + 1 != this.items.length && this.items[index + 1] != null) {
for(int i = index; i < this.items.length; i++) {
if(i + 1 != this.items.length) this.items[i] = this.items[i + 1];
}
this.items[this.items.length - 1] = null;
}
return out;
}
public int find(Object item) {
// return index given item or -1
}
public Object get(int index) {
// returns item given index
}
}
IGenericBag class:
public interface IGenericBag <T> {
void add(T item);
T remove(T item) throws NoSuchElementException;
boolean isEmpty();
int find(T item);
T get(int index);
}
GenericBag class:
public class GenericBag<T> implements IGenericBag<T> {
// private T[] items; can't use this b/c see comment in constructor
private Object[] items;
private int numItems;
public static void printBag(GenericBag bag) {
for(int i = 0; i < bag.numItems(); i++) {
System.out.println(bag.get(i));
}
}
public GenericBag(int size) {
// this.items = new T[size]; Bonus: throws generic array creation error (why?)
this.items = new Object[size];
this.numItems = 0;
}
public void add(T item){
this.items[this.numItems] = item;
this.numItems += 1;
}
public T remove(T item) {
int index = this.find(item);
if(index == -1) throw new NoSuchElementException("oops nothing found");
T out = (T) this.items[index];
this.items[index] = null;
this.numItems -= 1;
if(index + 1 != this.items.length && this.items[index + 1] != null) {
for(int i = index; i < this.items.length; i++) {
if(i + 1 != this.items.length) this.items[i] = this.items[i + 1];
}
this.items[this.items.length - 1] = null;
}
return out;
}
public int find(Object item) {
// given object return index or throw exception
}
public T get(int index) {
return (T) this.items[index];
}
}
Main class:
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Hello StackOverFlow!");
Object int1 = new Integer(1);
Object int2 = new Integer(2);
Object int3 = new Integer(3);
/* using my object bag ************************************************/
System.out.println("using my object bag");
IObjectBag myObjectBag = new ObjectBag(3);
myObjectBag.add(int1);
myObjectBag.add(int2);
myObjectBag.add(int3);
myObjectBag.remove(int2);
ObjectBag.printBag(myObjectBag);
/* using my generic bag ***********************************************/
System.out.println("using generic bag");
// Bonus Question: using object like above causes error at add method (why?)
Integer int4 = new Integer(4);
Integer int5 = new Integer(5);
Integer int6 = new Integer(6);
GenericBag<Integer> myGenericBag = new GenericBag<Integer>(3);
//Bonus Question: using Interface decllaration like above causes error in print bag (why?)
myGenericBag.add(int4);
myGenericBag.add(int5);
myGenericBag.add(int6);
myGenericBag.remove(int4);
GenericBag.printBag(myGenericBag);
}
}
Output:
Hello StackOverFlow!
using my object bag
1
3
using generic bag
5
6
Problems with your ObjectBag that are 'automaticaly' solved by the type safety offered by your GenericBag implementation:
Accessing an entry returns Object, at this stage you do not know of what type Object is.
You can insert any types of Objects (mixed) e.g a String and an Integer into the same list, this is an anti pattern and causes non readable code (try it with your Generics bag!)
Because your compiler knows the type of your GenericBag after you have declared it, at any stage of your code if you hover over your genericBag instance you will know its type, this makes your code more readable and also extendable for other people
Generics also offer way more, imagine you want your GenericBag to only accept numbers, then you could write it as follows:
public class GenericBag<T extends Number>
My suggestion for you is to read some articles on Java basics and especially Generics, having a praxis based way of learning is a good thing, but there are plenty articles that can give you some very nice theoretical insight on the matter.
https://www.baeldung.com/java-generics
Reason of using, let's say, GenericBag<String> over ObjectBag is essentially the same as for using String (or any other type) over an Object:
Type safety.
You declare that some method returns a collection of Strings and nothing else, thus preventing yourself from putting there other objects, or trying to treat what you get from a bag as some other type. This might sound stupid when you have 100 lines of code, but this may save you lot of debugging time when you work with decent codebase.
Although, type safety is not a silver bullet, it is just an instrument, that some people find useful and some don't. I'm pretty sure it is a popular holywar topic for any programming forum.
If you feel comfortable working without this paradigm (Javascript background, right?), you might consider trying some dynamically typed language like Python instead of Java.
I have list which contains a property class object, In the list i have 3 status
not_paid
paid
part_paid
I want to sort my list below mentioned order.
First - not_paid
second- part_paid
third -paid
How can I sort my list using Comparator class.?
public static Comparator<OrderHistoryItemData> COMPARE_BY_PAYMENT = new Comparator<OrderHistoryItemData>() {
public int compare(OrderHistoryItemData one, OrderHistoryItemData other) {
String p1 = one.getAttributes().getFieldPaymentStatus();
String p2 = other.getAttributes().getFieldPaymentStatus();
if (p1.equals(p2)) {
return 0;
}
if (p1.equals("not_paid") && (p2.equals("part_paid") || p2.equals("not_paid"))) {
return -1;
}
if (p1.equals("not_paid") && p2.equals("not_paid")) {
return -1;
}
return 1;
}
};
This is my Code. i am getting below order using this code.
paid-->not_paid-->part_paid
This is my Update Code. I got my result.
public static Comparator<OrderHistoryItemData> COMPARE_BY_PAYMENT = new Comparator<OrderHistoryItemData>() {
public int compare(OrderHistoryItemData one, OrderHistoryItemData other) {
String p1 = one.getAttributes().getFieldPaymentStatus();
String p2 = other.getAttributes().getFieldPaymentStatus();
if (p1.equals(p2)) {
return 0;
}
if (p1.equals("not_paid") && (p2.equals("part_paid") || p2.equals("paid"))) {
return -1;
}
if (p1.equals("part_paid") && p2.equals("paid")) {
return -1;
}
return 1;
}
};
To avoid complex comparator, I encourage you to export your statuses to an enum. (Plus this will work if you will add more statuses in the future, without the need to change logic in your comparator):
enum PaymentStatus { // Write them in order you want to be sorted
NOT_PAID,
PART_PAID,
PAID
}
Then sorting will be as simple as :
list.sort(Comparator.comparing(item ->item.getAttributes().getFieldPaymentStatus()));
What you can do is first mapping the strings to integers in the desired order, and then simply subtracting them from eachother.
private static Comparator<Payments> comparator = new Comparator<Payments>() {
// Use this mapping function to map the statuses to ints.
// The lowest number comes first
private int map(String str) {
switch (str) {
case "not_paid":
return 0;
case "part_paid":
return 1;
case "paid":
return 2;
default:
return 3;
}
}
// Alternatively, you can use the Map interface to define the sorting
// order.
#Override
public int compare(Payments o1, Payments o2) {
return map(o1.status) - map(o2.status);
}
};
I suggest – Schidu Luca already mentioned it in his answer – that you use enums to define a fixed set of known values, like payment statuses. This provides compile-time safety.
Note: I wouldn't, however, suggest to bind the enum declaration order to the sorting order.
I'm trying to sort my List but this one doesn't work. Method collections.sort() does nothing.
public boolean schedule(){
List<Task> keys = new ArrayList<Task>(g.tasks.keySet());
for(int i = 0; i<keys.size();i++){
System.out.println(keys.get(i).getSize());
}
Collections.sort(keys);
for(int i = 0; i<keys.size();i++){
System.out.println(keys.get(i).getSize());
}
return true;
}
and this is my compareTo() method in Task class:
public int compareTo(Task t1) {
Integer csize = new Integer(t1.size);
int cmp = csize.compareTo(t1.size);
return cmp;
}
What is wrong in this method?
collections.sort doesn't work for custom objects
Sure it does, but it won't in your case because your compareTo method is broken. You're comparing t1's size to itself, not to the size of this
You've got:
public int compareTo(Task t1) {
Integer csize = new Integer(t1.size); // get t1's size
int cmp = csize.compareTo(t1.size); // ???? compare with t1's size ???
return cmp;
}
You need to change it to something like:
public int compareTo(Task t1) {
return Integer.compare(this.size, t1.size);
}
So now you're comparing the size of the parameter with the size of the current object.
You have an error in compareTo that has been pointed out in the accepted answer. I am supplying an additional answer only to provide a different idiom you might consider for defining natural order of a class:
class Task implements Comparable<Task> {
private static final Comparator<Task> ORDER = Comparator
.comparingInt(Task::getSize)
.reversed()
.thenComparing(Task::getPriority);
public int compareTo(Task other) {
return ORDER.compare(this, other);
}
}
The potential advantage of this delegation idiom is that on casual reading of a traditional compareTo implementation it's easy to miss things such as the order of arguments reversing the comparison. The declaration makes it very explicit. This also means that you have all the features of Comparator available (e.g. deciding if nulls are first or last).
Already answer was posted by #HoverCraft.
In addition to that
//For ASC
public int compareTo(Task t1) {
return (this.size - t1.size);
}
//For DESC
public int compareTo(Task t1) {
return (t1.size - this.size);
}
First of all sorry if my English bad, its not my first language..
I'm working on and android app project, that needed to sort ArrayList of an object..so I made this method to deal with that...
Lets say that I have an object of Restaurant that will contain this data:
private String name;
private float distance ;
And I sort it using the value of the variable distance from lowest to highest:
public void sort(RArrayList<RestaurantData> datas) {
RestaurantData tmp = new RestaurantData();
int swapped;
boolean b = true;
while (b) {
swapped = 0;
for (int i = 0; i < datas.size()-1; i++) {
if (datas.get(i).getDistance() > datas.get(i+1).getDistance()) {
tmp = datas.get(i);
datas.set(i, datas.get(i+1));
datas.set(i+1, tmp);
swapped = 1;
System.err.println("Swapped happening");
}
}
if (swapped == 0) {
System.err.println("Swapped end");
break;
}
}
But when i try the program..the result of an ArrayList is still random, is there any problem with my logic to sort the ArrayList of an object..
Please Help...Thankyou..
Why not use the Collections.sort method?
Here's how you could do it in your project:
public void sort(RArrayList<RestaurantData> datas) {
Collections.sort(datas, new Comparator<RestaurantData>() {
#Override
public int compare(RestaurantData lhs, RestaurantData rhs) {
return lhs.getDistance() - rhs.getDistance();
}
});
}
The above solution is a bit "destructive" in the sense that it changes the order of the elements in the original array - datas. If that's fine for you go ahead and use it. Personally I prefer things less destructive and if you have the memory to spare (meaning your array is small) you could consider this solution which copies the array before sorting. It also assumes your RArrayList is an implementation of ArrayList or backed up by it:
public List<RestaurantData> sort(RArrayList<RestaurantData> datas) {
// Create a list with enough capacity for all elements
List<RestaurantData> newList = new RArrayList<RestaurantData>(datas.size());
Collections.copy(newList, datas);
Collections.sort(newList, new Comparator<RestaurantData>() {
#Override
public int compare(RestaurantData lhs, RestaurantData rhs) {
return lhs.getDistance() - rhs.getDistance();
}
});
return newList;
}
Another thing to consider is also to create a single instance of the Comparator used in the method, since this implementation will create one instance per call. Not sure if it's worth it though, because it will also be destroyed quite soon since the scope is local.
Here's the documentation for the Collections api
One last thing, the comparator simply needs to return a value less than 0 if the elements are in the right order, bigger than 0 if they're in the wrong order or 0 if they're the same. Therefore it seems to be that it's enough to simply subtract the distances of each restaurant. However, if this isn't the case, please implement the comparator suiting your needs.
I have an array of phonebook elements and I'm trying to sort them according to lexicographical order using comparable sort. But it all messes up. Please help. Thanks in advance
It will also help to describe about sort function in java a little bit!
Here is the code:
package myphonebook;
import javax.swing.*;
import java.util.Arrays;
import java.util.Comparator;
public class MyPhoneBook implements Comparator<MyPhoneBook>{
private String name,email,number;
MyPhoneBook()
{
}
public void input()
{
name = (JOptionPane.showInputDialog("Enter Name:\n")).toString();
number = JOptionPane.showInputDialog("Enter Number:\n").toString();
email = JOptionPane.showInputDialog("Enter email:\n").toString();
}
public void print()
{
JOptionPane.showMessageDialog(null, "Name: " + name+ "\n" + "Phone: " +number +"\n" + "Email: " + email);
}
public static void main(String[] args) {
MyPhoneBook a[] = new MyPhoneBook[300];
MyPhoneBook b = new MyPhoneBook();
//final Integer[] sorted = ArrayUtils.toObject(MyPhoneBook);
int i,n;
n = Integer.parseInt(JOptionPane.showInputDi… total number:\n"));
for(i=0;i<n;i++)
{
a[i] = new MyPhoneBook();
a[i].input();
}
Arrays.sort(a);
for(i=0;i<n;i++)
{
a[i].print();
}
}
#Override
public int compare(MyPhoneBook o1, MyPhoneBook o2) {
return o1.number.compareTo(o2.number);
}
public int compareTo(MyPhoneBook o) {
if(this.name.equals(o.name)) return this.number.compareTo(o.number);
if(this.number.equals(o.number)) return this.email.compareTo(o.email);
if(this.email.equals(o.email)) return this.name.compareTo(o.name);
return 0;
}
}
There are several problems here: the first is that your comparison is not actually lexicographic. For example, when the names are equal, you completely ignore the email address in your comparison logic. The second problem is that you fail to specify the comparator as a parameter to Arrays.sort().
First problem: fix comparison logic
If you can use third-party libraries in your code, then a really neat and simple way to handle this is using the ComparisonChain class from the Guava libraries (Google's core Java libraries that are opensource):
public int compareTo(MyPhoneBook o) {
return ComparisonChain
.start()
.compare(name, o.name)
.compare(email, o.email)
.compare(number, o.number)
.result();
}
Assuming you can't do that, however, here's the right way to do it:
public int compareTo(MyPhoneBook o) {
int nameComparison = name.compareTo(o.name);
if (nameComparison != 0) {
return nameComparison;
}
int emailComparison = email.compareTo(o.email);
if (emailComparison != 0) {
return emailComparison;
}
return number.compareTo(o.number);
}
Second problem: invoke Arrays.sort() with the comparator
Instead of your current call to Arrays.sort(), use:
Arrays.sort(a, new PhoneBookComparator());
And define PhoneBookComparator as a separate Comparator class.
Just use String#compareTo, it compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings.
public class MyPhoneBook implements Comparable<MyPhoneBook>{
#Override
public int compareTo(MyPhoneBook o) {
int returnValue =0;
if(o!=null){
returnvalue = this.name.compareTo(o.name);
if(returnValue==0){
returnValue = this.number.compareTo(o.number);
if(returnValue==0){
returnValue = this.email.compareTo(o.email);
}
}
}
return returnValue;
}
}
When running the code as you posted it it comes to a
Exception in thread "main" java.lang.ClassCastException: ...
MyPhoneBook cannot be cast to java.lang.Comparable
This is because you call
Arrays.sort(a);
Arrays.html#sort expects the Objects contained in the array to be implementing the interface Comparable. Your class is implmenting Comparator though.
You should change your class declaration to one of the following
public class MyPhoneBook implements Comparable<MyPhoneBook> {
and just remove
#Override
public int compare(MyPhoneBook o1, MyPhoneBook o2) {
return o1.number.compareTo(o2.number);
}
Or
public class MyPhoneBook {
and the call of sort to
Arrays.sort(a, new Comparator<MyPhoneBook>() {
#Override
public int compare(MyPhoneBook o1, MyPhoneBook o2) {
// TODO implment here your comapre logic
return o1.number.compareTo(o2.number);
}
});
After you have fixed that you'll get NullPointerException, againt because of the line
Arrays.sort(a);
This is because you pass an array of the length 300 and you do not necessarily have to put all 300 element in it since you ask for total number
you should be using
Arrays.sort(a, 0, n);
This sorts only the range witch have data. See the javadoc.