compacting an array in java by removing certain objects - java

For my computer science class we are supposed to take an array of objects {A,C,D,C,C,F,C,G} and sets all elements of a certain object to null. Object is C: {A,null,D,null,null,F,null,G}
Then we are supposed to move all the remaining object to the front of the array {A,D,F,G,null,null,null,null}...
So far I tried this but I cant find the problem with my method:
public static void compact (Object[] vec, Object item) {
int a=0;
for(int i=0; i < vec.length; i++)
{
if(vec[i]==item)
{
vec[i] = null;
}
else
{
vec[i]=vec[a];
a++;
}
}
for(int b=a; b < vec.length-(a-1); b++)
{
vec[b]=null;
}
}
Help please?

if(vec[i]==item)
Never use == for comparing objects, use equals() (and, when you define a new class, take care in implementing equals() and hashCode() in a practical way)
Of course there may be other problems, but since you are not even telling what it is failing I won't care much.

I think you want equals() rather than == unless testing for null. You are using an object.

Related

Need help using java.lang.reflect.Array to sort arrays

An interview question was to write this method to remove duplicate element in an array.
public static Array removeDuplicates(Array a) {
...
return type is java.lang.reflect.Array and parameter is also java.lang.reflect.Array type.
How would this method be called for any array?
Also not sure about my implementation:
public static Array removeDuplicates(Array a)
{
int end=Array.getLength(a)-1;
for(int i=0;i<=end-1;i++)
{
for(int j=i+1;j<=end;j++)
{
if(Array.get(a, i)==Array.get(a, j))
{
Array.set(a, j, Array.get(a, end));
end--;
j--;
}
}
}
Array b=(Array) Array.newInstance(a.getClass(), end+1);
for(int i=0;i<=end;i++)
Array.set(a, i, Array.get(a, i));
return b;
}
You may want to consider using a different data structure such as a hashmap to detect the duplicate (O(1)) instead of looping with nested for loops (O(n^2)). It should give you much better time complexity.
There are various problem with this code. Starting here:
if(Array.get(a, i)==Array.get(a, j))
Keep in mind that those get() calls return Object. So, when you pass in an array of strings, comparing with == simply will most likely result in wrong results (because many objects that are in fact equal still have different references --- so your check returns false all the time!)
So, the first thing to change: use equals() instead of == !
The other problem is:
end--;
Seriously: you never ever change the variable that controls your for loop.
Instead: have another counter, like
int numberOfOutgoingItems = end;
and then decrease that counter!
For your final question - check the javadoc; for example for get(). That reads get(Object array, int index)
So you should be able to do something like:
int a[] = ...;
Object oneValue = Array.get(a, 0);
for example.
Disclaimer. I have to admit: I don't know if the Array implementation is smart enough to automatically turn the elements of an int[] into an Integer object.
It could well be that you have to write code first to detect the exact type of array (if it is an array of int for example); to instead call getInt() instead of getObject().
Beyond that, some further reading how to use reflection/Array can be found here

Using variables instead of a long statement?

I am facing a confusion while working with objects. I searched google but couldn't find actual words to search for. The question is:
I am working with objects which consist some other object. For example:
public void mapObjects(A a, B b) {
a.setWeight(BigDecimal.valueOf(b.getWeight));
//Now my doubt lies here
if (a.getCharges.getDiscounts.getDiscountList != null) {
for(int i = 0; i < a.getCharges.getDiscounts.getDiscountList.size(); i++){
b.getList().get(0).setDiscountValue(a.getCharges.getDiscounts.getDiscountList.get(i).getValue());
b.getList().get(0).setDiscountName(a.getCharges.getDiscounts.getDiscountList.get(i).getValue);
}
}
}
The above code is just an example. The project in which I am working uses similar type of coding style. The usage of a.getCharges.getDiscounts.getDiscountList() kind of code always bugs me. Because I am again and again calling the same statement.
When I asked a senior why dont we save this statement into a simple List<> variable. He told me that it will use extra references which will increase overhead. Can using a variable be that much overhead than calling getters again and again?
As Java exchanges references not actual object, if you take a local variable it will just add a reference variable entry in stack frame.
This memory would be very less, almost negligible
This memory will be released once the method is completed because this will be local to the method
Despite that, you can gain significant performance gains if you use local variables. You are extracting same information within loop multiple times.
a.getCharges.getDiscounts.getDiscountList.size() is called multiple times. It should be a local variable.
b.getList().get(0) is being called multiple times. It should be a local variable.
a.getCharges.getDiscounts.getDiscountList is called multiple times. It should be a local variable.
Changing these to local variables would results in good performance gains, because unnecessary method calls would be saved.
Point your senior to this. If it works for limited resources on Android, I guess the technique of storing in local variables everything used in a for cycle is actually beneficial for performance anywhere.
In the excerpt below, note that we aren't even speaking about the overhead introduced by calling the (virtual) list.size() method, only storing the array.length as a local variable produces notable differences in performance.
public void zero() {
int sum = 0;
for (int i = 0; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
}
public void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
}
public void two() {
int sum = 0;
for (Foo a : mArray) {
sum += a.mSplat;
}
}
zero() is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop.
one() is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit.
two() is fastest for devices without a JIT, and indistinguishable from one() for devices with a JIT. It uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.
Just make the discountList field never null - ie initialized to an empty list - and iterate over it. Something like:
for (Discount discount : a.getCharges().getDiscounts().getDiscountList()) {
b.getList().get(0).setDiscountValue(discount.getValue());
b.getList().get(0).setDiscountName(discount.getName());
}
Your "senior" may need to do some research. The "performance impact" of doing this is a few bytes per object and a few microseconds per access. If he's really hung up about memory, initialise it with a LinkedList, which has almost no memory footprint.
In Java a variable V pointing to an object instance O is simply a numeric value pointing to a memory location where the object's data is stored.
When we assign Vto another variable V1 all that happens is that V1 now points to the same memory location where data for O is stored. This means that new memory is not allocated when you do simple assignment unlike C++ code where the = operator can be be overloaded to do a deep-copy in which case new memory is actually allocated. Illustrating with an example below
Consider a class like below
class Foo {
private List<String> barList = new ArrayList<>();
//class methods...
//getter for the list
List<String> getBarList() {
return this.barList;
}
}
public static void main(String[] args) {
Foo f = new Foo()
//the below lien will print 0 since there is no bar string added
System.out.println("Bar list size: " + f.getBarList().size());
// add a bar string. Observe here that I am simply getting the list
// and adding - similar to how your code is currently structured
f.getBarList().add("SomeString");
//now get a reference to the list and store it in a variable.
// Below anotherList only points to the same memory location
// where the original bar list is present. No new memory is allocated.
List<String> anotherList = f.getBarList();
//print the content of bar list and another list. Both will be same
for(String s : f.getBarList()) {
System.out.println(s);
}
for(String s: anotherList) {
System.out.println(s);
}
//add a new bar string using the reference variable
anotherList.add("Another string");
//print the content of bar list and another list. Both will be same. If anotherList had separate memory allocated to it then the new string added would be only seen when we print the content of anotherList and not when we print the content of f.getBarList(). This proves that references are only some numeric addresses that point to locations of the object on heap.
for(String s : f.getBarList()) {
System.out.println(s);
}
for(String s: anotherList) {
System.out.println(s);
}
}
Hope this helps.

Java-trouble with not equal to

I am trying to solve a question. But the program control is going into the if statement even when both the numbers I check are the same which is not supposed to happen. What is the reason?
static int lonelyinteger(int[] a) {
Integer[] b=new Integer[a.length];
for(int i=0;i<a.length;i++){
b[i]=new Integer(a[i]);
}
int val=0;
Arrays.sort(b);
boolean flag=false;
for(int i=0;i<a.length-2;i+=2)
if (b[i]!=b[i+1]){
val=b[i];
flag=true;
break;
}
if(flag==true)
return val;
else
return b[a.length-1];
You are using != on Integer objects. This will only work with integer values between -128 and 127 (reference) because these are cached by the JVM. But it won't work for larger/smaller values. Instead use .equals
if (!b[i].equals(b[i+1])){
val=b[i];
flag=true;
break;
}
As correctly pointed out by Jesper in the comments, the cache used for Integer objects by the JVM is not used when you force the JVM to create new Integer objects through the explicit call of the constructor as in new Integer(value). Calling the constructor will create new Integer instances instead of returning the cached Integer instances, which means that != and == which check whether the two objects are the same instance will always think the instances are different.
1) Do not use new Integer() use Integer.valueOf() instead.
2) Use Object.equals() when comparing objects.
if (b[i]!=b[i+1]) {
...
}
should be
if (!b[i].equals(b[i+1])) {
...
}

