How to iterate through ArrayList of objects? - java

I have a class called SparseMatrix. It contains an ArrayList of Nodes (also class). I am wondering of how to iterate through the Array and access a value in Node. I have tried the following:
//Assume that the member variables in SparseMatrix and Node are fully defined.
class SparseMatrix {
ArrayList filled_data_ = new ArrayList();
//Constructor, setter (both work)
// The problem is that I seem to not be allowed to use the operator[] on
// this type of array.
int get (int row, int column) {
for (int i = 0; i < filled_data_.size(); i++){
if (row * max_row + column == filled_data[i].getLocation()) {
return filled_data[i].getSize();
}
}
return defualt_value_;
}
}
I will probably switch to static arrays (and remake it every time I add an object). If anyone has a solution, I would very much appreciate you sharing it with me. Also, thank you in advance for helping me.
Feel free to ask questions if you don't understand anything here.

Assuming filled_data_ is a list that contains list of objects of a class named Node.
List<Nodes> filled_data_ = new ArrayList<>();
for (Node data : filled_data_) {
data.getVariable1();
data.getVariable2();
}
More info http://crunchify.com/how-to-iterate-through-java-list-4-way-to-iterate-through-loop/

First of all, you should not use raw types. See this link for more info: What is a raw type and why shouldn't we use it?
The fix is to declare the type of object held by your array list. Change the declaration to:
ArrayList<Node> filled_data_ = new ArrayList<>();
Then you can access each element in the array list using filled_data_.get(i) (as opposed to filled_data_[i], which would work for a regular array).
`filled_data_.get(i)`
The above will return the element at index i. Documentation here: https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#get(int)

If you didn't use generic, then you need to cast the object
//Assume that the member variables in SparseMatrix and Node are fully defined.
class SparseMatrix {
ArrayList filled_data_ = new ArrayList();
//Constructor, setter (both work)
// The problem is that I seem to not be allowed to use the operator[] on
// this type of array.
int get (int row, int column) {
for (int i = 0; i < filled_data_.size(); i++){
Node node = (Node)filled_data.get(i);
if (row * max_row + column == node.getLocation()) {
return node.getSize();
}
}
return defualt_value_;
}
}

If array list contains Nodes which defines getLocation() you could use :
((Nodes)filled_data_.get(i)).getLocation()
You could also define
ArrayList<Nodes> filled_data_ = new ArrayList<Nodes>();

