I need to group a given sort list by some given "blocks" or "groups" of elements. For example:
Given a list:
[A, B, C, D, E, F, G, H, I, J]
And groups
[A, C, D]
[F, E]
[J, H, I]
the result should be
[A, C, D, B, F, E, G, J, H, I]
The blocks of elements can not be mixed with non-group elements. The blocks should have the same order. The other elements of the list should mantain their order.
I have already found a solution. But it's not the most efficient code as you will see.
I'm using java 6 also...
public static List<CategoryProduct> sortProductsByBlocks(List<CategoryProduct> products, CategoryBlocks categoryBlocks) {
if (!validateCategoryBlocks(categoryBlocks)) {
return products;
}
Map<String, BlockView> mapProductByBlock = mapBlocksByPartnumber(categoryBlocks);
Map<String, BlockView> mapFirstProductByBlock = mapFirstProductByBlock(categoryBlocks);
Map<Integer, Block> blocksById = blocksById(categoryBlocks);
List<CategoryProduct> sortedProduct = Lists.newArrayList();
Map<String, CategoryProduct> productsMapByPartNumber = ProductHelper.getProductsMapByPartNumber(products);
List<CategoryProduct> processedProducts = Lists.newArrayList();
int j = 0;
for (int i = 0; i < products.size(); i++) {
CategoryProduct product = products.get(i);
if (blocksById.isEmpty() && !processedProducts.contains(product)) {
sortedProduct.add(j++, product);
processedProducts.add(product);
}
if (!processedProducts.contains(product) && (mapFirstProductByBlock.get(product.getPartNumber()) != null
|| mapProductByBlock.get(product.getPartNumber()) == null)) {
BlockView blockView = mapProductByBlock.get(product.getPartNumber());
if (blockView != null) {
Block block = blocksById.get(blockView.getBlockId());
if (block == null) {
sortedProduct.add(j++, product);
continue;
}
for (BlockProduct blockProduct : block.getProducts()) {
CategoryProduct categoryProduct = productsMapByPartNumber.get(blockProduct.getPartnumber());
sortedProduct.add(j++, categoryProduct);
processedProducts.add(categoryProduct);
}
blocksById.remove(blockView.getBlockId());
} else {
sortedProduct.add(j++, product);
processedProducts.add(product);
}
}
}
return sortedProduct;
}
Any advice to improve and make it faster will be welcome.
(edit with the improved code)
public static List<CategoryProduct> sortProductsByBlocks2(List<CategoryProduct> products,
CategoryBlocks categoryBlocks) {
if (!validateCategoryBlocks(categoryBlocks)) {
return products;
}
Map<String, Integer> blocksIdByFirstPartnumber = Maps.newHashMap();
List<String> partnumbersInBlocks = Lists.newArrayList();
for (int k = 0; k < categoryBlocks.getBlocks().size(); k++) {
Block block = categoryBlocks.getBlocks().get(k);
if (block != null && block.getProducts() != null) {
for (int i = 0; i < block.getProducts().size(); i++) {
BlockProduct blockProduct = block.getProducts().get(i);
if (i == 0) {
blocksIdByFirstPartnumber.put(blockProduct.getPartnumber(), k);
} else {
partnumbersInBlocks.add(blockProduct.getPartnumber());
}
}
}
}
CategoryProduct[] result = new CategoryProduct[products.size()];
Map<String, Integer> productsIndex = Maps.newHashMap();
Map<String, CategoryProduct> categoryProductByPartnumber = Maps.newHashMap();
int indexResult = 0;
for (CategoryProduct categoryProduct : products) {
String partNumber = categoryProduct.getPartNumber();
if (!partnumbersInBlocks.contains(partNumber)) {
if (blocksIdByFirstPartnumber.get(partNumber) != null) {
Block categoryProductBlock = categoryBlocks.getBlocks()
.get(blocksIdByFirstPartnumber.get(partNumber));
result[indexResult] = categoryProduct;
indexResult++;
for (int i = 1; i < categoryProductBlock.getProducts().size(); i++) {
BlockProduct blockProduct = categoryProductBlock.getProducts().get(i);
if (categoryProductByPartnumber.get(blockProduct.getPartnumber()) != null) {
result[indexResult] = categoryProductByPartnumber.get(blockProduct.getPartnumber());
} else {
productsIndex.put(blockProduct.getPartnumber(), indexResult);
result[indexResult] = null;
}
indexResult++;
}
} else {
result[indexResult] = categoryProduct;
indexResult++;
}
} else {
if (productsIndex.get(partNumber) != null) {
result[productsIndex.get(partNumber)] = categoryProduct;
} else {
categoryProductByPartnumber.put(partNumber, categoryProduct);
}
}
}
return Lists.newArrayList(Arrays.asList(result));
}
Performance:
Elements New algorithm Old algorithm
1200 0.002s 0.129s
12000 0.021s 14.673s
Form the code you submitted, I cannot figure out how your algorithm is fully working.
I can write another algorithm that will do the task.
Mark the first element for each group
[A,C,D] -> A
Remove from list(to_be_sorted) all elements from groups that are not marked
[A,C,D] -> remove [C,D]
perform sort on list
result ([A,B,F,G,J])
place removed element based on Mark
Initial Sorted List [A,B,F,G,J]
A->add [C,D]
List is [A,C,D,B,F,G,J]
B->as it is
F->add [E]
List is [A,C,D,B,F,E,G,J]
G->as it is
J->add [H,I]
Final Sorted List [A,C,D,B,F,E,G,J,H,I]
Time complexity is the same as sorting algorithm
By your definition it isn't entirely clear what the conditions are to merge the results from your given list and 'groups' ( arrays ). However, here is a solution based on your requirements using the assertion
"You want the first element of the list not contained in any of the groups inserted between the groups... "
public class MergeArrays {
private static final List<String> FIRST = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J"));
private static final List<String> SECOND = new ArrayList<>(Arrays.asList("A", "C", "D"));
private static final List<String> THIRD = new ArrayList<>(Arrays.asList("F", "E"));
private static final List<String> FOURTH = new ArrayList<>(Arrays.asList("J", "H", "I"));
public static List<String> merge(List<String> source, List<String>... lists) {
List<String> result = new ArrayList<>();
for (List<String> list : lists) {
for (String value : list) {
source.remove(value);
}
}
for (List<String> list : lists) {
String value = null;
if (source.size() > 0) {
value = source.get(0);
source.remove(0);
}
result.addAll(merge(value, list));
}
return result;
}
public static List<String> merge(String value, List<String> list) {
List<String> result = new ArrayList<>(list);
if (value != null) {
result.add(value);
}
return result;
}
public static void main(String[] args) {
List<String> result = merge(FIRST, SECOND, THIRD, FOURTH);
System.out.println(result);
}
}
//Results
[A, C, D, B, F, E, G, J, H, I]
Related
I've an ArrayList which contains pairs of integers( say int i, int j). But it may be contains duplicates pairs (like (int i, int j) and (int j, int i)). Now how can I remove duplicates from it in O(n) time complexity.
Updated code:
class Pair<t1,t2>
{
int i, j;
Pair(int i,int j){
this.i=i;
this.j=j;
}
}
public class My
{
public static void main(String[] args) {
Pair p;
List<Pair<Integer,Integer>> src = Arrays.asList(new Pair(1,2),
new Pair(2,3), new Pair(2,1),new Pair(1,2));
HashSet<String> dest = new HashSet();
for(int i=0; i < src.size(); i++) {
p=src.get(i);
if(dest.contains(p.j+" "+p.i)) {
System.out.println("duplicacy");
}
else {
dest.add(p.i+" "+p.j);
}
}
System.out.println("set is = "+dest);
List<Pair<Integer,Integer>> ans=new ArrayList();
String temp;
int i,j;
Iterator<String> it=dest.iterator();
while(it.hasNext())
{
temp=it.next();
i=Integer.parseInt(temp.substring(0,temp.indexOf(' ')));
j=Integer.parseInt(temp.substring(temp.indexOf('
')+1,temp.length()));
ans.add(new Pair(i,j));
}
for(Pair i_p:ans) {
System.out.println("Pair = "+i_p.i+" , "+i_p.j);
}
}//end of main method
}//end of class My
This code is working fine but I want to know it performance wise, I mean its overall time complexity ?
If you can modify Pair class, just implement equals() and hashCode():
public class Pair {
private int a;
private int b;
public Pair(int a, int b) {
this.a = a;
this.b = b;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return (a == pair.a && b == pair.b) || (a == pair.b && b == pair.a);
}
#Override
public int hashCode() {
return Objects.hashCode(new HashSet<>(Arrays.asList(a,b)));
}
#Override
public String toString() {
return "Pair{" +
"a=" + a +
", b=" + b +
'}';
}
}
Then just create a new Set<Pair>:
List<Pair> pairs = Arrays.asList(new Pair(1, 2), new Pair(2, 1), new Pair(3, 2));
Set<Pair> pairSet = new HashSet<>(pairs);
System.out.println(pairSet);
Output:
[Pair{a=1, b=2}, Pair{a=3, b=2}]
If you can't modify Pair class:
List<Pair> pairs = Arrays.asList(new Pair(1, 2), new Pair(2, 1), new Pair(3, 2));
Set<Pair> pairSet = pairs.stream()
.map(pair -> new HashSet<>(Arrays.asList(pair.getA(), pair.getB())))
.distinct()
.map(integers -> {
Iterator<Integer> iterator = integers.stream().iterator();
return new Pair(iterator.next(), iterator.next());
})
.collect(Collectors.toSet());
System.out.println(pairSet);
Output:
[Pair{a=1, b=2}, Pair{a=2, b=3}]
If you want, you can convert your Set back to a list:
List<Pair> list = new ArrayList<>(set);
But it's most likely unnecessary.
Make only one loop throught list of Pairs and collect by the way in HashSet processed pair and it's reversed copy:
List<Pair<Integer,Integer>> lp = Arrays.asList(new Pair(1,2),
new Pair(2,3),
new Pair(1,2),
new Pair(2,1));
Set<Pair<Integer,Integer>> sp = new HashSet<>();
List<Pair<Integer,Integer>> ulp = lp.stream()
.collect(ArrayList::new,
(l,p)-> { Pair<Integer,Integer> p1 = new Pair(p.getValue(), p.getKey());
if (!(sp.contains(p))&&!(sp.contains(p1))){
l.add(p);
sp.add(p);
sp.add(p1);
}} , List::addAll);
System.out.println(ulp);
Since the contains() of HashSet runs in O(1) time (See this and other references) you can use the following method which is the overall O(n):
import java.util.*;
import javafx.util.*;
public class Main
{
public static void main(String[] args) {
List<Pair<Integer,Integer>> src = Arrays.asList(new Pair(1,2), new Pair(2,3), new Pair(2,1));
HashSet<Pair<Integer,Integer>> dest = new HashSet();
for(int i=0; i < src.size(); i++) {
if(dest.contains(src.get(i)) ||
dest.contains(new Pair(src.get(i).getValue(),src.get(i).getKey()))) {
}else {
dest.add(src.get(i));
}
}
System.out.println(dest);
}
}
EDIT 1:
You can use Map.Entry instead of javafx.util.pair. Do the program without Javafx is as follow.
import java.util.*;
public class Main
{
public static void main(String[] args) {
List<Map.Entry<Integer,Integer>> src = Arrays.asList(new AbstractMap.SimpleEntry(1,2),
new AbstractMap.SimpleEntry(2,3), new AbstractMap.SimpleEntry(2,1));
HashSet<Map.Entry<Integer,Integer>> dest = new HashSet();
for(int i=0; i < src.size(); i++) {
if(dest.contains(src.get(i)) ||
dest.contains(new AbstractMap.SimpleEntry(src.get(i).getValue(),src.get(i).getKey()))) {
}else {
dest.add(src.get(i));
}
}
System.out.println(dest);
}
}
2*2 Matrix
Men Friends
A B,C,D
B E,F
C A
E B
F B
G F
I need list of Friends and Friends of Friends for requested men.
Example Like G -> F,B,E,F,B and After removing duplicate F,B,E
I resolved it with loops and recursion but not satisfied
Need better approach/suggestion.. rest i will implement.
Why not try something like this. Of course, i have taken a bit of freedom on the design as you didnt provide any code. Hope this helps!
private static Set<Node> getNodesFollowAllEdges(Node node) {
Set<Node> nodes = getNodesFollowAllEdges(node, new HashSet<>());
// remember to remove the original node from the set
nodes.remove(node);
return nodes;
}
private static Set<Node> getNodesFollowAllEdges(Node node, Set<Node> visited) {
if (node.getConnectedNodes().isEmpty()) {
return visited;
}
for (Node n : node.getConnectedNodes()) {
if (!visited.contains(n)) {
visited.add(n);
getNodesFollowAllEdges(n, visited);
}
}
return visited;
}
Also, it is very easy to provide a maximum search dept. Just add int maxDept and increase it every recursion step.
Given the following example:
Node a = new Node("A");
Node b = new Node("B");
Node c = new Node("C");
Node d = new Node("D");
Node e = new Node("E");
Node f = new Node("F");
Node g = new Node("G");
a.addConnectedNodes(b, c, d);
b.addConnectedNodes(e, f);
c.addConnectedNodes(a);
e.addConnectedNodes(b);
f.addConnectedNodes(b);
g.addConnectedNodes(f);
Set<Node> friends = getNodesFollowAllEdges(a);
friends.forEach(node -> System.out.println(node.getName()));
should give you the correct result of (order neglected)
B
F
E
Note: Remember that, since its a Set, the resulting nodes can be in any order.
Thanks Glains,
My Code is :
public class Demo {
Set<String> freinds = new HashSet<>();
public static void main(String[] args) {
String[][] emailArray = new String[][] {
{ "abc#gmail.com", "abc1#gmail.com,abc2#gmail.com,abc3#gmail.com,1212#gmail.com" },
{ "abc1#gmail.com", "bcs1#gmail.combc2#gmail.com,bcds3#gmail.com" },
{ "bc#gmail.com", "bc1#gmail.combc2#gmail.com,bc3#gmail.com" } };
new Demo().sendMail("#gmail.combc2#gmail.com", "sdsd", emailArray);
}
void sendMail(String email, String message, String[][] freindsArray) {
Map<String, Email> emailsMap = new HashMap<>();
for (int i = 0; i < freindsArray.length; i++) {
for (int j = 0; j < 1; j++) {
Email e = new Email(freindsArray[i][j]);
e.addConnectedNodes(freindsArray[i][j + 1]);
emailsMap.put(e.email, e);
}
}
if (emailsMap.containsKey(email)) {
Demo.getNodesFollowAllEdges(emailsMap.get(email), emailsMap).forEach(e -> {
System.out.println(e);
});
} else {
System.out.println("no emails exist");
}
}
private static Set<String> getNodesFollowAllEdges(Email e, Map<String, Email> emailsMap) {
Set<String> nodes = getNodesFollowAllEdges(e, new HashSet<>(), emailsMap);
nodes.remove(e.email);
return nodes;
}
private static Set<String> getNodesFollowAllEdges(Email node, Set<String> visited, Map<String, Email> emailsMap) {
if (node.getConnectedEmails().isEmpty()) {
return visited;
}
for (String n : node.getConnectedEmails()) {
if (!visited.contains(n)) {
visited.add(n);
if (emailsMap.get(n) != null) {
getNodesFollowAllEdges(emailsMap.get(n), visited, emailsMap);
}
}
}
return visited;
}
}
class Email {
String email;
List<String> freindsEmails = new ArrayList<>();
public List<String> getConnectedEmails() {
return freindsEmails;
}
public Email(String email) {
this.email = email;
}
public void addConnectedNodes(String friendsEmail) {
freindsEmails.addAll(Arrays.asList(friendsEmail.split(",")));
}
}
I need to union a collection of sets by intersection of sets and write a function with such signature
Collection<Set<Integer>> filter(Collection<Set<Integer>> collection);
Here is a simple example of sets
1) {1,2,3}
2) {4}
3) {1,5}
4) {4,7}
5) {3,5}
In this example we can see that sets 1, 3, and 5 intersect. We can rewrite it as a new set {1,2,3,5}. Also we have two sets that have intersections as well. They're 2 and 4, and we can create a new set {4,7}. The output result will be a collection of two sets: {1,2,3,5} and {4,7}.
I don't know from which point to start solving this task.
This should solve your use-case. It may be implemented in a more efficient way, but I guess this should give you an idea to start with:
private static Collection<Set<Integer>> mergeIntersections(Collection<Set<Integer>> collection) {
Collection<Set<Integer>> processedCollection = mergeIntersectionsInternal(collection);
while (!isMergedSuccessfully(processedCollection)) {
processedCollection = mergeIntersectionsInternal(processedCollection);
}
return processedCollection;
}
private static boolean isMergedSuccessfully(Collection<Set<Integer>> processedCollection) {
if (processedCollection.size() <= 1) {
return true;
}
final Set<Integer> mergedNumbers = new HashSet<>();
int totalNumbers = 0;
for (Set<Integer> set : processedCollection) {
totalNumbers += set.size();
mergedNumbers.addAll(set);
}
if (totalNumbers > mergedNumbers.size()) {
return false;
}
return true;
}
private static Collection<Set<Integer>> mergeIntersectionsInternal(Collection<Set<Integer>> collection) {
final Collection<Set<Integer>> processedCollection = new ArrayList<>();
// ITERATE OVER ALL SETS
for (final Set<Integer> numberSet : collection) {
for (final Integer number : numberSet) {
boolean matched = false;
// ITERATE OVER ALL PROCESSED SETS COLLECTION
for (final Set<Integer> processedSet : processedCollection) {
// CHECK OF THERE IS A MATCH
if (processedSet.contains(number)) {
matched = true;
// MATCH FOUND, MERGE THE SETS
processedSet.addAll(numberSet);
// BREAK OUT OF PROCESSED COLLECTION LOOP
break;
}
}
// IF NOT MATCHED THEN ADD AS A COLLECTION ITEM
if (!matched) {
processedCollection.add(new HashSet<>(numberSet));
}
}
}
return processedCollection;
}
This is how it executed it:
public static void main(String[] args) {
final Collection<Set<Integer>> collection = new ArrayList<>();
final Set<Integer> set1 = new HashSet<>();
set1.add(1);
set1.add(2);
set1.add(3);
collection.add(set1);
final Set<Integer> set2 = new HashSet<>();
set2.add(4);
collection.add(set2);
final Set<Integer> set3 = new HashSet<>();
set3.add(1);
set3.add(5);
collection.add(set3);
final Set<Integer> set4 = new HashSet<>();
set4.add(4);
set4.add(7);
collection.add(set4);
final Set<Integer> set5 = new HashSet<>();
set5.add(3);
set5.add(5);
collection.add(set5);
System.out.println(mergeIntersections(collection));
}
Here’s my go. It deletes all sets from the input collection, this could be easily fixed by making a copy first. It does not modify each set in the input collection. With my implementation Ajay’s main method prints [[1, 2, 3, 5], [4, 7]].
Collection<Set<Integer>> filter(Collection<Set<Integer>> collection) {
Collection<Set<Integer>> mergedSets = new ArrayList<>(collection.size());
// for each set at a time, merge it with all sets that intersect it
while (! collection.isEmpty()) {
// take out the first set; make a copy as not to mutate original sets
Set<Integer> currentSet = new HashSet<>(removeOneElement(collection));
// find all intersecting sets and merge them into currentSet
// the trick is to continue merging until we find no intersecting
boolean mergedAny;
do {
mergedAny = false;
Iterator<Set<Integer>> it = collection.iterator();
while (it.hasNext()) {
Set<Integer> candidate = it.next();
if (intersect(currentSet, candidate)) {
it.remove();
currentSet.addAll(candidate);
mergedAny = true;
}
}
} while (mergedAny);
mergedSets.add(currentSet);
}
return mergedSets;
}
private static Set<Integer> removeOneElement(Collection<Set<Integer>> collection) {
Iterator<Set<Integer>> it = collection.iterator();
Set<Integer> element = it.next();
it.remove();
return element;
}
/** #return true if the sets have at least one element in common */
private static boolean intersect(Set<Integer> leftSet, Set<Integer> rightSet) {
// don’t mutate, take a copy
Set<Integer> copy = new HashSet<>(leftSet);
copy.retainAll(rightSet);
return ! copy.isEmpty();
}
An elegant way to solve this problem is using Undirected Graphs, where you connect an element from an input set with at least one other element from the same set, and then look for the Connected Components.
So the graph representation of your example is:
And from that we can easily infer the Connected Components: {1, 2, 3, 5} and {4, 7}.
Here is my code:
Collection<Set<Integer>> filter(Collection<Set<Integer>> collection) {
// Build the Undirected Graph represented as an adjacency list
Map<Integer, Set<Integer>> adjacents = new HashMap<>();
for (Set<Integer> integerSet : collection) {
if (!integerSet.isEmpty()) {
Iterator<Integer> it = integerSet.iterator();
int node1 = it.next();
while (it.hasNext()) {
int node2 = it.next();
if (!adjacents.containsKey(node1)) {
adjacents.put(node1, new HashSet<>());
}
if (!adjacents.containsKey(node2)) {
adjacents.put(node2, new HashSet<>());
}
adjacents.get(node1).add(node2);
adjacents.get(node2).add(node1);
}
}
}
// Run DFS on each node to collect the Connected Components
Collection<Set<Integer>> result = new ArrayList<>();
Set<Integer> visited = new HashSet<>();
for (int start : adjacents.keySet()) {
if (!visited.contains(start)) {
Set<Integer> resultSet = new HashSet<>();
Deque<Integer> stack = new ArrayDeque<>();
stack.push(start);
while (!stack.isEmpty()) {
int node1 = stack.pop();
visited.add(node1);
resultSet.add(node1);
for (int node2 : adjacents.get(node1)) {
if (!visited.contains(node2)) {
stack.push(node2);
}
}
}
result.add(resultSet);
}
}
return result;
}
IMHO the best solution is Union-Find algorithm
An implemtation:
public class UnionFind {
Set<Integer> all = new HashSet<>();
Set<Integer> representants = new HashSet<>();
Map<Integer, Integer> parents = new HashMap<>();
public void union(int p0, int p1) {
int cp0 = find(p0);
int cp1 = find(p1);
if (cp0 != cp1) {
int size0 = parents.get(cp0);
int size1 = parents.get(cp1);
if (size1 < size0) {
int swap = cp0;
cp0 = cp1;
cp1 = swap;
}
parents.put(cp0, size0 + size1);
parents.put(cp1, cp0);
representants.remove(cp1);
}
}
public int find(int p) {
Integer result = parents.get(p);
if (result == null) {
all.add(p);
parents.put(p, -1);
representants.add(p);
result = p;
} else if (result < 0) {
result = p;
} else {
result = find(result);
parents.put(p, result);
}
return result;
}
public Collection<Set<Integer>> getGroups() {
Map<Integer, Set<Integer>> result = new HashMap<>();
for (Integer representant : representants) {
result.put(representant, new HashSet<>(-parents.get(representant)));
}
for (Integer value : all) {
result.get(find(value)).add(value);
}
return result.values();
}
public static Collection<Set<Integer>> filter(Collection<Set<Integer>> collection) {
UnionFind groups = new UnionFind();
for (Set<Integer> set : collection) {
if (!set.isEmpty()) {
Iterator<Integer> it = set.iterator();
int first = groups.find(it.next());
while (it.hasNext()) {
groups.union(first, it.next());
}
}
}
return groups.getGroups();
}
}
Info = new String[15];
Livraison = new String[5];
Facturation = new String[5];
Autres = new String[3];
Livraison = AddressForm(JP_Add_Livraison,"Livraison");
Facturation = AddressForm(JP_Add_Facturation,"Facturation");
Autres[0] = JT_Tel.getText();
Autres[1] = JT_Contact.getText();
Autres[2] = JT_Date.getText();
Autres[3] = JT_Note.getText();
Info.add(Livraison);
Info.add(Facturation);
Info.add(Autres);
I want the 3 String[] -> Livraison + Facturation + Autres in Info[]
How can I do that ?
Thanks
You'll find it much easier to do this if you work with the standard collections types. In particular, try using List<String>, instead of String[]. Then you'll find that adding mutiple lists to another list is a simple matter of calling the "addAll" method which is designed to copy the elements from one collection to another.
You can create and array of arrays like this:
String[][] arrays = { array1, array2, array3, array4, array5 };
But, alternatively, you could create a class that has those attributes, don't know if that's what you want to do..
public class Something{
String[] Livraison;
String[] Facturation;
String[] Autres;
}
Arrays.copyOf will work for you.
A suggestion - how to do this!
int len1 = newarray.length;
int len2 = arraytobecopied.length;
String[] result = Arrays.copyOf(newarray, len1 + len2);
System.arraycopy(arraytobecopied, 0, result, len1, len2);
public static void main(String[] args) throws Exception {
String[] all = new String[15];
String[] some = new String[] { "one", "two", "three" };
String[] more = new String[] { "four", "five" };
System.arraycopy(some, 0, all, 0, some.length);
System.arraycopy(more, 0, all, some.length, more.length);
for (String value : all) System.out.println(value);
}
Totally over the top unless you need to do this a lot (I do) you may find wrapping the arrays in an Iterable useful.
public class JoinedArray<T> implements Iterable<T> {
final List<T[]> joined;
#SafeVarargs
public JoinedArray(T[]... arrays) {
joined = Arrays.<T[]>asList(arrays);
}
#Override
public Iterator<T> iterator() {
return new JoinedIterator<>(joined);
}
private class JoinedIterator<T> implements Iterator<T> {
// The iterator acrioss the arrays.
Iterator<T[]> i;
// The array I am working on.
T[] a;
// Where we are in it.
int ai;
// The next T to return.
T next = null;
private JoinedIterator(List<T[]> joined) {
i = joined.iterator();
a = i.hasNext() ? i.next() : null;
ai = 0;
}
#Override
public boolean hasNext() {
if (next == null) {
// a goes to null at the end of i.
if (a != null) {
// End of a?
if (ai >= a.length) {
// Yes! Next i.
if (i.hasNext()) {
a = i.next();
} else {
// Finished.
a = null;
}
ai = 0;
}
if (a != null) {
next = a[ai++];
}
}
}
return next != null;
}
#Override
public T next() {
T n = null;
if (hasNext()) {
// Give it to them.
n = next;
next = null;
} else {
// Not there!!
throw new NoSuchElementException();
}
return n;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
}
public int copyTo(T[] to, int offset, int length) {
int copied = 0;
// Walk each of my arrays.
for (T[] a : joined) {
// All done if nothing left to copy.
if (length <= 0) {
break;
}
if (offset < a.length) {
// Copy up to the end or to the limit, whichever is the first.
int n = Math.min(a.length - offset, length);
System.arraycopy(a, offset, to, copied, n);
offset = 0;
copied += n;
length -= n;
} else {
// Skip this array completely.
offset -= a.length;
}
}
return copied;
}
public int copyTo(T[] to, int offset) {
return copyTo(to, offset, to.length);
}
public int copyTo(T[] to) {
return copyTo(to, 0);
}
#Override
public String toString() {
StringBuilder s = new StringBuilder();
Separator comma = new Separator(",");
for (T[] a : joined) {
s.append(comma.sep()).append(Arrays.toString(a));
}
return s.toString();
}
public static void main(String[] args) {
JoinedArray<String> a = new JoinedArray<>(
new String[]{
"One"
},
new String[]{
"Two",
"Three",
"Four",
"Five"
},
new String[]{
"Six",
"Seven",
"Eight",
"Nine"
});
for (String s : a) {
System.out.println(s);
}
String[] four = new String[4];
int copied = a.copyTo(four, 3, 4);
System.out.println("Copied " + copied + " = " + Arrays.toString(four));
}
}
Note that the arrays are used to back the lists internally so if you change the arrays the joined versions also change. Obviously if the arrays get resized then that will break the connection.
ask yourself question : do i really need arrays?
based on your code sample:(which actually shoulnd work as you declare length of Autres 3 and add 4 elements)
Autres[0] = JT_Tel.getText();
Autres[1] = JT_Contact.getText();
Autres[2] = JT_Date.getText();
Autres[3] = JT_Note.getText();
i recommend you to go with object Autres
class Autres{
private String tel,contact,date,note;
//getters and setters ommited
}
I have 2 Strings:
A1=[Rettangolo, Quadrilatero, Rombo, Quadrato]
A2=[Rettangolo, Rettangolo, Rombo, Quadrato]
I want to obtain this: "I have found "Quadrilatero", instead of "Rettangolo" ".
If I use removeAll() or retainAll() it doesn't work because I have 2 instances of "Rettangolo".
In fact, if I use a1.containsAll(a2), I get true and I want false.
Thanks all for considering my request.
Use the remove method from ArrayList. It only removes the first occurance.
public static void main(String []args){
//Create ArrayLists
String[] A1 = {"Rettangolo", "Quadrilatero", "Rombo", "Quadrato"};
ArrayList<String> a1=new ArrayList(Arrays.asList(A1));
String[] A2 ={"Rettangolo", "Rettangolo", "Rombo", "Quadrato"};
ArrayList<String> a2=new ArrayList(Arrays.asList(A2));
// Check ArrayLists
System.out.println("a1 = " + a1);
System.out.println("a2 = " + a2);
// Find difference
for( String s : a1)
a2.remove(s);
// Check difference
System.out.println("a1 = " + a1);
System.out.println("a2 = " + a2);
}
Result
a1 = [Rettangolo, Quadrilatero, Rombo, Quadrato]
a2 = [Rettangolo, Rettangolo, Rombo, Quadrato]
a1 = [Rettangolo, Quadrilatero, Rombo, Quadrato]
a2 = [Rettangolo]
These two classes might help. Let me know how I can improve this further.
Feel free to use the code below in your own work.
I must point out that the current code does not take care of repeated list elements.
import java.util.List;
public class ListDiff<T> {
private List<T> removed;
private List<T> added;
public ListDiff(List<T> removed, List<T> added) {
super();
this.removed = removed;
this.added = added;
}
public ListDiff() {
super();
}
public List<T> getRemoved() {
return removed;
}
public List<T> getAdded() {
return added;
}
}
Util class.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class ListUtil {
public static <T> ListDiff<T> diff(List<T> one, List<T> two) {
List<T> removed = new ArrayList<T>();
List<T> added = new ArrayList<T>();
for (int i = 0; i < one.size(); i++) {
T elementOne = one.get(i);
if (!two.contains(elementOne)) {
//element in one is removed from two
removed.add(elementOne);
}
}
for (int i = 0; i < two.size(); i++) {
T elementTwo = two.get(i);
if (!one.contains(elementTwo)) {
//element in two is added.
added.add(elementTwo);
}
}
return new ListDiff<T>(removed, added);
}
public static <T> ListDiff<T> diff(List<T> one, List<T> two, Comparator<T> comparator) {
List<T> removed = new ArrayList<T>();
List<T> added = new ArrayList<T>();
for (int i = 0; i < one.size(); i++) {
T elementOne = one.get(i);
boolean found = false;
//loop checks if element in one is found in two.
for (int j = 0; j < two.size(); j++) {
T elementTwo = two.get(j);
if (comparator.compare(elementOne, elementTwo) == 0) {
found = true;
break;
}
}
if (found == false) {
//element is not found in list two. it is removed.
removed.add(elementOne);
}
}
for (int i = 0; i < two.size(); i++) {
T elementTwo = two.get(i);
boolean found = false;
//loop checks if element in two is found in one.
for (int j = 0; j < one.size(); j++) {
T elementOne = one.get(j);
if (comparator.compare(elementTwo, elementOne) == 0) {
found = true;
break;
}
}
if (found == false) {
//it means element has been added to list two.
added.add(elementTwo);
}
}
return new ListDiff<T>(removed, added);
}
public static void main(String args[]) {
String[] arr1 = { "london", "newyork", "delhi", "singapore", "tokyo", "amsterdam" };
String[] arr2 = { "london", "newyork", "delhi", "singapore", "seoul", "bangalore", "oslo" };
ListDiff<String> ld = ListUtil.diff(Arrays.asList(arr1), Arrays.asList(arr2));
System.out.println(ld.getRemoved());
System.out.println(ld.getAdded());
ld = ListUtil.diff(Arrays.asList(arr1), Arrays.asList(arr2), new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
}); //sample for using custom comparator
System.out.println(ld.getRemoved());
System.out.println(ld.getAdded());
}
}
Here are three solutions.
An implementation that uses a remove method.
public static boolean same(List<String> list1, List<String> list2){
if (list1.size() != list2.size())
return false;
List<String> temp = new ArrayList<String>(list1);
temp.removeAll(list2);
return temp.size() == 0;
}
A solution that sorts then compares.
public static boolean same(List<String> list1, List<String> list2){
if (list1.size() != list2.size())
return false;
Collections.sort(list1);
Collections.sort(list2);
for (int i=0;i<list1.size();i++){
if (!list1.get(i).equals(list2.get(i)))
return false;
}
return true;
}
And, just for fun, you could do this by doing a word count difference between the two arrays. It wouldn't be the most efficient, but it works and possibly could be useful.
public static boolean same(List<String> list1, List<String> list2){
Map<String,Integer> counts = new HashMap<String,Integer>();
for (String str : list1){
Integer i = counts.get(str);
if (i==null)
counts.put(str, 1);
else
counts.put(str, i+1);
}
for (String str : list2){
Integer i = counts.get(str);
if (i==null)
return false; /// found an element that's not in the other
else
counts.put(str, i-1);
}
for (Entry<String,Integer> entry : counts.entrySet()){
if (entry.getValue() != 0)
return false;
}
return true;
}
This will find the intersection between two arrays for this specific case you have explained.
String[] A1 = { "Rettangolo", "Quadrilatero", "Rombo", "Quadrato" };
String[] A2 = { "Rettangolo", "Rettangolo", "Rombo", "Quadrato" };
ArrayList<String> a1 = new ArrayList<String>(Arrays.asList(A1));
ArrayList<String> a2 = new ArrayList<String>(Arrays.asList(A2));
a1.removeAll(a2);
System.out.println("I have found " + a1);
I hope this will help you
String[] A1 = {"Rettangolo", "Quadrilatero", "Rombo", "Quadrato"};
String[] A2 ={"Rettangolo", "Rettangolo", "Rombo", "Quadrato"};
Set<String> set1 = new HashSet<String>();
Set<String> set2 = new HashSet<String>();
set1.addAll(Arrays.asList(A1));
set2.addAll(Arrays.asList(A2));
set1.removeAll(set2);
System.out.println(set1);// ==> [Quadrilatero]