Comparing variables of objects in an array?

I've an array of objects in Java. Say these objects Obj contain a variable var, and I have several Obj stored in an array Array[].
I'd like to compare the var between two adjacent Obj but I don't know how, nor can I find any info online (which makes me think i'm working my question wrong or it's not doable or something)
Edit:
I'm currently attempting the rather roundabout method of assigning the array objects in question to new temporary objects and just doing the comparison with those:
Obj o1 = o[i];
Obj o2 = o[i+1];
if (o1.var > o2.var)
//etc
But surely there is something better.
If you have an array of objects, you can do your comparison without creating the temporary references:
MyObject[] arr = //populated somehow
for (int index = 0; index < arr.length - 1; index++) {
if (arr[index].var > arr[index + 1].var) {
//your logic
}
}
You might also want to take a look at the Comparable interface as a means of encapsulating the comparison of the objects based on a particular field. Using this interface would allow you to take advantage of its support in the Collections API.
Based on your edit, it would be fine to say
if (o[i].var > o[i+1].var) { ... }
assuming that o was of type Obj[].
I'm curious, though: are you trying to sort the array? If so, you can use Arrays.sort() (If not, it's a good method to know about anyway.)
I may not be understanding your question correctly, but the following is perfectly valid:
if (o[i].var > o[i+1].var ) { // ...etc... }
Beware of when you hit the end of the array! That is, if you are looping through all of the elements and i is the last one, then o[i+1] will give you an Array Index Out of Bounds error!
Just use them directly without the reference i.e. substitute the array lookup into where you are doing the comparison.
if (o[i].var > o[i+1].var) {
// etc
}
Or in a loop, doing every one programmatically:
for (int i=0; i<o.length-1; i++) {
if (o[i].var > o[i + 1].var) {
// etc
}
}

Most compact way to compare three objects for equality using Java?

What's the most compact code to compare three objects for (semantic) equality using Java? I have a business rule that the objects must be unique i.e. A is different to B, A is different to C and B is different to C.
Assume that the objects are all of the same class and have correctly overridden equals and hashCode methods. A slight wrinkle is that object C could be null—if this is the case then A and B have to be different to each other.
I have some code but it's a bit workmanlike for my tastes.
As the OP said A and B are never null, C may be null, use this:
if(A.equals(B) || B.equals(C) || A.equals(C))
// not unique
and, as others have already suggested, you can put it in a method for reuse. Or a generic method if you need more reuse ;-)
Note that in Java, a feature of equals is that if its argument is null it should not throw, but return false.
Since I never start a Java project without using Apache commons-lang, try ObjectUtils.equals (it's null safe):
if (ObjectUtils.equals(a, b) || ObjectUtils.equals(b, c) || ObjectUtils.equals(a, c)) {
// error condition
}
Put that logic in a generic method, and you'll do even better.
While the business logic allows C to be null, in scenarios like this, it's often better to code defensively and assume that either A or B could be null as well.
You can abstract that method in a utilities method like:
public boolean allUnique(Object... objs) {
Set<Object> set = new HashSet<Object>();
for (Object o : objs)
set.add(o);
return set.size() == objs.length
}
The method may not perform well for small numbers (due to the overhead of creating the Set and the varargs array). However, it grows linearly O(n), and for large values it's better than the quadratic growth of a nested if statements.
boolean areDistinct(Object a, Object b, Object c) {
return (!a.equals(b) &&
(c == null || (!c.equals(a) && !c.equals(b))));
}
As the apache's common.lang3.ObjectUtils.equals() is #Deprecated. Use Objects.equals(aObj,bObj). Comparison should be made with && if you want that all 3 objects are the same. Use || if you want that just one combination of a&b, a&c or b&c is the same.
/**
* Compare 3 objects of the same {#link TYPE}, if they are all equal using {#link Objects#equals(Object, Object)}.
*
* #param aObj the 1st object
* #param bObj the 2nd object
* #param cObj the 3th object
* #param <TYPE> the type of the objects
* #return true if the are all the same
*/
public static <TYPE> boolean equals(TYPE aObj, TYPE bObj, TYPE cObj) {
return Objects.equals(aObj, bObj) && Objects.equals(bObj, cObj) && Objects.equals(cObj, aObj);
}
As long as your objects implement equals, you can use the Stream API to get a distinct set of values, and if that distinct count is 1, they are all the same.
boolean allEqual = Stream.of(obj1, obj2, obj3).distinct().count() == 1
package com.test;
public class Equality {
public static void main(String[] args) {
Boolean flag;
int[] arr={1,1,1,12};
flag=check_equal(arr);
System.out.println(flag);
}
public static Boolean check_equal(int[] arr){
Boolean flag=true;
outerloop:
for(int i=1; i< arr.length; i++)
{
for(int j=1; j< arr.length; j++){
if(arr[i]==arr[j]){
flag=true;
}
else{
flag=false;
break outerloop;
}
}
}
return flag;
}
}

Categories