When you create the ArrayList object, you should specify the type of the contained elements with <> brackets. It is also good to keep the reference to the List interface - not ArrayList class. To iterate through such a collection, use foreach loop:
Here is an example of the Node class:
public class Node {
private int value;
public Node(int value) {
this.value = value;
}
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Here is an example of the Main class:
public class Main {
public static void main(String[] args) {
List<Node> filledData = new ArrayList<Node>();
filledData.add(new Node(1));
filledData.add(new Node(2));
filledData.add(new Node(3));
for (Node n : filledData) {
System.out.println(n.getValue());
}
}
}

Related

How to set a variable with type List<T> to a value with type ArrayList<T> using the constructor

An implementation of a graph node is as follows (I cannot change the implementation as it is from a coding website):
class Node {
public int val;
public List<Node> neighbors;
public Node(int _val, ArrayList<Node> _neighbors) {
val = _val;
neighbors = _neighbors;
}
}
If I pass a node to my copyGraph function below, I wouldn't be able to make a copy of that node by calling the Node constructor because I get
incompatible types: List cannot be converted to ArrayList
class Solution {
public Node copyGraph(Node node) {
Node n = new Node(node.val, node.neighbors);
//do some code
}
}
How else could I make a new Node with this implementation?
Problem
That API is poorly designed, FYI. The constructor should accept a List rather than ArrayList. Ideally that code would be:
public Node ( int _val , List < Node > _neighbors ) { … }
… or perhaps even the more general Collection if order were unimportant.
public Node ( int _val , Collection < Node > _neighbors ) { … }
Workaround
Two ways to work around that poor design: cast, or copy.
If you know for sure that your List object is actually an ArrayList, cast as shown in the correct Answer by coconan.
If you are not sure of the concrete implementation of your List object, construct a new ArrayList while passing your List.
Node n = new Node ( node.val, new ArrayList < Node > ( nodesList ) );
You can cast node.neighbors to ArrayList with (ArrayList<Node>) node.neighbors
class Solution {
public Node copyGraph(Node node) {
Node n = new Node(node.val, (ArrayList<Node>) node.neighbors);
//do some code
}
}

How to sort a list when certain values must appear later than others, potentially ignoring sort order for such items that need 'delaying' [duplicate]

This question already has answers here:
Sample Directed Graph and Topological Sort Code [closed]
(7 answers)
Closed 4 years ago.
Problem
I have the requirement to sort a list by a certain property of each object in that list. This is a standard action supported in most languages.
However, there is additional requirement that certain items may depend on others, and as such, must not appear in the sorted list until items they depend on have appeared first, even if this requires going against the normal sort order. Any such item that is 'blocked', should appear in the list the moment the items 'blocking' it have been added to the output list.
An Example
If I have items:
[{'a',6},{'b',1},{'c',5},{'d',15},{'e',12},{'f',20},{'g',14},{'h',7}]
Sorting these normally by the numeric value will get:
[{'b',1},{'c',5},{'a',6},{'h',7},{'e',12},{'g',14},{'d',15},{'f',20}]
However, if the following constraints are enforced:
a depends on e
g depends on d
c depends on b
Then this result is invalid. Instead, the result should be:
[{'b',1},{'c',5},{'h',7},{'e',12},{'a',6},{'d',15},{'g',14},{'f',20}]
Where b, c, d, e, f and h have been sorted in correct order b, c, h, e, d and f; both a and g got delayed until e and d respectively had been output; and c did not need delaying, as the value it depended on, b, had already been output.
What I have already tried
Initially I investigated if this was possible using basic Java comparators, where the comparator implementation was something like:
private Map<MyObject,Set<MyObject>> dependencies; // parent to set of children
public int compare(MyObj x, MyObj y) {
if (dependencies.get(x).contains(y)) {
return 1;
} else if (dependencies.get(y).contains(x)) {
return -1;
} else if (x.getValue() < y.getValue()) {
return -1;
} else if (x.getValue() > y.getValue()) {
return 1;
} else {
return 0;
}
}
However this breaks the requirement of Java comparators of being transitive. Taken from the java documentation:
((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0.
However, in the above example
a(6) < h(7) : true
h(7) < e(12) : true
a(6) < e(12) : false
Instead, I have come up with the below code, which while works, seems massively over-sized and over-complex for what seems like a simple problem. (Note: This is a slightly cut down version of the class. It can also be viewed and run at https://ideone.com/XrhSeA)
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class ListManager<ValueType extends Comparable<ValueType>> {
private static final class ParentChildrenWrapper<ValueType> {
private final ValueType parent;
private final Set<ValueType> childrenByReference;
public ParentChildrenWrapper(ValueType parent, Set<ValueType> childrenByReference) {
this.parent = parent;
this.childrenByReference = childrenByReference;
}
public ValueType getParent() {
return this.parent;
}
public Set<ValueType> getChildrenByReference() {
return this.childrenByReference;
}
}
private static final class QueuedItem<ValueType> implements Comparable<QueuedItem<ValueType>> {
private final ValueType item;
private final int index;
public QueuedItem(ValueType item, int index) {
this.item = item;
this.index = index;
}
public ValueType getItem() {
return this.item;
}
public int getIndex() {
return this.index;
}
#Override
public int compareTo(QueuedItem<ValueType> other) {
if (this.index < other.index) {
return -1;
} else if (this.index > other.index) {
return 1;
} else {
return 0;
}
}
}
private final Set<ValueType> unsortedItems;
private final Map<ValueType, Set<ValueType>> dependentsOfParents;
public ListManager() {
this.unsortedItems = new HashSet<>();
this.dependentsOfParents = new HashMap<>();
}
public void addItem(ValueType value) {
this.unsortedItems.add(value);
}
public final void registerDependency(ValueType parent, ValueType child) {
if (!this.unsortedItems.contains(parent)) {
throw new IllegalArgumentException("Unrecognized parent");
} else if (!this.unsortedItems.contains(child)) {
throw new IllegalArgumentException("Unrecognized child");
} else if (Objects.equals(parent,child)) {
throw new IllegalArgumentException("Parent and child are the same");
} else {
this.dependentsOfParents.computeIfAbsent(parent, __ -> new HashSet<>()).add(child);
}
}
public List<ValueType> createSortedList() {
// Create a copy of dependentsOfParents where the sets of children can be modified without impacting the original.
// These sets will representing the set of children for each parent that are yet to be dealt with, and such sets will shrink as more items are processed.
Map<ValueType, Set<ValueType>> blockingDependentsOfParents = new HashMap<>(this.dependentsOfParents.size());
for (Map.Entry<ValueType, Set<ValueType>> parentEntry : this.dependentsOfParents.entrySet()) {
Set<ValueType> childrenOfParent = parentEntry.getValue();
if (childrenOfParent != null && !childrenOfParent.isEmpty()) {
blockingDependentsOfParents.put(parentEntry.getKey(), new HashSet<>(childrenOfParent));
}
}
// Compute a list of which children impact which parents, alongside the set of children belonging to each parent.
// This will allow a child to remove itself from all of it's parents' lists of blocking children.
Map<ValueType,List<ParentChildrenWrapper<ValueType>>> childImpacts = new HashMap<>();
for (Map.Entry<ValueType, Set<ValueType>> entry : blockingDependentsOfParents.entrySet()) {
ValueType parent = entry.getKey();
Set<ValueType> childrenForParent = entry.getValue();
ParentChildrenWrapper<ValueType> childrenForParentWrapped = new ParentChildrenWrapper<>(parent,childrenForParent);
for (ValueType child : childrenForParent) {
childImpacts.computeIfAbsent(child, __ -> new LinkedList<>()).add(childrenForParentWrapped);
}
}
// If there are no relationships, the remaining code can be massively optimised.
boolean hasNoRelationships = blockingDependentsOfParents.isEmpty();
// Create a pre-sorted stream of items.
Stream<ValueType> rankedItemStream = this.unsortedItems.stream().sorted();
List<ValueType> outputList;
if (hasNoRelationships) {
// There are no relationships, and as such, the stream is already in a perfectly fine order.
outputList = rankedItemStream.collect(Collectors.toList());
} else {
Iterator<ValueType> rankedIterator = rankedItemStream.iterator();
int queueIndex = 0;
outputList = new ArrayList<>(this.unsortedItems.size());
// A collection of items that have been visited but are blocked by children, stored in map form for easy deletion.
Map<ValueType,QueuedItem<ValueType>> lockedItems = new HashMap<>();
// A list of items that have been freed from their blocking children, but have yet to be processed, ordered by order originally encountered.
PriorityQueue<QueuedItem<ValueType>> freedItems = new PriorityQueue<>();
while (true) {
// Grab the earliest-seen item which was once locked but has now been freed. Otherwise, grab the next unseen item.
ValueType item;
boolean mustBeUnblocked;
QueuedItem<ValueType> queuedItem = freedItems.poll();
if (queuedItem == null) {
if (rankedIterator.hasNext()) {
item = rankedIterator.next();
mustBeUnblocked = false;
} else {
break;
}
} else {
item = queuedItem.getItem();
mustBeUnblocked = true;
}
// See if this item has any children that are blocking it from being added to the output list.
Set<ValueType> childrenWaitingUpon = blockingDependentsOfParents.get(item);
if (childrenWaitingUpon == null || childrenWaitingUpon.isEmpty()) {
// There are no children blocking this item, so start removing it from all blocking lists.
// Get a list of all parents that is item was blocking, if there are any.
List<ParentChildrenWrapper<ValueType>> childImpact = childImpacts.get(item);
if (childImpact != null) {
// Iterate over all those parents
ListIterator<ParentChildrenWrapper<ValueType>> childImpactIterator = childImpact.listIterator();
while (childImpactIterator.hasNext()) {
// Remove this item from that parent's blocking children.
ParentChildrenWrapper<ValueType> wrappedParentImpactedByChild = childImpactIterator.next();
Set<ValueType> childrenOfParentImpactedByChild = wrappedParentImpactedByChild.getChildrenByReference();
childrenOfParentImpactedByChild.remove(item);
// Does this parent no longer have any children blocking it?
if (childrenOfParentImpactedByChild.isEmpty()) {
// Remove it from the children impacts map, to prevent unnecessary processing of a now empty set in future iterations.
childImpactIterator.remove();
// If this parent was locked, mark it as now freed.
QueuedItem<ValueType> freedQueuedItem = lockedItems.remove(wrappedParentImpactedByChild.getParent());
if (freedQueuedItem != null) {
freedItems.add(freedQueuedItem);
}
}
}
// If there are no longer any parents at all being blocked by this child, remove it from the map.
if (childImpact.isEmpty()) {
childImpacts.remove(item);
}
}
outputList.add(item);
} else if (mustBeUnblocked) {
throw new IllegalStateException("Freed item is still blocked. This should not happen.");
} else {
// Mark the item as locked.
lockedItems.put(item,new QueuedItem<>(item,queueIndex++));
}
}
// Check that all items were processed successfully. Given there is only one path that will add an item to to the output list without an exception, we can just compare sizes.
if (outputList.size() != this.unsortedItems.size()) {
throw new IllegalStateException("Could not complete ordering. Are there recursive chains of items?");
}
}
return outputList;
}
}
My question
Is there an already existing algorithm, or an algorithm significantly shorter than the above, that will allow this to be done?
While the language I am developing in is Java, and the code above is in Java, language-independent answers that I could implement in Java are also fine.
This is called topological sorting. You can model "blocking" as edges of a directed graph. This should work if there are no circular "blockings".
I've done this in <100 lines of c# code (with comments). This implementation seems a little complicated.
Here is the outline of the algorithm
Create a priority queue that is keyed by value that you want to sort by
Insert all the items that do not have any "blocking" connections incoming
While there are elements in the queue:
Take an element of the queue. Put it in your resulting list.
If there are any elements that were being directly blocked by this element and were not visited previously, put them into the queue (an element can have more than one blocking element, so you check for that)
A list of unprocessed elements should be empty at the end, or you had a cycle in your dependencies.
This is essentialy Topological sort with built in priority for nodes. Keep in mind that the result can be quite suprising depending on the number of connections in your graph (ex. it's possible to actually get elements that are in reverse order).
As Pratik Deoghare stated in their answer, you can use topological sorting. You can view your "dependencies" as arcs of a Directed Acyclic Graph (DAG). The restriction that the dependencies on the objects are acyclic is important as topological sorting is only possible "if and only if the graph has no directed cycles." The dependencies also of course don't make sense otherwise (i.e. a depends on b and b depends on a doesn't make sense because this is a cyclic dependency).
Once you do topological sorting, the graph can be interpreted as having "layers". To finish the solution, you need to sort within these layers. If there are no dependencies in the objects, this leads to there being just one layer where all the nodes in the DAG are on the same layer and then they are sorted based on their value.
The overall running time is still O(n log n) because topological sorting is O(n) and sorting within the layers is O(n log n). See topological sorting wiki for full running time analysis.
Since you said any language that could be converted to Java, I've done a combination of [what I think is] your algorithm and ghord's in C.
A lot of the code is boilerplate to handle arrays, searches, and array/list insertions that I believe can be reduced by using standard Java primitives. Thus, the amount of actual algorithm code is fairly small.
The algorithm I came up with is:
Given: A raw list of all elements and a dependency list
Copy elements that depend on another element to a "hold" list. Otherwise, copy them to a "sort" list.
Note: an alternative is to only use the sort list and just remove the nodes that depend on another to the hold list.
Sort the "sort" list.
For all elements in the dependency list, find the corresponding nodes in the sort list and the hold list. Insert the hold element into the sort list after the corresponding sort element.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
// sort node definition
typedef struct {
int key;
int val;
} Node;
// dependency definition
typedef struct {
int keybef; // key of node that keyaft depends on
int keyaft; // key of node to insert
} Dep;
// raw list of all nodes
Node rawlist[] = {
{'a',6}, // depends on e
{'b',1},
{'c',5}, // depends on b
{'d',15},
{'e',12},
{'f',20},
{'g',14}, // depends on d
{'h',7}
};
// dependency list
Dep deplist[] = {
{'e','a'},
{'b','c'},
{'d','g'},
{0,0}
};
#define MAXLIST (sizeof(rawlist) / sizeof(rawlist[0]))
// hold list -- all nodes that depend on another
int holdcnt;
Node holdlist[MAXLIST];
// sort list -- all nodes that do _not_ depend on another
int sortcnt;
Node sortlist[MAXLIST];
// prtlist -- print all nodes in a list
void
prtlist(Node *node,int nodecnt,const char *tag)
{
printf("%s:\n",tag);
for (; nodecnt > 0; --nodecnt, ++node)
printf(" %c:%d\n",node->key,node->val);
}
// placenode -- put node into hold list or sort list
void
placenode(Node *node)
{
Dep *dep;
int holdflg;
holdflg = 0;
// decide if node depends on another
for (dep = deplist; dep->keybef != 0; ++dep) {
holdflg = (node->key == dep->keyaft);
if (holdflg)
break;
}
if (holdflg)
holdlist[holdcnt++] = *node;
else
sortlist[sortcnt++] = *node;
}
// sortcmp -- qsort compare function
int
sortcmp(const void *vlhs,const void *vrhs)
{
const Node *lhs = vlhs;
const Node *rhs = vrhs;
int cmpflg;
cmpflg = lhs->val - rhs->val;
return cmpflg;
}
// findnode -- find node in list that matches the given key
Node *
findnode(Node *node,int nodecnt,int key)
{
for (; nodecnt > 0; --nodecnt, ++node) {
if (node->key == key)
break;
}
return node;
}
// insert -- insert hold node into sorted list at correct spot
void
insert(Node *sort,Node *hold)
{
Node prev;
Node next;
int sortidx;
prev = *sort;
*sort = *hold;
++sortcnt;
for (; sort < &sortlist[sortcnt]; ++sort) {
next = *sort;
*sort = prev;
prev = next;
}
}
int
main(void)
{
Node *node;
Node *sort;
Node *hold;
Dep *dep;
prtlist(rawlist,MAXLIST,"RAW");
printf("DEP:\n");
for (dep = deplist; dep->keybef != 0; ++dep)
printf(" %c depends on %c\n",dep->keyaft,dep->keybef);
// place nodes into hold list or sort list
for (node = rawlist; node < &rawlist[MAXLIST]; ++node)
placenode(node);
prtlist(sortlist,sortcnt,"SORT");
prtlist(holdlist,holdcnt,"HOLD");
// sort the "sort" list
qsort(sortlist,sortcnt,sizeof(Node),sortcmp);
prtlist(sortlist,sortcnt,"SORT");
// add nodes from hold list to sort list
for (dep = deplist; dep->keybef != 0; ++dep) {
printf("inserting %c after %c\n",dep->keyaft,dep->keybef);
sort = findnode(sortlist,sortcnt,dep->keybef);
hold = findnode(holdlist,holdcnt,dep->keyaft);
insert(sort,hold);
prtlist(sortlist,sortcnt,"POST");
}
return 0;
}
Here's the program output:
RAW:
a:6
b:1
c:5
d:15
e:12
f:20
g:14
h:7
DEP:
a depends on e
c depends on b
g depends on d
SORT:
b:1
d:15
e:12
f:20
h:7
HOLD:
a:6
c:5
g:14
SORT:
b:1
h:7
e:12
d:15
f:20
inserting a after e
POST:
b:1
h:7
e:12
a:6
d:15
f:20
inserting c after b
POST:
b:1
c:5
h:7
e:12
a:6
d:15
f:20
inserting g after d
POST:
b:1
c:5
h:7
e:12
a:6
d:15
g:14
f:20
I think you are generally on the right track, and the core concept behind your solution is similar to the one I will post below. The general algorithm is as follows:
Create a map that associates each item to the items that depend upon it.
Insert elements with no dependencies into a heap.
Remove the top element from the heap.
Subtract 1 from dependency count of each dependent of the element.
Add any elements with a dependency count of zero to the heap.
Repeat from step 3 until the heap is empty.
For simplicity I have replaced your ValueType with a String, but the same concepts apply.
The BlockedItem class:
import java.util.ArrayList;
import java.util.List;
public class BlockedItem implements Comparable<BlockedItem> {
private String value;
private int index;
private List<BlockedItem> dependentUpon;
private int dependencies;
public BlockedItem(String value, int index){
this.value = value;
this.index = index;
this.dependentUpon = new ArrayList<>();
this.dependencies = 0;
}
public String getValue() {
return value;
}
public List<BlockedItem> getDependentUpon() {
return dependentUpon;
}
public void addDependency(BlockedItem dependentUpon) {
this.dependentUpon.add(dependentUpon);
this.dependencies++;
}
#Override
public int compareTo(BlockedItem other){
return this.index - other.index;
}
public int countDependencies() {
return dependencies;
}
public int subtractDependent(){
return --this.dependencies;
}
#Override
public String toString(){
return "{'" + this.value + "', " + this.index + "}";
}
}
The BlockedItemHeapSort class:
import java.util.*;
public class BlockedItemHeapSort {
//maps all blockedItems to the blockItems which depend on them
private static Map<String, Set<BlockedItem>> generateBlockedMap(List<BlockedItem> unsortedList){
Map<String, Set<BlockedItem>> blockedMap = new HashMap<>();
//initialize a set for each element
unsortedList.stream().forEach(item -> {
Set<BlockedItem> dependents = new HashSet<>();
blockedMap.put(item.getValue(), dependents);
});
//place each element in the sets corresponding to its dependencies
unsortedList.stream().forEach(item -> {
if(item.countDependencies() > 0){
item.getDependentUpon().stream().forEach(dependency -> blockedMap.get(dependency.getValue()).add(item));
}
});
return blockedMap;
}
public static List<BlockedItem> sortBlockedItems(List<BlockedItem> unsortedList){
List<BlockedItem> sorted = new ArrayList<>();
Map<String, Set<BlockedItem>> blockedMap = generateBlockedMap(unsortedList);
PriorityQueue<BlockedItem> itemHeap = new PriorityQueue<>();
//put elements with no dependencies in the heap
unsortedList.stream().forEach(item -> {
if(item.countDependencies() == 0) itemHeap.add(item);
});
while(itemHeap.size() > 0){
//get the top element
BlockedItem item = itemHeap.poll();
sorted.add(item);
//for each element that depends upon item, decrease its dependency count
//if it has a zero dependency count after subtraction, add it to the heap
if(!blockedMap.get(item.getValue()).isEmpty()){
blockedMap.get(item.getValue()).stream().forEach(dependent -> {
if(dependent.subtractDependent() == 0) itemHeap.add(dependent);
});
}
}
return sorted;
}
}
You can modify this to more closely fit your use-case.
Java Code for topological sort:
static List<ValueType> topoSort(List<ValueType> vertices) {
List<ValueType> result = new ArrayList<>();
List<ValueType> todo = new LinkedList<>();
Collections.sort(vertices);
for (ValueType v : vertices){
todo.add(v);
}
outer:
while (!todo.isEmpty()) {
for (ValueType r : todo) {
if (!hasDependency(r, todo)) {
todo.remove(r);
result.add(r);
// no need to worry about concurrent modification
continue outer;
}
}
}
return result;
}
static boolean hasDependency(ValueType r, List<ValueType> todo) {
for (ValueType c : todo) {
if (r.getDependencies().contains(c))
return true;
}
return false;
}
ValueType is described like below:
class ValueType implements Comparable<ValueType> {
private Integer index;
private String value;
private List<ValueType> dependencies;
public ValueType(int index, String value, ValueType...dependencies){
this.index = index;
this.value = value;
this.dependencies = dependencies==null?null:Arrays.asList(dependencies);
}
public List<ValueType> getDependencies() {
return dependencies;
}
public void setDependencies(List<ValueType> dependencies) {
this.dependencies = dependencies;
}
#Override
public int compareTo(#NotNull ValueType o) {
return this.index.compareTo(o.index);
}
#Override
public String toString() {
return value +"(" + index +")";
}
}
And tested with these values:
public static void main(String[] args) {
//[{'a',6},{'b',1},{'c',5},{'d',15},{'e',12},{'f',20},{'g',14},{'h',7}]
//a depends on e
//g depends on d
//c depends on b
ValueType b = new ValueType(1,"b");
ValueType c = new ValueType(5,"c", b);
ValueType d = new ValueType(15,"d");
ValueType e = new ValueType(12,"e");
ValueType a = new ValueType(6,"a", e);
ValueType f = new ValueType(20,"f");
ValueType g = new ValueType(14,"g", d);
ValueType h = new ValueType(7,"h");
List<ValueType> valueTypes = Arrays.asList(a,b,c,d,e,f,g,h);
List<ValueType> r = topoSort(valueTypes);
for(ValueType v: r){
System.out.println(v);
}
}

Merge two lists on index

I have two lists containing the same type of objects. Each object has an int, a string and some other stuff where the int is its index.
Here is the object that both lists are holding:
public class ListElement
{
private int index;
private String data;
private String some;
private String other;
private String stuff;
// gets, sets...
}
What i want is to take List A's index and "some other stuff" and replace its string "data" with the one from List B. The one it takes from List B should match the index of List A. I hope this is understandable.
EDIT: It should be noted that the index int inside the object has nothing to do with the actual position of the object in the list. Its for other porpuses
UPDATE: You mentioned that the index field of your ListElement has no relationship with its actual place in its containing List.
You just happen to have a field with a random name that you want to compare both list on (join on). This solution uses nested loops to compare every element in one list with every element in the other list.
for (int iA = 0; iA < listA.size(); iA++) //iterate over listA
{
ListElement currentElement = listA.get(iA);
for (int iB = 0; iB < listB.size(); iB++) //iterate over listB
{
ListElement other = listB.get(iB);
if (other.index == currentElement.index) //compare the elements
{
//do stuff
currentElement.setData(other.getData());
break; //if only want first match
}
}
}
Assuming your both list have the same number of elements, you could do something like:
ListElement sourceElement, destElement;
for (int i =0; i<list1.size(); i++) {
sourceElement = list1.get(0);
destElement = list2.get(0);
sourceElement.setData(destElement.getData());
...
}
The first idea is probably not the brightest but I'll come to that later.
For (ListElement e : ListA) {
For (ListElement le : ListB) {
if (e.getIndex() = le.getIndex()) {
e.setData(le.getData());
}
}
}
So this is my first shot for what you wrote, but it's probably not the easiest way. To make it simpler and faster you could implement the interface Comparable and use sort, i this case you access the List elements by the index in ListElement (assuming you assure the indices are complete from 1..n).
My favored solution would be to use some kind of maps to store the index as key, and the ListElement as value, then it's just MapA.get(i).setData(MapB.get(i).getData()) This is fool-prove, as long as for every item in MapA there is an according item in MapB with the same index.
If you want to match on the index field on the ListItem object, try this:
for (ListItem listItemA : listA) {
for (ListItem listItemB : listB) {
if (listItemB.getIndex() == listItemA.getIndex()) {
listItemA.setData(listItemB.getData());
}
}
}
If you're interested in matching based on index within the List objects, try
for (int i = 0; i < listA.size(); i++) {
listA.get(i).setData(listB.get(i).getData());
}

Sort string-array using java

I have a vector in which which holds items of type string. i am able to add items to the vector using
public void AddItem(String value)
{
data[length] = value;
length++;
}
however i would like the vector to be sorted in ascending order once items are added to in any particular order for instance if i added these items
v.AddItem("10");
v.AddItem("20");
v.AddItem("30");
v.AddItem("40");
v.AddItem("50");
v.AddItem("90");
v.AddItem("70");
v.AddItem("80");
i would expect "90" to be the last item in the list. i tried using this
for (int i = length- 1; i>1;i++)
{
if (data[length -1].compareTo(data[length]) > 0)
{
data[length-1] = temp;
data[length]=data[length -1];
temp = data[length];
}
}
and it doesnt seem to work can anybody point me in the right direction?
Arrays.sort(data);
instead of
for (int i = length- 1; i>1;i++)
{
if (data[length -1].compareTo(data[length]) > 0)
{
data[length-1] = temp;
data[length]=data[length -1];
temp = data[length];
}
}
but recommend use collections, if random access - ArraysList, for example,
if consistent access to elements use LinkedList
List<YourType> list = new LinkedList<YourType>();
list.add(SomeValue);
Collections.sort(list);
If values distinct, you can use TreeSet, this Collection sort values when adding new value:
Set<YourType> set = new TreeSet<YourType>();
set.add(SomeValue);
// Collections.sort(list) - not needed, set already sorted :)
You can use Arrays.sort() (notice that you need to add import statement):
import java.util.Arrays; // or just: import java.util.*;
public void AddItem(String value)
{
data[length] = value;
length++;
Arrays.sort(data);
}
As other people have pointed out in the comments, the data structure you use is array, not Vector.

couldn't cast an object array to another type array

been pulling my hair for nights when I get an ClassCastException as I try to cast an object type to another object type.... I'm that sure that this code will work because all objects are are subclasses of the Object class... but somehow i get this exception...some help guys?
Sorry guys..not to be confused with the Original ArrayList, I'm learning Java programming, and practicing on casting object arrays... the exception is at line 8, where I casted the object array to a weapon array type... sorry for any form of trolling...
public class ArrayList {
public static void main(String args[]){
ArrayList arrayList = new ArrayList();
weapon[] weapons = new weapon[5];
for (int i = 0; i < weapons.length; i++) {
weapons[i] = new weapon(i);
}
weapons = (weapon[]) arrayList.add(weapons,
new weapon(weapons.length + 1, "mp5"));
}
public Object[] add(Object[] targetObjectList, Object add){
Object[] oldList = new Object[targetObjectList.length];
for (int i = 0 ; i < oldList.length; i++){
oldList[i] = targetObjectList[i];
}
Object[] newList = new Object[oldList.length+1];
for (int i = 0; i < oldList.length; i++) {
newList[i] = oldList[i];
}
newList[newList.length - 1] = add;
return newList;
}
}//end arrayList class
class weapon {
String name;
int id;
public weapon(int id) {
this.id = id;
name = "weapon";
}
public weapon(int id, String name) {
this.id = id;
this.name = name;
}
}
A weapon is an Object; therefore, we may treat an array af weapon as an array of Object. However, not all Objects are weapons; therefore, an array of Object may not be treated as an array of weapon - unless the thing that seems to be an array of Object really was an array of weapon to begin with. Because of this, your approach will become difficult. You could try
weapon[] newList = new weapon[oldList.length+1];
instead, but then you'd need to change all the arrays to be of type weapon[], and the method wouldn't become general (which I suppose is your goal). However, if you want a method that can add an element to any kind of array, you should use generics instead.
P.S. If you are learning about programming and arrays, writing such an add() method is a good exercise - but if you "just want it to work", you should use ArrayList instead, which does the whole job of adding for you.
Arrays are subclass of Object. You cannot cast Object[] to weapon[]. Here is a generic solution for your problem:
weapons = (weapon[])arrayList.add(weapons, new weapon(weapons.length + 1, "mp5"),weapon.class);
and
public <T> T[] add(T[] targetObjectList, T add, Class<T> c) {
T[] oldList = (T[])Array.newInstance(c, targetObjectList.length);
for (int i = 0; i < oldList.length; i++) {
oldList[i] = targetObjectList[i];
}
T[] newList = (T[])Array.newInstance(c, oldList.length + 1);
for (int i = 0; i < oldList.length; i++) {
newList[i] = oldList[i];
}
newList[newList.length - 1] = add;
return newList;
}
Note: Follow Java Naming Conventions. Avoid Java API class names as your class name.
Object o = new Foo(). This is ok. Foo is Object. As Foo extends Object
Foo f = new Object() Not OK, Object is NOT Foo (Compiler error)
Foo f = (Foo)(new Object()) - ClassCastException
What you are looking to do is known as contravariance. The inherent problem in your code is that the ARRAY that you are creating in the add function is an array of Objects (regardless of what those objects actually end up being).
If you were to do the following, your code would work. I think that you need to work with generics in this sense (look at the actual ArrayList class as it already implements this).
...snip...
Object[] newList = new weapon[oldList.length+1];
for (int i = 0; i < oldList.length; i++) {
newList[i] = oldList[i];
}
newList[newList.length - 1] = add;
return newList;
...snip...
Here is an example code that works much as you are anticipating it.
public class Test {
public static void main(String[] args) {
Integer[] i = (Integer[])Test.get();
}
public static Object[] get() {
Object[] o = new Object[20];
for(int i = 0; i < o.length; i++) {
o[i] = new Integer(0);
}
return o;
}
}
ArrayList has a method .toArray(T[] a) which will return an enlarged array size containing your new elements. So how does this contravariance work? Through the java.reflect package. This is a very small excerpt of how it actually works (there are a few different packages that work together to get down to this.)
...Object[] function(Object[] typearray) {
Object[] o = (Object[]) Array.newInstance(typearray.getClass().getComponentType(), 20);
...fill...
return o;
}
The reason you must do this is because the ARRAY (since everything in Java are objects) is an Object itself, then an Array of Objects cannot be upcasted to an Array of Integers. If you downcasted from an array of integers to an array of Objects (as shown in this above example) and then upcasted again from an Array of Objects to an Array of Integers (because we never dropped the underlying class of it being an Array of Integers).

Categories

Resources